Skip to content

Commit 4baba5a

Browse files
committed
Enable/optimize NonEmpty traversals
1 parent 28d6e4f commit 4baba5a

File tree

2 files changed

+32
-14
lines changed

2 files changed

+32
-14
lines changed

src/FSharpPlus/Control/Traversable.fs

+13-14
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ type ParSequence =
254254
static member inline InvokeOnInstance (t: '``ParTraversable<'Functor<'T>>``) = (^``ParTraversable<'Functor<'T>>`` : (static member ParSequence : _ -> _) t) : '``Functor<'ParTraversable<'T>>``
255255

256256
[<EditorBrowsable(EditorBrowsableState.Never)>]
257-
static member inline ForInfiniteSequences (t: seq<_>, isFailure, conversion) =
257+
static member inline ForInfiniteSequences (t: seq<_>, [<InlineIfLambda>]isFailure, [<InlineIfLambda>]conversion, [<InlineIfLambda>]result) =
258258
let add x y = y :: x
259259
let mutable go = true
260260
let mutable r = Unchecked.defaultof<_>
@@ -265,7 +265,7 @@ type ParSequence =
265265
if isEmpty then r <- Map.Invoke List.singleton e.Current
266266
else r <- Map.Invoke add r </> e.Current
267267
isEmpty <- false
268-
if isEmpty then ParReturn.Invoke (conversion [])
268+
if isEmpty then result (conversion [])
269269
else Map.Invoke (List.rev >> conversion) r
270270

271271
type ParTraverse =
@@ -306,14 +306,14 @@ type ParTraverse =
306306
Traces.add "ParTraverse seq, 'T -> Functor<'U>"
307307
#endif
308308
let mapped = Seq.map f t
309-
ParSequence.ForInfiniteSequences (mapped, IsParLeftZero.Invoke, List.toSeq) : '``Functor<seq<'U>>``
309+
ParSequence.ForInfiniteSequences (mapped, IsParLeftZero.Invoke, List.toSeq, Return.Invoke) : '``Functor<seq<'U>>``
310310

311311
static member inline ParTraverse (t: NonEmptySeq<'T>, f: 'T -> '``Functor<'U>``, [<Optional>]_output: '``Functor<NonEmptySeq<'U>>``, [<Optional>]_impl: Default2) =
312312
#if TEST_TRACE
313313
Traces.add "ParTraverse NonEmptySeq, 'T -> Functor<'U>"
314314
#endif
315315
let mapped = NonEmptySeq.map f t
316-
ParSequence.ForInfiniteSequences (mapped, IsParLeftZero.Invoke, NonEmptySeq.ofList) : '``Functor<NonEmptySeq<'U>>``
316+
ParSequence.ForInfiniteSequences (mapped, IsParLeftZero.Invoke, NonEmptySeq.ofList, Return.Invoke) : '``Functor<NonEmptySeq<'U>>``
317317

318318
static member inline ParTraverse (t: ^a, f, [<Optional>]_output: 'R, [<Optional>]_impl: Default1) : 'R =
319319
#if TEST_TRACE
@@ -429,26 +429,25 @@ type ParSequence with
429429
Seq.foldBack cons_f t (ParReturn.Invoke Seq.empty)
430430

431431
static member inline ParSequence (t: seq<'``Applicative<'T>``>, [<Optional>]_output: '``Applicative<seq<'T>>`` , [<Optional>]_impl: Default4) : '``Applicative<seq<'T>>`` =
432-
ParSequence.ForInfiniteSequences (t, IsParLeftZero.Invoke, List.toSeq)
432+
ParSequence.ForInfiniteSequences (t, IsParLeftZero.Invoke, List.toSeq, ParReturn.Invoke)
433433

434434
static member ParSequence (t: seq<option<'t>> , [<Optional>]_output: option<seq<'t>> , [<Optional>]_impl: Default3) : option<seq<'t>> = Option.Sequence t
435435
#if !FABLE_COMPILER
436436
static member ParSequence (t: seq<voption<'t>> , [<Optional>]_output: voption<seq<'t>> , [<Optional>]_impl: Default3) : voption<seq<'t>> = ValueOption.Sequence t
437437
#endif
438438
static member inline ParSequence (t: seq<Result<'t,'e>>, [<Optional>]_output: Result<seq<'t>, 'e>, [<Optional>]_impl: Default3) : Result<seq<'t>, 'e> = Result.Parallel ((++), t)
439439
static member inline ParSequence (t: seq<Choice<'t,'e>>, [<Optional>]_output: Choice<seq<'t>, 'e>, [<Optional>]_impl: Default3) : Choice<seq<'t>, 'e> = Choice.Parallel ((++), t)
440-
static member ParSequence (t: seq<list<'t>> , [<Optional>]_output: list<seq<'t>> , [<Optional>]_impl: Default3) : list<seq<'t>> = ParSequence.ForInfiniteSequences (t, List.isEmpty, List.toSeq)
441-
// static member ParSequence (t: seq<'t []> , [<Optional>]_output: seq<'t> [] , [<Optional>]_impl: Default3) : seq<'t> [] = ParSequence.ForInfiniteSequences (t, Array.isEmpty, List.toSeq)
440+
static member ParSequence (t: seq<list<'t>> , [<Optional>]_output: list<seq<'t>> , [<Optional>]_impl: Default3) : list<seq<'t>> = ParSequence.ForInfiniteSequences (t, List.isEmpty, List.toSeq, List.singleton >> List.cycle)
442441

443442
#if !FABLE_COMPILER
444443
static member ParSequence (t: seq<Async<'t>> , [<Optional>]_output: Async<seq<'t>> , [<Optional>]_impl: Default3) : Async<seq<'t>> = Async.Parallel t |> Async.map Array.toSeq
445444
#endif
446-
static member inline ParSequence (t: NonEmptySeq<'``Applicative<'T>``>, [<Optional>]_output: '``Applicative<NonEmptySeq<'T>>`` , [<Optional>]_impl: Default4) : '``Applicative<NonEmptySeq<'T>>`` = ParSequence.ForInfiniteSequences (t, IsParLeftZero.Invoke, NonEmptySeq.ofList)
445+
static member inline ParSequence (t: NonEmptySeq<'``Applicative<'T>``>, [<Optional>]_output: '``Applicative<NonEmptySeq<'T>>``, [<Optional>]_impl: Default4) : '``Applicative<NonEmptySeq<'T>>`` = ParSequence.ForInfiniteSequences (t, IsParLeftZero.Invoke, NonEmptySeq.ofList, fun _ -> Unchecked.defaultof<_>)
447446
static member ParSequence (t: NonEmptySeq<option<'t>> , [<Optional>]_output: option<NonEmptySeq<'t>> , [<Optional>]_impl: Default3) : option<NonEmptySeq<'t>> = Option.Sequence t |> Option.map NonEmptySeq.unsafeOfSeq
448447
static member inline ParSequence (t: NonEmptySeq<Result<'t,'e>>, [<Optional>]_output: Result<NonEmptySeq<'t>, 'e>, [<Optional>]_impl: Default3) : Result<NonEmptySeq<'t>, 'e> = Result.Parallel ((++), t) |> Result.map NonEmptySeq.unsafeOfSeq
449448
static member inline ParSequence (t: NonEmptySeq<Choice<'t,'e>>, [<Optional>]_output: Choice<NonEmptySeq<'t>, 'e>, [<Optional>]_impl: Default3) : Choice<NonEmptySeq<'t>, 'e> = Choice.Parallel ((++), t) |> Choice.map NonEmptySeq.unsafeOfSeq
450-
static member ParSequence (t: NonEmptySeq<list<'t>> , [<Optional>]_output: list<NonEmptySeq<'t>> , [<Optional>]_impl: Default3) : list<NonEmptySeq<'t>> = ParSequence.ForInfiniteSequences(t, List.isEmpty , NonEmptySeq.ofList)
451-
// static member ParSequence (t: NonEmptySeq<'t []> , [<Optional>]_output: NonEmptySeq<'t> [] , [<Optional>]_impl: Default3) : NonEmptySeq<'t> [] = ParSequence.ForInfiniteSequences(t, Array.isEmpty, NonEmptySeq.ofList)
449+
static member ParSequence (t: NonEmptySeq<list<'t>> , [<Optional>]_output: list<NonEmptySeq<'t>> , [<Optional>]_impl: Default3) : list<NonEmptySeq<'t>> = ParSequence.ForInfiniteSequences (t, List.isEmpty , NonEmptySeq.ofList, fun _ -> Unchecked.defaultof<_>)
450+
static member ParSequence (t: NonEmptySeq<'t []> , [<Optional>]_output: NonEmptySeq<'t> [] , [<Optional>]_impl: Default3) : NonEmptySeq<'t> [] = ParSequence.ForInfiniteSequences (t, Array.isEmpty, NonEmptySeq.ofList, fun _ -> Unchecked.defaultof<_>)
452451
#if !FABLE_COMPILER
453452
static member ParSequence (t: NonEmptySeq<Async<'t>> , [<Optional>]_output: Async<NonEmptySeq<'t>> , [<Optional>]_impl: Default3) = Async.Parallel t |> Async.map NonEmptySeq.unsafeOfSeq : Async<NonEmptySeq<'t>>
454453
#endif
@@ -460,7 +459,7 @@ type ParSequence with
460459
#if !FABLE_COMPILER
461460
static member inline ParSequence (t: voption<_>, [<Optional>]_output: 'R, [<Optional>]_impl: ParSequence) : 'R = match t with ValueSome x -> Map.Invoke ValueSome x | _ -> ParReturn.Invoke ValueNone
462461
#endif
463-
static member inline ParSequence (t: list<_> , [<Optional>]_output: 'R, [<Optional>]_impl: ParSequence) : 'R = ParSequence.ForInfiniteSequences(t, IsParLeftZero.Invoke, id)
462+
static member inline ParSequence (t: list<_> , [<Optional>]_output: 'R, [<Optional>]_impl: ParSequence) : 'R = ParSequence.ForInfiniteSequences (t, IsParLeftZero.Invoke, id, ParReturn.Invoke)
464463

465464
static member inline ParSequence (t: Map<_,_> , [<Optional>]_output: 'R, [<Optional>]_impl: ParSequence) : 'R =
466465
let insert_f k x ys = Map.Invoke (Map.add k) x </> ys
@@ -476,11 +475,11 @@ type ParSequence with
476475
| Choice1Of2 a -> Map.Invoke Choice<'T,'Error>.Choice1Of2 a
477476
| Choice2Of2 e -> ParReturn.Invoke (Choice<'T,'Error>.Choice2Of2 e)
478477

479-
static member inline ParSequence (t: _ [] , [<Optional>]_output: 'R , [<Optional>]_impl: ParSequence) : 'R = ParSequence.ForInfiniteSequences(t, IsParLeftZero.Invoke, Array.ofList)
478+
static member inline ParSequence (t: _ [] , [<Optional>]_output: 'R , [<Optional>]_impl: ParSequence) : 'R = ParSequence.ForInfiniteSequences (t, IsParLeftZero.Invoke, Array.ofList, ParReturn.Invoke)
480479

481-
static member inline ParSequence (t: Id<'``Functor<'T>``> , [<Optional>]_output: '``Functor<Id<'T>>`` , [<Optional>]_impl: ParSequence) : '``Functor<Id<'T>>`` = ParTraverse.Invoke id t
480+
static member inline ParSequence (t: Id<'``Functor<'T>``> , [<Optional>]_output: '``Functor<Id<'T>>`` , [<Optional>]_impl: ParSequence) : '``Functor<Id<'T>>`` = ParTraverse.Invoke id t
482481

483-
static member inline ParSequence (t: ResizeArray<'``Functor<'T>``>, [<Optional>]_output: '``Functor<ResizeArray<'T>>`` , [<Optional>]_impl: ParSequence) : '``Functor<ResizeArray<'T>>``= ParTraverse.Invoke id t
482+
static member inline ParSequence (t: ResizeArray<'``Functor<'T>``>, [<Optional>]_output: '``Functor<ResizeArray<'T>>``, [<Optional>]_impl: ParSequence) : '``Functor<ResizeArray<'T>>``= ParTraverse.Invoke id t
484483

485484
static member inline Invoke (t: '``ParTraversable<'Applicative<'T>>``) : '``Applicative<'ParTraversable<'T>>`` =
486485
let inline call_3 (a: ^a, b: ^b, c: ^c) = ((^a or ^b or ^c) : (static member ParSequence : _*_*_ -> _) b, c, a)

src/FSharpPlus/Data/NonEmptyList.fs

+19
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,18 @@ module NonEmptyList =
148148
/// </summary>
149149
let inline sequence (source: NonEmptyList<'``Functor<'T>``>) : '``Functor<NonEmptyList<'T>>`` = traverse id source
150150

151+
/// <summary>
152+
/// Maps each element of the list to an action, evaluates these actions from left to right, pointwise, and/or in parallel, and collect the results.
153+
/// </summary>
154+
let inline ptraverse (f: 'T -> '``Functor<'U>``) (source: NonEmptyList<'T>) =
155+
ParSequence.ForInfiniteSequences (Seq.map f source, IsParLeftZero.Invoke, ofList, fun _ -> invalidOp "Unreacheable code.")
156+
157+
/// <summary>
158+
/// Evaluates each action in the list from left to right, pointwise, and/or in parallel and collect the results.
159+
/// </summary>
160+
let inline psequence (source: NonEmptyList<'``Functor<'T>``>) : '``Functor<NonEmptyList<'T>>`` =
161+
ParSequence.ForInfiniteSequences (source, IsParLeftZero.Invoke, ofList, fun _ -> invalidOp "Unreacheable code.")
162+
151163
#endif
152164

153165
/// <summary>Returns the average of the elements in the list.</summary>
@@ -251,6 +263,7 @@ type NonEmptyList<'t> with
251263
let r = NonEmptyList.toList f </List.apply/> NonEmptyList.toList x
252264
{Head = r.Head; Tail = r.Tail}
253265

266+
static member ParReturn (x: 'a) = { Head = x; Tail = List.cycle [x] }
254267
static member (</>) (f: NonEmptyList<'T->'U>, x: NonEmptyList<'T>) = NonEmptyList.map2Shortest (<|) f x
255268

256269
static member Lift2 (f: 'T -> 'U -> 'V, x, y) = NonEmptyList.ofList (List.lift2 f (NonEmptyList.toList x) (NonEmptyList.toList y))
@@ -290,6 +303,12 @@ type NonEmptyList<'t> with
290303
[<EditorBrowsable(EditorBrowsableState.Never)>]
291304
static member inline Sequence (s: NonEmptyList<'``Functor<'T>``>) : '``Functor<NonEmptyList<'T>>`` = NonEmptyList.sequence s
292305

306+
[<EditorBrowsable(EditorBrowsableState.Never)>]
307+
static member inline ParTraverse (s: NonEmptyList<'T>, f: 'T -> '``Functor<'U>``) : '``Functor<NonEmptyList<'U>>`` = NonEmptyList.ptraverse f s
308+
309+
[<EditorBrowsable(EditorBrowsableState.Never)>]
310+
static member inline ParSequence (s: NonEmptyList<'``Functor<'T>``>) : '``Functor<NonEmptyList<'T>>`` = NonEmptyList.psequence s
311+
293312
static member Replace (source: NonEmptyList<'T>, oldValue: NonEmptyList<'T>, newValue: NonEmptyList<'T>, _impl: Replace ) =
294313
let lst = source |> NonEmptyList.toSeq |> Seq.replace oldValue newValue |> Seq.toList
295314
{Head = lst.Head; Tail = lst.Tail}

0 commit comments

Comments
 (0)