diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 449bd88dc..b86199435 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -67,7 +67,7 @@ We should add as much concrete implementations for primitive types (types coming #### Defaults -The goal of default implementations is to allow users of the library to write less code, as an example we expect the user will add `Bind` , `Return` to their specific monad types, but we don't want to force him to add `Join` although if he adds it, code might be more efficient. +The goal of default implementations is to allow users of the library to write less code, as an example we expect the user will add `Bind` , `Return` to their specific monad types, but we don't want to force them to add `Join` although if they do, code might be more efficient. But those defaults are not intended to be used by developers of F#+ as we should afford writing more code in order to maximize usability of the library. You can read this as "the principle is to allow user to write less boilerplate, and because of that we have to put some boilerplate inside F#+". #### Invoker diff --git a/src/FSharpPlus/Control/Traversable.fs b/src/FSharpPlus/Control/Traversable.fs index 40e276cf1..7c33a2e00 100644 --- a/src/FSharpPlus/Control/Traversable.fs +++ b/src/FSharpPlus/Control/Traversable.fs @@ -11,22 +11,20 @@ open FSharpPlus.Internals.Prelude open FSharpPlus.Internals.MonadOps open FSharpPlus.Extensions - type Sequence = inherit Default1 static member inline InvokeOnInstance (t: '``Traversable>``) = (^``Traversable>`` : (static member Sequence : _ -> _) t) : '``Functor<'Traversable<'T>>`` - + [] static member inline ForInfiniteSequences (t: seq<_>, isFailure, conversion) = - let add x y = y :: x - let mutable go = true - let mutable r = result [] - use e = t.GetEnumerator () - while go && e.MoveNext () do - if isFailure e.Current then go <- false - r <- Map.Invoke add r <*> e.Current - Map.Invoke (List.rev >> conversion) r - + let add x y = y :: x + let mutable go = true + let mutable r = result [] + use e = t.GetEnumerator () + while go && e.MoveNext () do + if isFailure e.Current then go <- false + r <- Map.Invoke add r <*> e.Current + Map.Invoke (List.rev >> conversion) r type Traverse = inherit Default1 @@ -187,12 +185,12 @@ type Sequence with Seq.foldBack cons_f t (result Seq.empty) static member inline Sequence (t: seq<'``Applicative<'T>``>, []_output: '``Applicative>`` , []_impl: Default4) = Sequence.ForInfiniteSequences (t, IsLeftZero.Invoke, List.toSeq) : '``Applicative>`` - static member Sequence (t: seq> , []_output: option> , []_impl: Default3) = Sequence.ForInfiniteSequences(t, Option.isNone, List.toSeq) : option> + static member Sequence (t: seq> , []_output: option> , []_impl: Default3) = Option.Sequence t : option> #if !FABLE_COMPILER - static member Sequence (t: seq> , []_output: voption> , []_impl: Default3) = Sequence.ForInfiniteSequences(t, ValueOption.isNone, List.toSeq) : voption> + static member Sequence (t: seq> , []_output: voption> , []_impl: Default3) = ValueOption.Sequence t : voption> #endif - static member Sequence (t: seq>, []_output: Result, 'e>, []_impl: Default3) = Sequence.ForInfiniteSequences(t, (function Error _ -> true | _ -> false), List.toSeq) : Result, 'e> - static member Sequence (t: seq>, []_output: Choice, 'e>, []_impl: Default3) = Sequence.ForInfiniteSequences(t, (function Choice2Of2 _ -> true | _ -> false), List.toSeq) : Choice, 'e> + static member Sequence (t: seq>, []_output: Result, 'e>, []_impl: Default3) = Result.Sequence t : Result, 'e> + static member Sequence (t: seq>, []_output: Choice, 'e>, []_impl: Default3) = Choice.Sequence t : Choice, 'e> static member Sequence (t: seq> , []_output: list> , []_impl: Default3) = Sequence.ForInfiniteSequences(t, List.isEmpty, List.toSeq) : list> static member Sequence (t: seq<'t []> , []_output: seq<'t> [] , []_impl: Default3) = Sequence.ForInfiniteSequences(t, Array.isEmpty, List.toSeq) : seq<'t> [] @@ -200,9 +198,9 @@ type Sequence with static member Sequence (t: seq> , []_output: Async> , []_impl: Default3) = Async.Sequence t : Async> #endif static member inline Sequence (t: NonEmptySeq<'``Applicative<'T>``>, []_output: '``Applicative>`` , []_impl: Default4) = Sequence.ForInfiniteSequences (t, IsLeftZero.Invoke, NonEmptySeq.ofList) : '``Applicative>`` - static member Sequence (t: NonEmptySeq> , []_output: option> , []_impl: Default3) = Sequence.ForInfiniteSequences(t, Option.isNone, NonEmptySeq.ofList) : option> - static member Sequence (t: NonEmptySeq>, []_output: Result, 'e>, []_impl: Default3) = Sequence.ForInfiniteSequences(t, (function Error _ -> true | _ -> false), NonEmptySeq.ofList) : Result, 'e> - static member Sequence (t: NonEmptySeq>, []_output: Choice, 'e>, []_impl: Default3) = Sequence.ForInfiniteSequences(t, (function Choice2Of2 _ -> true | _ -> false), NonEmptySeq.ofList) : Choice, 'e> + static member Sequence (t: NonEmptySeq> , []_output: option> , []_impl: Default3) = Option.Sequence t |> Option.map NonEmptySeq.unsafeOfSeq : option> + static member Sequence (t: NonEmptySeq>, []_output: Result, 'e>, []_impl: Default3) = Result.Sequence t |> Result.map NonEmptySeq.unsafeOfSeq : Result, 'e> + static member Sequence (t: NonEmptySeq>, []_output: Choice, 'e>, []_impl: Default3) = Choice.Sequence t |> Choice.map NonEmptySeq.unsafeOfSeq : Choice, 'e> static member Sequence (t: NonEmptySeq> , []_output: list> , []_impl: Default3) = Sequence.ForInfiniteSequences(t, List.isEmpty, NonEmptySeq.ofList) : list> static member Sequence (t: NonEmptySeq<'t []> , []_output: NonEmptySeq<'t> [] , []_impl: Default3) = Sequence.ForInfiniteSequences(t, Array.isEmpty, NonEmptySeq.ofList) : NonEmptySeq<'t> [] #if !FABLE_COMPILER diff --git a/src/FSharpPlus/Extensions/Extensions.fs b/src/FSharpPlus/Extensions/Extensions.fs index c01ceaa0f..35920bd20 100644 --- a/src/FSharpPlus/Extensions/Extensions.fs +++ b/src/FSharpPlus/Extensions/Extensions.fs @@ -148,7 +148,8 @@ module Extensions = if noneFound then None else - Some (accumulator.Close () |> Array.toSeq) + let res = accumulator.Close () + if res.Length = 0 then None else Some res #endif type ValueOption<'t> with