diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 3c257a01..47362a3d 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -1,30 +1,34 @@ { - "version": 1, - "isRoot": true, - "tools": { - "paket": { - "version": "8.0.3", - "commands": [ - "paket" - ] - }, - "fable": { - "version": "4.4.0", - "commands": [ - "fable" - ] - }, - "fantomas": { - "version": "6.0.0-alpha-010", - "commands": [ - "fantomas" - ] - }, - "femto": { - "version": "0.19.0", - "commands": [ - "femto" - ] - } + "version": 1, + "isRoot": true, + "tools": { + "paket": { + "version": "8.0.3", + "commands": [ + "paket" + ], + "rollForward": false + }, + "fable": { + "version": "4.4.0", + "commands": [ + "fable" + ], + "rollForward": false + }, + "fantomas": { + "version": "6.3.16", + "commands": [ + "fantomas" + ], + "rollForward": false + }, + "femto": { + "version": "0.19.0", + "commands": [ + "femto" + ], + "rollForward": false } + } } \ No newline at end of file diff --git a/.fantomasignore b/.fantomasignore index e01fb49a..bbf3b17b 100644 --- a/.fantomasignore +++ b/.fantomasignore @@ -1 +1,3 @@ AssemblyInfo.fs +tests/FsToolkit.ErrorHandling.AsyncSeq.Tests/Main.fs +tests/FsToolkit.ErrorHandling.Tests/Main.fs diff --git a/benchmarks/Benchmarks.fs b/benchmarks/Benchmarks.fs index 778d0460..4ea1a175 100644 --- a/benchmarks/Benchmarks.fs +++ b/benchmarks/Benchmarks.fs @@ -304,10 +304,8 @@ type ResultBuilder() = member this.Zero() : Result = this.Return() member _.Bind - ( - result: Result<'T, 'TError>, - binder: 'T -> Result<'U, 'TError> - ) : Result<'U, 'TError> = + (result: Result<'T, 'TError>, binder: 'T -> Result<'U, 'TError>) + : Result<'U, 'TError> = Result.bind binder result @@ -319,10 +317,8 @@ type ResultBuilderInlined() = member inline this.Zero() : Result = this.Return() member inline _.Bind - ( - result: Result<'T, 'TError>, - binder: 'T -> Result<'U, 'TError> - ) : Result<'U, 'TError> = + (result: Result<'T, 'TError>, binder: 'T -> Result<'U, 'TError>) + : Result<'U, 'TError> = Result.Inlined.bind binder result type ResultBuilderInlinedLambda() = @@ -331,10 +327,8 @@ type ResultBuilderInlinedLambda() = member inline this.Zero() : Result = this.Return() member inline _.Bind - ( - result: Result<'T, 'TError>, - [] binder: 'T -> Result<'U, 'TError> - ) : Result<'U, 'TError> = + (result: Result<'T, 'TError>, [] binder: 'T -> Result<'U, 'TError>) + : Result<'U, 'TError> = Result.Alt.InlinedLambda.bind binder result diff --git a/build/build.fs b/build/build.fs index 7b62ef75..fd686a60 100644 --- a/build/build.fs +++ b/build/build.fs @@ -152,7 +152,9 @@ let checkFormatCode _ = elif result.ExitCode = 99 then failwith "Some files need formatting, check output for more info" else - Trace.logf "Errors while formatting: %A" result.Errors + let msg = sprintf "Errors while formatting: %A" result.Errors + Trace.log msg + failwith msg let clean _ = diff --git a/playground.fsx b/playground.fsx index f3772be8..3efbec6d 100644 --- a/playground.fsx +++ b/playground.fsx @@ -5,6 +5,7 @@ let inline id x = x open FsToolkit.ErrorHandling Result.ofChoice + module Operators = let inline bindM builder m ([] f) = @@ -167,7 +168,6 @@ module AsyncResult = } - module DisposableOptionThings = open System open System.Threading.Tasks @@ -177,16 +177,23 @@ module DisposableOptionThings = [] [] type DisposableOption<'a when 'a :> IDisposable> = - | None - | Some of 'a + | None + | Some of 'a + interface IDisposable with member this.Dispose() = match this with | None -> () | Some x -> x.Dispose() - static member inline OfObj<'a when 'a :> IDisposable> (x: 'a) = - if box x |> isNull then None else Some x + static member inline OfObj<'a when 'a :> IDisposable>(x: 'a) = + if + box x + |> isNull + then + None + else + Some x static member inline ToOption(x: DisposableOption<'a>) = match x with @@ -198,30 +205,25 @@ module DisposableOptionThings = | None -> ValueOption.None | Some x -> ValueOption.Some x - static member inline OfOption (x: 'a Option) = + static member inline OfOption(x: 'a Option) = match x with | Option.None -> None | Option.Some x -> Some x - static member inline OfValueOption (x: 'a ValueOption) = + static member inline OfValueOption(x: 'a ValueOption) = match x with | ValueNone -> None | ValueSome x -> Some x - static member inline op_Implicit (x: 'a) = - DisposableOption.OfObj x + static member inline op_Implicit(x: 'a) = DisposableOption.OfObj x - static member inline op_Implicit (x: 'a DisposableOption) = - DisposableOption.ToOption x + static member inline op_Implicit(x: 'a DisposableOption) = DisposableOption.ToOption x - static member inline op_Implicit (x: 'a DisposableOption) = - DisposableOption.ToValueOption x + static member inline op_Implicit(x: 'a DisposableOption) = DisposableOption.ToValueOption x - static member inline op_Implicit (x: 'a Option) = - DisposableOption.OfOption x + static member inline op_Implicit(x: 'a Option) = DisposableOption.OfOption x - static member inline op_Imp licit (x: 'a ValueOption) = - DisposableOption.OfValueOption x + static member inline op_Imp licit (x: 'a ValueOption) = DisposableOption.OfValueOption x [] @@ -230,10 +232,12 @@ module DisposableOptionThings = match x with | DisposableOption.Some x -> f x | DisposableOption.None -> None + let inline map f x = match x with - | DisposableOption.Some x -> Some (f x) + | DisposableOption.Some x -> Some(f x) | DisposableOption.None -> None + let inline iter f x = match x with | DisposableOption.Some x -> f x @@ -242,16 +246,23 @@ module DisposableOptionThings = [] type AsyncDisposableOption<'a when 'a :> IAsyncDisposable> = - | Some of 'a - | None + | Some of 'a + | None + interface IAsyncDisposable with member this.DisposeAsync() = match this with | Some x -> x.DisposeAsync() | None -> ValueTask() - static member inline ofObj (x: 'a) = - if box x |> isNull then None else Some x + static member inline ofObj(x: 'a) = + if + box x + |> isNull + then + None + else + Some x member inline x.toOption() = match x with @@ -263,43 +274,47 @@ module DisposableOptionThings = | Some x -> ValueOption.Some x | None -> ValueOption.None - static member inline ofOption (x: 'a Option) = + static member inline ofOption(x: 'a Option) = match x with | Option.Some x -> Some x | Option.None -> None - static member inline ofValueOption (x: 'a ValueOption) = + static member inline ofValueOption(x: 'a ValueOption) = match x with | ValueOption.ValueSome x -> Some x | ValueOption.ValueNone -> None - static member inline op_Implicit (x: 'a) = - AsyncDisposableOption.ofObj x + static member inline op_Implicit(x: 'a) = AsyncDisposableOption.ofObj x - static member inline op_Implicit (x: 'a AsyncDisposableOption) = - x.toOption() + static member inline op_Implicit(x: 'a AsyncDisposableOption) = x.toOption () - static member inline op_Implicit (x: 'a AsyncDisposableOption) = - x.toValueOption() + static member inline op_Implicit(x: 'a AsyncDisposableOption) = x.toValueOption () - static member inline op_Implicit (x: 'a Option) = - AsyncDisposableOption.ofOption x + static member inline op_Implicit(x: 'a Option) = AsyncDisposableOption.ofOption x - static member inline op_Implicit (x: 'a ValueOption) = - AsyncDisposableOption.ofValueOption x + static member inline op_Implicit(x: 'a ValueOption) = AsyncDisposableOption.ofValueOption x module Examples = open DisposableOptionThings open System.Diagnostics - let inline implicitConv (x: ^T) : ^U = ((^T or ^U) : (static member op_Implicit : ^T -> ^U) (x)) + let inline implicitConv (x: ^T) : ^U = + ((^T or ^U): (static member op_Implicit: ^T -> ^U) (x)) + let inline (!>) x = implicitConv x - let inline (|!>) x f = f (!> x) + let inline (|!>) x f = f (!>x) let activitySource = new ActivitySource("Playground.App") let example () = - use a = activitySource.StartActivity("lol") |> DisposableOption.OfObj - a |!> Option.iter(fun a -> a.AddTag("hello", "world") |> ignore) - () + use a = + activitySource.StartActivity("lol") + |> DisposableOption.OfObj + a + |!> Option.iter (fun a -> + a.AddTag("hello", "world") + |> ignore + ) + + () diff --git a/src/FsToolkit.ErrorHandling.AsyncSeq/Library.fs b/src/FsToolkit.ErrorHandling.AsyncSeq/Library.fs index db0539cb..ec7dc45e 100644 --- a/src/FsToolkit.ErrorHandling.AsyncSeq/Library.fs +++ b/src/FsToolkit.ErrorHandling.AsyncSeq/Library.fs @@ -41,17 +41,13 @@ module AsyncSeqCE = member this.For - ( - xs: AsyncSeq>, - binder: 'T -> Async> - ) : Async> = + (xs: AsyncSeq>, binder: 'T -> Async>) + : Async> = this.Using(xs.GetEnumerator(), (fun enum -> this.While(enum.MoveNext, binder))) member this.For - ( - xs: AsyncSeq<'T>, - binder: 'T -> Async> - ) : Async> = + (xs: AsyncSeq<'T>, binder: 'T -> Async>) + : Async> = this.Using( xs.GetEnumerator(), fun enum -> diff --git a/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskOption.fs b/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskOption.fs index 13f3b9cd..0ebf3966 100644 --- a/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskOption.fs +++ b/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskOption.fs @@ -81,10 +81,8 @@ type ValueTaskValueOptionBuilderBase() = /// Note that this requires that the first step has no result. /// This prevents constructs like `task { return 1; return 2; }`. member inline _.Combine - ( - task1: TaskOptionCode<'TOverall, unit>, - task2: TaskOptionCode<'TOverall, 'T> - ) : TaskOptionCode<'TOverall, 'T> = + (task1: TaskOptionCode<'TOverall, unit>, task2: TaskOptionCode<'TOverall, 'T>) + : TaskOptionCode<'TOverall, 'T> = ResumableCode.Combine( task1, @@ -95,10 +93,8 @@ type ValueTaskValueOptionBuilderBase() = /// Builds a step that executes the body while the condition predicate is true. member inline _.While - ( - [] condition: unit -> bool, - body: TaskOptionCode<'TOverall, unit> - ) : TaskOptionCode<'TOverall, unit> = + ([] condition: unit -> bool, body: TaskOptionCode<'TOverall, unit>) + : TaskOptionCode<'TOverall, unit> = let mutable keepGoing = true ResumableCode.While( @@ -120,19 +116,15 @@ type ValueTaskValueOptionBuilderBase() = /// Wraps a step in a try/with. This catches exceptions both in the evaluation of the function /// to retrieve the step, and in the continuation of the step (if any). member inline _.TryWith - ( - body: TaskOptionCode<'TOverall, 'T>, - catch: exn -> TaskOptionCode<'TOverall, 'T> - ) : TaskOptionCode<'TOverall, 'T> = + (body: TaskOptionCode<'TOverall, 'T>, catch: exn -> TaskOptionCode<'TOverall, 'T>) + : TaskOptionCode<'TOverall, 'T> = ResumableCode.TryWith(body, catch) /// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function /// to retrieve the step, and in the continuation of the step (if any). member inline _.TryFinally - ( - body: TaskOptionCode<'TOverall, 'T>, - [] compensation: unit -> unit - ) : TaskOptionCode<'TOverall, 'T> = + (body: TaskOptionCode<'TOverall, 'T>, [] compensation: unit -> unit) + : TaskOptionCode<'TOverall, 'T> = ResumableCode.TryFinally( body, ResumableCode<_, _>(fun _sm -> @@ -142,10 +134,8 @@ type ValueTaskValueOptionBuilderBase() = ) member inline this.For - ( - sequence: seq<'T>, - body: 'T -> TaskOptionCode<'TOverall, unit> - ) : TaskOptionCode<'TOverall, unit> = + (sequence: seq<'T>, body: 'T -> TaskOptionCode<'TOverall, unit>) + : TaskOptionCode<'TOverall, unit> = ResumableCode.Using( sequence.GetEnumerator(), // ... and its body is a while loop that advances the enumerator and runs the body on each element. @@ -158,10 +148,8 @@ type ValueTaskValueOptionBuilderBase() = ) member inline internal this.TryFinallyAsync - ( - body: TaskOptionCode<'TOverall, 'T>, - compensation: unit -> ValueTask - ) : TaskOptionCode<'TOverall, 'T> = + (body: TaskOptionCode<'TOverall, 'T>, compensation: unit -> ValueTask) + : TaskOptionCode<'TOverall, 'T> = ResumableCode.TryFinallyAsync( body, ResumableCode<_, _>(fun sm -> @@ -203,10 +191,8 @@ type ValueTaskValueOptionBuilderBase() = ) member inline this.Using<'Resource, 'TOverall, 'T when 'Resource :> IAsyncDisposable> - ( - resource: 'Resource, - body: 'Resource -> TaskOptionCode<'TOverall, 'T> - ) : TaskOptionCode<'TOverall, 'T> = + (resource: 'Resource, body: 'Resource -> TaskOptionCode<'TOverall, 'T>) + : TaskOptionCode<'TOverall, 'T> = this.TryFinallyAsync( (fun sm -> (body resource).Invoke(&sm)), (fun () -> @@ -469,10 +455,8 @@ module TaskOptionCEExtensionsLowPriority = and ^Awaiter :> ICriticalNotifyCompletion and ^Awaiter: (member get_IsCompleted: unit -> bool) and ^Awaiter: (member GetResult: unit -> 'TResult1 option)> - ( - task: ^TaskLike, - continuation: ('TResult1 -> TaskOptionCode<'TOverall, 'TResult2>) - ) : TaskOptionCode<'TOverall, 'TResult2> = + (task: ^TaskLike, continuation: ('TResult1 -> TaskOptionCode<'TOverall, 'TResult2>)) + : TaskOptionCode<'TOverall, 'TResult2> = TaskOptionCode<'TOverall, _>(fun sm -> if __useResumableCode then @@ -501,7 +485,13 @@ module TaskOptionCEExtensionsLowPriority = sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm) false else - ValueTaskValueOptionBuilderBase.BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall>( + ValueTaskValueOptionBuilderBase.BindDynamic< + ^TaskLike, + 'TResult1, + 'TResult2, + ^Awaiter, + 'TOverall + >( &sm, task, continuation @@ -535,10 +525,8 @@ module TaskOptionCEExtensionsLowPriority = } member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IDisposable> - ( - resource: 'Resource, - body: 'Resource -> TaskOptionCode<'TOverall, 'T> - ) = + (resource: 'Resource, body: 'Resource -> TaskOptionCode<'TOverall, 'T>) + = ResumableCode.Using(resource, body) [] @@ -612,10 +600,8 @@ module TaskOptionCEExtensionsHighPriority = ) member inline this.BindReturn - ( - x: CancellableValueTaskValueOption<'T>, - [] f - ) = + (x: CancellableValueTaskValueOption<'T>, [] f) + = this.Bind(x, (fun x -> this.Return(f x))) // member inline _.MergeSources(t1: CancellableTaskOption<'T>, t2: CancellableTaskOption<'T1>) = TaskOption.zip t1 t2 diff --git a/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultBuilderBase.fs b/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultBuilderBase.fs index 8e79edc1..9d9f6024 100644 --- a/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultBuilderBase.fs +++ b/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultBuilderBase.fs @@ -43,7 +43,9 @@ module CancellableTaskResultBuilderBase = /// This is used by the compiler as a template for creating state machine structs and CancellableTaskResultBuilderBaseStateMachine<'TOverall, 'Error, 'Builder> = - ResumableStateMachine> + ResumableStateMachine< + CancellableTaskResultBuilderBaseStateMachineData<'TOverall, 'Error, 'Builder> + > /// Represents the runtime continuation of a cancellableTasks state machine created dynamically and CancellableTaskResultBuilderBaseResumptionFunc<'TOverall, 'Error, 'Builder> = @@ -51,11 +53,16 @@ module CancellableTaskResultBuilderBase = /// Represents the runtime continuation of a cancellableTasks state machine created dynamically and CancellableTaskResultBuilderBaseResumptionDynamicInfo<'TOverall, 'Error, 'Builder> = - ResumptionDynamicInfo> + ResumptionDynamicInfo< + CancellableTaskResultBuilderBaseStateMachineData<'TOverall, 'Error, 'Builder> + > /// A special compiler-recognised delegate type for specifying blocks of cancellableTasks code with access to the state machine and CancellableTaskResultBuilderBaseCode<'TOverall, 'T, 'Error, 'Builder> = - ResumableCode, 'T> + ResumableCode< + CancellableTaskResultBuilderBaseStateMachineData<'TOverall, 'Error, 'Builder>, + 'T + > /// /// Contains methods to build TaskLikes using the F# computation expression syntax @@ -215,11 +222,24 @@ module CancellableTaskResultBuilderBase = static member inline BindDynamic ( sm: - byref>>, + byref< + ResumableStateMachine< + CancellableTaskResultBuilderBaseStateMachineData< + 'TOverall, + 'Error, + 'Builder + > + > + >, [] getAwaiter: CancellationToken -> 'Awaiter, continuation: ('TResult1 - -> CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>) + -> CancellableTaskResultBuilderBaseCode< + 'TOverall, + 'TResult2, + 'Error, + 'Builder + >) ) : bool = sm.Data.ThrowIfCancellationRequested() @@ -264,7 +284,12 @@ module CancellableTaskResultBuilderBase = [] getAwaiterTResult: CancellationToken -> 'Awaiter, continuation: ('TResult1 - -> CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>) + -> CancellableTaskResultBuilderBaseCode< + 'TOverall, + 'TResult2, + 'Error, + 'Builder + >) ) : CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder> = CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>(fun sm -> @@ -388,8 +413,11 @@ module CancellableTaskResultBuilderBase = let mutable awaiter = compensation () let cont = - CancellableTaskResultBuilderBaseResumptionFunc<'TOverall, 'Error, 'Builder>(fun - sm -> + CancellableTaskResultBuilderBaseResumptionFunc< + 'TOverall, + 'Error, + 'Builder + >(fun sm -> Awaiter.GetResult awaiter true ) @@ -490,8 +518,11 @@ module CancellableTaskResultBuilderBase = let mutable awaiter = condition () let cont = - CancellableTaskResultBuilderBaseResumptionFunc<'TOverall, 'Error, 'Builder>(fun - sm -> + CancellableTaskResultBuilderBaseResumptionFunc< + 'TOverall, + 'Error, + 'Builder + >(fun sm -> condition_res <- Awaiter.GetResult awaiter if condition_res then body.Invoke(&sm) else true ) @@ -543,11 +574,24 @@ module CancellableTaskResultBuilderBase = static member inline BindDynamic ( sm: - byref>>, + byref< + ResumableStateMachine< + CancellableTaskResultBuilderBaseStateMachineData< + 'TOverall, + 'Error, + 'Builder + > + > + >, [] getAwaiter: CancellationToken -> 'Awaiter, continuation: ('TResult1 - -> CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>) + -> CancellableTaskResultBuilderBaseCode< + 'TOverall, + 'TResult2, + 'Error, + 'Builder + >) ) : bool = sm.Data.ThrowIfCancellationRequested() @@ -589,7 +633,12 @@ module CancellableTaskResultBuilderBase = [] getAwaiterT: CancellationToken -> 'Awaiter, continuation: ('TResult1 - -> CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>) + -> CancellableTaskResultBuilderBaseCode< + 'TOverall, + 'TResult2, + 'Error, + 'Builder + >) ) : CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder> = CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>(fun sm -> @@ -664,11 +713,24 @@ module CancellableTaskResultBuilderBase = static member inline BindDynamic ( sm: - byref>>, + byref< + ResumableStateMachine< + CancellableTaskResultBuilderBaseStateMachineData< + 'TOverall, + 'Error, + 'Builder + > + > + >, awaiter: 'Awaiter, continuation: ('TResult1 - -> CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>) + -> CancellableTaskResultBuilderBaseCode< + 'TOverall, + 'TResult2, + 'Error, + 'Builder + >) ) : bool = sm.Data.ThrowIfCancellationRequested() let mutable awaiter = awaiter @@ -710,7 +772,12 @@ module CancellableTaskResultBuilderBase = awaiterT: 'Awaiter, continuation: ('TResult1 - -> CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>) + -> CancellableTaskResultBuilderBaseCode< + 'TOverall, + 'TResult2, + 'Error, + 'Builder + >) ) : CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder> = CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>(fun sm -> @@ -951,11 +1018,24 @@ module CancellableTaskResultBuilderBase = static member inline BindDynamic ( sm: - byref>>, + byref< + ResumableStateMachine< + CancellableTaskResultBuilderBaseStateMachineData< + 'TOverall, + 'Error, + 'Builder + > + > + >, awaiter: 'Awaiter, continuation: ('TResult1 - -> CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>) + -> CancellableTaskResultBuilderBaseCode< + 'TOverall, + 'TResult2, + 'Error, + 'Builder + >) ) : bool = sm.Data.ThrowIfCancellationRequested() let mutable awaiter = awaiter @@ -1001,7 +1081,12 @@ module CancellableTaskResultBuilderBase = awaiterTResult: 'Awaiter, continuation: ('TResult1 - -> CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>) + -> CancellableTaskResultBuilderBaseCode< + 'TOverall, + 'TResult2, + 'Error, + 'Builder + >) ) : CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder> = CancellableTaskResultBuilderBaseCode<'TOverall, 'TResult2, 'Error, 'Builder>(fun sm -> diff --git a/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultCE.fs b/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultCE.fs index 47b92aa5..d3571b7c 100644 --- a/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultCE.fs +++ b/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskResultCE.fs @@ -92,7 +92,10 @@ module CancellableTaskResultCE = (code: CancellableTaskResultBuilderBaseCode<'T, 'T, 'Error, _>) : CancellableTaskResult<'T, 'Error> = if __useResumableCode then - __stateMachine, CancellableTaskResult<'T, 'Error>> + __stateMachine< + CancellableTaskResultBuilderBaseStateMachineData<'T, 'Error, _>, + CancellableTaskResult<'T, 'Error> + > (MoveNextMethodImpl<_>(fun sm -> //-- RESUMABLE CODE START __resumeAt sm.ResumptionPoint @@ -223,7 +226,10 @@ module CancellableTaskResultCE = (code: CancellableTaskResultBuilderBaseCode<'T, 'T, 'Error, _>) : CancellableTaskResult<'T, 'Error> = if __useResumableCode then - __stateMachine, CancellableTaskResult<'T, 'Error>> + __stateMachine< + CancellableTaskResultBuilderBaseStateMachineData<'T, 'Error, _>, + CancellableTaskResult<'T, 'Error> + > (MoveNextMethodImpl<_>(fun sm -> //-- RESUMABLE CODE START __resumeAt sm.ResumptionPoint diff --git a/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskValidationCE.fs b/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskValidationCE.fs index 452ede54..0e0fd54d 100644 --- a/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskValidationCE.fs +++ b/src/FsToolkit.ErrorHandling.IcedTasks/CancellableTaskValidationCE.fs @@ -79,7 +79,12 @@ module CancellableTaskValidationCE = /// static member inline RunDynamic (code: - CancellableTaskResultBuilderBaseCode<'T, 'T, 'Error list, AsyncTaskMethodBuilder>>) + CancellableTaskResultBuilderBaseCode< + 'T, + 'T, + 'Error list, + AsyncTaskMethodBuilder> + >) : CancellableTaskValidation<'T, 'Error> = let mutable sm = CancellableTaskResultBuilderBaseStateMachine<'T, 'Error list, _>() @@ -139,7 +144,14 @@ module CancellableTaskValidationCE = (code: CancellableTaskResultBuilderBaseCode<'T, 'T, 'Error list, _>) : CancellableTaskValidation<'T, 'Error> = if __useResumableCode then - __stateMachine>>, CancellableTaskValidation<'T, 'Error>> + __stateMachine< + CancellableTaskResultBuilderBaseStateMachineData< + 'T, + 'Error list, + AsyncTaskMethodBuilder> + >, + CancellableTaskValidation<'T, 'Error> + > (MoveNextMethodImpl<_>(fun sm -> //-- RESUMABLE CODE START __resumeAt sm.ResumptionPoint @@ -214,20 +226,20 @@ module AsyncExtensions = type Microsoft.FSharp.Control.AsyncBuilder with member inline this.Bind - ( - [] t: CancellableTask<'T>, - [] binder: ('T -> Async<'U>) - ) : Async<'U> = + ([] t: CancellableTask<'T>, [] binder: ('T -> Async<'U>)) : Async< + 'U + > + = this.Bind(Async.AwaitCancellableTask t, binder) member inline this.ReturnFrom([] t: CancellableTask<'T>) : Async<'T> = this.ReturnFrom(Async.AwaitCancellableTask t) member inline this.Bind - ( - [] t: CancellableTask, - [] binder: (unit -> Async<'U>) - ) : Async<'U> = + ([] t: CancellableTask, [] binder: (unit -> Async<'U>)) : Async< + 'U + > + = this.Bind(Async.AwaitCancellableTask t, binder) member inline this.ReturnFrom([] t: CancellableTask) : Async = @@ -675,10 +687,8 @@ module CTVMergeSourcesExtensionsCT1T2 = [] member inline this.MergeSources - ( - [] left: CancellationToken -> 'Awaiter1, - right: 'Awaiter2 - ) = + ([] left: CancellationToken -> 'Awaiter1, right: 'Awaiter2) + = this.Source( // cancellableTask.Run( // cancellableTask.Bind( @@ -709,10 +719,8 @@ module CTVMergeSourcesExtensionsCV1T2 = [] member inline this.MergeSources - ( - [] left: CancellationToken -> 'Awaiter1, - right: 'Awaiter2 - ) = + ([] left: CancellationToken -> 'Awaiter1, right: 'Awaiter2) + = this.Source( // cancellableTask.Run( // cancellableTask.Bind( @@ -744,10 +752,8 @@ module CTVMergeSourcesExtensionsCT1TV2 = [] member inline this.MergeSources - ( - [] left: CancellationToken -> 'Awaiter1, - right: 'Awaiter2 - ) = + ([] left: CancellationToken -> 'Awaiter1, right: 'Awaiter2) + = this.Source( // cancellableTask.Run( // cancellableTask.Bind( @@ -779,10 +785,8 @@ module CTVMergeSourcesExtensionsCV1TV2 = [] member inline this.MergeSources - ( - [] left: CancellationToken -> 'Awaiter1, - right: 'Awaiter2 - ) = + ([] left: CancellationToken -> 'Awaiter1, right: 'Awaiter2) + = this.Source( // cancellableTask.Run( // cancellableTask.Bind( @@ -813,10 +817,8 @@ module CTVMergeSourcesExtensionsT1CT2 = [] member inline this.MergeSources - ( - left: 'Awaiter1, - [] right: CancellationToken -> 'Awaiter2 - ) = + (left: 'Awaiter1, [] right: CancellationToken -> 'Awaiter2) + = this.Source( // cancellableTask.Run( // cancellableTask.Bind( @@ -847,10 +849,8 @@ module CTVMergeSourcesExtensionsTV1CT2 = [] member inline this.MergeSources - ( - left: 'Awaiter1, - [] right: CancellationToken -> 'Awaiter2 - ) = + (left: 'Awaiter1, [] right: CancellationToken -> 'Awaiter2) + = this.Source( // cancellableTask.Run( // cancellableTask.Bind( @@ -882,10 +882,8 @@ module CTVMergeSourcesExtensionsT1CV2 = [] member inline this.MergeSources - ( - left: 'Awaiter1, - [] right: CancellationToken -> 'Awaiter2 - ) = + (left: 'Awaiter1, [] right: CancellationToken -> 'Awaiter2) + = this.Source( // cancellableTask.Run( // cancellableTask.Bind( @@ -917,10 +915,8 @@ module CTVMergeSourcesExtensionsTV1CV2 = [] member inline this.MergeSources - ( - left: 'Awaiter1, - [] right: CancellationToken -> 'Awaiter2 - ) = + (left: 'Awaiter1, [] right: CancellationToken -> 'Awaiter2) + = this.Source( // cancellableTask.Run( // cancellableTask.Bind( diff --git a/src/FsToolkit.ErrorHandling.JobResult/JobOptionCE.fs b/src/FsToolkit.ErrorHandling.JobResult/JobOptionCE.fs index c459e84b..fb74ce32 100644 --- a/src/FsToolkit.ErrorHandling.JobResult/JobOptionCE.fs +++ b/src/FsToolkit.ErrorHandling.JobResult/JobOptionCE.fs @@ -20,10 +20,8 @@ module JobOptionCE = |> job.Return member inline _.Bind - ( - jobResult: Job<_ option>, - [] binder: 'T -> Job<_ option> - ) : Job<_ option> = + (jobResult: Job<_ option>, [] binder: 'T -> Job<_ option>) + : Job<_ option> = job { let! result = jobResult @@ -43,10 +41,8 @@ module JobOptionCE = Job.delay generator member inline this.Combine - ( - computation1: Job<_ option>, - computation2: Job<_ option> - ) : Job<_ option> = + (computation1: Job<_ option>, computation2: Job<_ option>) + : Job<_ option> = this.Bind(computation1, (fun () -> computation2)) member inline _.TryWith @@ -64,24 +60,18 @@ module JobOptionCE = Job.tryWithDelay computation handler member inline _.TryFinally - ( - computation: Job<_ option>, - [] compensation: unit -> unit - ) : Job<_ option> = + (computation: Job<_ option>, [] compensation: unit -> unit) + : Job<_ option> = Job.tryFinallyFun computation compensation member inline _.TryFinally - ( - computation: unit -> Job<_ option>, - [] compensation: unit -> unit - ) : Job<_ option> = + (computation: unit -> Job<_ option>, [] compensation: unit -> unit) + : Job<_ option> = Job.tryFinallyFunDelay computation compensation member inline _.Using - ( - resource: 'T :> IDisposable, - [] binder: 'T -> Job<_ option> - ) : Job<_ option> = + (resource: 'T :> IDisposable, [] binder: 'T -> Job<_ option>) + : Job<_ option> = job.Using(resource, binder) member this.While(guard: unit -> bool, computation: Job<_ option>) : Job<_ option> = @@ -102,10 +92,8 @@ module JobOptionCE = } member inline this.For - ( - sequence: #seq<'T>, - [] binder: 'T -> Job<_ option> - ) : Job<_ option> = + (sequence: #seq<'T>, [] binder: 'T -> Job<_ option>) + : Job<_ option> = this.Using( sequence.GetEnumerator(), fun enum -> this.While(enum.MoveNext, this.Delay(fun () -> binder enum.Current)) diff --git a/src/FsToolkit.ErrorHandling.JobResult/JobResultCE.fs b/src/FsToolkit.ErrorHandling.JobResult/JobResultCE.fs index f13dad76..c1acecd2 100644 --- a/src/FsToolkit.ErrorHandling.JobResult/JobResultCE.fs +++ b/src/FsToolkit.ErrorHandling.JobResult/JobResultCE.fs @@ -39,10 +39,8 @@ module JobResultCE = Job.delay generator member inline this.Combine - ( - computation1: Job>, - computation2: Job> - ) : Job> = + (computation1: Job>, computation2: Job>) + : Job> = this.Bind(computation1, (fun () -> computation2)) member inline _.TryWith @@ -60,10 +58,13 @@ module JobResultCE = Job.tryWithDelay computation handler member inline _.TryFinally - ( - computation: Job>, - [] compensation: unit -> unit - ) : Job> = + (computation: Job>, [] compensation: unit -> unit) : Job< + Result< + 'T, + 'TError + > + > + = Job.tryFinallyFun computation compensation member inline _.TryFinally @@ -74,17 +75,18 @@ module JobResultCE = Job.tryFinallyFunDelay computation compensation member inline _.Using - ( - resource: 'T :> IDisposable, - [] binder: 'T -> Job> - ) : Job> = + (resource: 'T :> IDisposable, [] binder: 'T -> Job>) : Job< + Result< + 'U, + 'TError + > + > + = job.Using(resource, binder) member this.While - ( - guard: unit -> bool, - computation: Job> - ) : Job> = + (guard: unit -> bool, computation: Job>) + : Job> = job { let mutable doContinue = true let mutable result = Ok() @@ -102,10 +104,8 @@ module JobResultCE = } member inline this.For - ( - sequence: #seq<'T>, - [] binder: 'T -> Job> - ) : Job> = + (sequence: #seq<'T>, [] binder: 'T -> Job>) + : Job> = this.Using( sequence.GetEnumerator(), fun enum -> this.While(enum.MoveNext, this.Delay(fun () -> binder enum.Current)) diff --git a/src/FsToolkit.ErrorHandling/AsyncOptionCE.fs b/src/FsToolkit.ErrorHandling/AsyncOptionCE.fs index b18dfea4..e277db58 100644 --- a/src/FsToolkit.ErrorHandling/AsyncOptionCE.fs +++ b/src/FsToolkit.ErrorHandling/AsyncOptionCE.fs @@ -16,20 +16,18 @@ module AsyncOptionCE = |> async.Return member inline _.Bind - ( - input: Async<'input option>, - [] binder: 'input -> Async<'output option> - ) : Async<'output option> = + (input: Async<'input option>, [] binder: 'input -> Async<'output option>) : Async< + 'output option + > + = AsyncOption.bind binder input member inline _.Delay(generator: unit -> Async<'value option>) : Async<'value option> = async.Delay generator member inline this.Combine - ( - computation1: Async<_ option>, - computation2: Async<_ option> - ) : Async<_ option> = + (computation1: Async<_ option>, computation2: Async<_ option>) + : Async<_ option> = this.Bind(computation1, (fun () -> computation2)) member inline _.TryWith @@ -40,17 +38,15 @@ module AsyncOptionCE = async.TryWith(computation, handler) member inline _.TryFinally - ( - computation: Async<'value option>, - [] compensation: unit -> unit - ) : Async<'value option> = + (computation: Async<'value option>, [] compensation: unit -> unit) + : Async<'value option> = async.TryFinally(computation, compensation) #if !FABLE_COMPILER member inline _.TryFinallyAsync - ( - computation: Async<'value option>, - [] compensation: unit -> ValueTask - ) : Async<'value option> = + (computation: Async<'value option>, [] compensation: unit -> ValueTask) : Async< + 'value option + > + = let compensation = async { let vTask = compensation () @@ -83,10 +79,8 @@ module AsyncOptionCE = #endif member this.While - ( - guard: unit -> bool, - computation: Async - ) : Async = + (guard: unit -> bool, computation: Async) + : Async = if not (guard ()) then this.Zero() else @@ -142,10 +136,8 @@ module AsyncOptionCEExtensions = ) member inline this.For - ( - sequence: #seq<'input>, - binder: 'input -> Async - ) : Async = + (sequence: #seq<'input>, binder: 'input -> Async) + : Async = this.Using( sequence.GetEnumerator(), fun enum -> this.While(enum.MoveNext, this.Delay(fun () -> binder enum.Current)) diff --git a/src/FsToolkit.ErrorHandling/AsyncResultCE.fs b/src/FsToolkit.ErrorHandling/AsyncResultCE.fs index 6116b3da..1b04c25d 100644 --- a/src/FsToolkit.ErrorHandling/AsyncResultCE.fs +++ b/src/FsToolkit.ErrorHandling/AsyncResultCE.fs @@ -34,10 +34,8 @@ module AsyncResultCE = async.Delay generator member inline this.Combine - ( - computation1: Async>, - computation2: Async> - ) : Async> = + (computation1: Async>, computation2: Async>) + : Async> = this.Bind(computation1, (fun () -> computation2)) member inline _.TryWith @@ -48,10 +46,13 @@ module AsyncResultCE = async.TryWith(computation, handler) member inline _.TryFinally - ( - computation: Async>, - [] compensation: unit -> unit - ) : Async> = + (computation: Async>, [] compensation: unit -> unit) : Async< + Result< + 'ok, + 'error + > + > + = async.TryFinally(computation, compensation) #if !FABLE_COMPILER member inline _.TryFinallyAsync @@ -90,10 +91,8 @@ module AsyncResultCE = ) #endif member inline this.While - ( - [] guard: unit -> bool, - computation: Async> - ) : Async> = + ([] guard: unit -> bool, computation: Async>) + : Async> = if guard () then let mutable whileAsync = Unchecked.defaultof<_> @@ -106,10 +105,8 @@ module AsyncResultCE = member inline _.BindReturn - ( - x: Async>, - [] f: 'okInput -> 'okOutput - ) : Async> = + (x: Async>, [] f: 'okInput -> 'okOutput) + : Async> = AsyncResult.map f x /// @@ -164,10 +161,8 @@ module AsyncResultCEExtensions = member inline this.For - ( - sequence: #seq<'ok>, - [] binder: 'ok -> Async> - ) : Async> = + (sequence: #seq<'ok>, [] binder: 'ok -> Async>) + : Async> = this.Using( sequence.GetEnumerator(), fun enum -> diff --git a/src/FsToolkit.ErrorHandling/AsyncResultOptionCE.fs b/src/FsToolkit.ErrorHandling/AsyncResultOptionCE.fs index e39dd584..b925d66d 100644 --- a/src/FsToolkit.ErrorHandling/AsyncResultOptionCE.fs +++ b/src/FsToolkit.ErrorHandling/AsyncResultOptionCE.fs @@ -80,10 +80,11 @@ module AsyncResultOptionCE = #endif member inline this.While - ( - [] guard: unit -> bool, - computation: AsyncResultOption - ) : AsyncResultOption = + ([] guard: unit -> bool, computation: AsyncResultOption) : AsyncResultOption< + unit, + 'error + > + = if guard () then let mutable whileAsync = Unchecked.defaultof<_> @@ -151,10 +152,11 @@ module AsyncResultOptionCEExtensions = member inline this.For - ( - sequence: #seq<'ok>, - [] binder: 'ok -> AsyncResultOption - ) : AsyncResultOption = + (sequence: #seq<'ok>, [] binder: 'ok -> AsyncResultOption) : AsyncResultOption< + unit, + 'error + > + = this.Using( sequence.GetEnumerator(), fun enum -> diff --git a/src/FsToolkit.ErrorHandling/AsyncValidationCE.fs b/src/FsToolkit.ErrorHandling/AsyncValidationCE.fs index a05d36d1..b163c7ee 100644 --- a/src/FsToolkit.ErrorHandling/AsyncValidationCE.fs +++ b/src/FsToolkit.ErrorHandling/AsyncValidationCE.fs @@ -28,10 +28,11 @@ module AsyncValidationCE = async.Delay generator member inline this.Combine - ( - validation1: AsyncValidation, - validation2: AsyncValidation<'ok, 'error> - ) : AsyncValidation<'ok, 'error> = + (validation1: AsyncValidation, validation2: AsyncValidation<'ok, 'error>) : AsyncValidation< + 'ok, + 'error + > + = this.Bind(validation1, (fun () -> validation2)) member inline _.TryWith @@ -56,10 +57,8 @@ module AsyncValidationCE = async.Using(resource, binder) member inline this.While - ( - [] guard: unit -> bool, - computation: AsyncValidation - ) : AsyncValidation = + ([] guard: unit -> bool, computation: AsyncValidation) + : AsyncValidation = if guard () then let mutable whileAsync = Unchecked.defaultof<_> @@ -72,10 +71,11 @@ module AsyncValidationCE = member inline this.For - ( - sequence: #seq<'ok>, - [] binder: 'ok -> AsyncValidation - ) : AsyncValidation = + (sequence: #seq<'ok>, [] binder: 'ok -> AsyncValidation) : AsyncValidation< + unit, + 'error + > + = this.Using( sequence.GetEnumerator(), fun enum -> this.While(enum.MoveNext, this.Delay(fun () -> binder enum.Current)) @@ -89,10 +89,8 @@ module AsyncValidationCE = AsyncValidation.map mapper input member inline _.MergeSources - ( - left: AsyncValidation<'left, 'error>, - right: AsyncValidation<'right, 'error> - ) : AsyncValidation<'left * 'right, 'error> = + (left: AsyncValidation<'left, 'error>, right: AsyncValidation<'right, 'error>) + : AsyncValidation<'left * 'right, 'error> = AsyncValidation.zip left right let asyncValidation = AsyncValidationBuilder() diff --git a/src/FsToolkit.ErrorHandling/OptionCE.fs b/src/FsToolkit.ErrorHandling/OptionCE.fs index cf6ec296..8c9f049f 100644 --- a/src/FsToolkit.ErrorHandling/OptionCE.fs +++ b/src/FsToolkit.ErrorHandling/OptionCE.fs @@ -10,27 +10,21 @@ module OptionCE = member inline _.ReturnFrom(m: 'value option) : 'value option = m member inline _.Bind - ( - input: 'input option, - [] binder: 'input -> 'output option - ) : 'output option = + (input: 'input option, [] binder: 'input -> 'output option) + : 'output option = Option.bind binder input // Could not get it to work solely with Source. In loop cases it would potentially match the #seq overload and ask for type annotation member inline this.Bind - ( - m: 'input when 'input: null, - [] binder: 'input -> 'output option - ) : 'output option = + (m: 'input when 'input: null, [] binder: 'input -> 'output option) + : 'output option = this.Bind(Option.ofObj m, binder) member inline this.Zero() : unit option = this.Return() member inline _.Combine - ( - m: 'input option, - [] binder: 'input -> 'output option - ) : 'output option = + (m: 'input option, [] binder: 'input -> 'output option) + : 'output option = Option.bind binder m member inline this.Combine(m1: unit option, m2: 'output option) : 'output option = @@ -88,27 +82,21 @@ module OptionCE = result member inline this.For - ( - sequence: #seq<'value>, - [] binder: 'value -> unit option - ) : unit option = + (sequence: #seq<'value>, [] binder: 'value -> unit option) + : unit option = this.Using( sequence.GetEnumerator(), fun enum -> this.While(enum.MoveNext, this.Delay(fun () -> binder enum.Current)) ) member inline _.BindReturn - ( - input: 'input option, - [] mapper: 'input -> 'output - ) : 'output option = + (input: 'input option, [] mapper: 'input -> 'output) + : 'output option = Option.map mapper input member inline _.BindReturn - ( - x: 'input, - [] f: 'input -> 'output - ) : 'output option = + (x: 'input, [] f: 'input -> 'output) + : 'output option = Option.map f (Option.ofObj x) /// diff --git a/src/FsToolkit.ErrorHandling/ResultCE.fs b/src/FsToolkit.ErrorHandling/ResultCE.fs index e1b43386..63de067f 100644 --- a/src/FsToolkit.ErrorHandling/ResultCE.fs +++ b/src/FsToolkit.ErrorHandling/ResultCE.fs @@ -30,10 +30,11 @@ module ResultCE = generator () member inline this.Combine - ( - result: Result, - [] binder: unit -> Result<'ok, 'error> - ) : Result<'ok, 'error> = + (result: Result, [] binder: unit -> Result<'ok, 'error>) : Result< + 'ok, + 'error + > + = this.Bind(result, binder) member inline this.TryWith @@ -57,10 +58,8 @@ module ResultCE = compensation () member inline this.Using - ( - resource: 'disposable :> IDisposable, - binder: 'disposable -> Result<'ok, 'error> - ) : Result<'ok, 'error> = + (resource: 'disposable :> IDisposable, binder: 'disposable -> Result<'ok, 'error>) + : Result<'ok, 'error> = this.TryFinally( (fun () -> binder resource), (fun () -> @@ -89,10 +88,8 @@ module ResultCE = result member inline this.For - ( - sequence: #seq<'T>, - [] binder: 'T -> Result - ) : Result = + (sequence: #seq<'T>, [] binder: 'T -> Result) + : Result = this.Using( sequence.GetEnumerator(), fun enum -> @@ -103,10 +100,8 @@ module ResultCE = ) member inline _.BindReturn - ( - x: Result<'okInput, 'error>, - [] f: 'okInput -> 'okOutput - ) : Result<'okOutput, 'error> = + (x: Result<'okInput, 'error>, [] f: 'okInput -> 'okOutput) + : Result<'okOutput, 'error> = Result.map f x /// diff --git a/src/FsToolkit.ErrorHandling/ResultOptionCE.fs b/src/FsToolkit.ErrorHandling/ResultOptionCE.fs index 7af5243a..ae9a1902 100644 --- a/src/FsToolkit.ErrorHandling/ResultOptionCE.fs +++ b/src/FsToolkit.ErrorHandling/ResultOptionCE.fs @@ -57,10 +57,11 @@ module ResultOptionCE = compensation () member inline this.Using - ( - resource: 'disposable :> IDisposable, - binder: 'disposable -> Result<'ok option, 'error> - ) : Result<'ok option, 'error> = + (resource: 'disposable :> IDisposable, binder: 'disposable -> Result<'ok option, 'error>) : Result< + 'ok option, + 'error + > + = this.TryFinally( (fun () -> binder resource), (fun () -> @@ -94,10 +95,8 @@ module ResultOptionCE = result member inline this.For - ( - sequence: #seq<'T>, - [] binder: 'T -> Result - ) : Result = + (sequence: #seq<'T>, [] binder: 'T -> Result) + : Result = this.Using( sequence.GetEnumerator(), fun enum -> @@ -108,10 +107,8 @@ module ResultOptionCE = ) member inline _.BindReturn - ( - resultOpt: Result<'T option, 'TError>, - [] binder: 'T -> 'U - ) : Result<'U option, 'TError> = + (resultOpt: Result<'T option, 'TError>, [] binder: 'T -> 'U) + : Result<'U option, 'TError> = ResultOption.map binder resultOpt member inline _.Source(result: Result<'ok option, 'error>) : Result<'ok option, 'error> = diff --git a/src/FsToolkit.ErrorHandling/Seq.fs b/src/FsToolkit.ErrorHandling/Seq.fs index 9cee77a4..9252dd7a 100644 --- a/src/FsToolkit.ErrorHandling/Seq.fs +++ b/src/FsToolkit.ErrorHandling/Seq.fs @@ -1,364 +1,360 @@ [] module FsToolkit.ErrorHandling.Seq - /// - /// Applies a function to each element of a sequence and returns a single result - /// - /// The initial state - /// The function to apply to each element - /// The input sequence - /// A result with the ok elements in a sequence or the first error occurring in the sequence - let inline traverseResultM' - state - ([] f: 'okInput -> Result<'okOutput, 'error>) - (xs: 'okInput seq) - = - match state with - | Error _ -> state +/// +/// Applies a function to each element of a sequence and returns a single result +/// +/// The initial state +/// The function to apply to each element +/// The input sequence +/// A result with the ok elements in a sequence or the first error occurring in the sequence +let inline traverseResultM' + state + ([] f: 'okInput -> Result<'okOutput, 'error>) + (xs: 'okInput seq) + = + match state with + | Error _ -> state + | Ok oks -> + use enumerator = xs.GetEnumerator() + + let rec loop oks = + if enumerator.MoveNext() then + match f enumerator.Current with + | Ok ok -> + loop ( + seq { + yield ok + yield! oks + } + ) + | Error e -> Error e + else + Ok(Seq.rev oks) + + loop oks + +/// +/// Applies a function to each element of a sequence and returns a single result +/// +/// The function to apply to each element +/// The input sequence +/// A result with the ok elements in a sequence or the first error occurring in the sequence +/// This function is equivalent to but applying and initial state of 'Seq.empty' +let traverseResultM f xs = traverseResultM' (Ok Seq.empty) f xs + +/// +/// Converts a sequence of results into a single result +/// +/// The input sequence +/// A result with the ok elements in a sequence or the first error occurring in the sequence +/// This function is equivalent to but auto-applying the 'id' function +let sequenceResultM xs = traverseResultM id xs + +/// +/// Applies a function to each element of a sequence and returns a single result +/// +/// The initial state +/// The function to apply to each element +/// The input sequence +/// A result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence +let inline traverseResultA' state ([] f: 'okInput -> Result<'okOutput, 'error>) xs = + let folder state x = + match state, f x with + | Error errors, Error e -> + Seq.append errors (Seq.singleton e) + |> Error + | Ok oks, Ok ok -> + Seq.append oks (Seq.singleton ok) + |> Ok + | Ok _, Error e -> + Seq.singleton e + |> Error + | Error _, Ok _ -> state + + Seq.fold folder state xs + +/// +/// Applies a function to each element of a sequence and returns a single result +/// +/// The function to apply to each element +/// The input sequence +/// A result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence +/// This function is equivalent to but applying and initial state of 'Seq.empty' +let traverseResultA f xs = traverseResultA' (Ok Seq.empty) f xs + +/// +/// Converts a sequence of results into a single result +/// +/// The input sequence +/// A result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence +/// This function is equivalent to but auto-applying the 'id' function +let sequenceResultA xs = traverseResultA id xs + +/// +/// Applies a function to each element of a sequence and returns a single async result +/// +/// The initial state +/// The function to apply to each element +/// The input sequence +/// An async result with the ok elements in a sequence or the first error occurring in the sequence +let inline traverseAsyncResultM' + state + ([] f: 'okInput -> Async>) + (xs: 'okInput seq) + = + async { + match! state with + | Error _ -> return! state | Ok oks -> use enumerator = xs.GetEnumerator() let rec loop oks = - if enumerator.MoveNext() then - match f enumerator.Current with - | Ok ok -> - loop ( - seq { - yield ok - yield! oks - } - ) - | Error e -> Error e - else - Ok(Seq.rev oks) - - loop oks - - /// - /// Applies a function to each element of a sequence and returns a single result - /// - /// The function to apply to each element - /// The input sequence - /// A result with the ok elements in a sequence or the first error occurring in the sequence - /// This function is equivalent to but applying and initial state of 'Seq.empty' - let traverseResultM f xs = traverseResultM' (Ok Seq.empty) f xs - - /// - /// Converts a sequence of results into a single result - /// - /// The input sequence - /// A result with the ok elements in a sequence or the first error occurring in the sequence - /// This function is equivalent to but auto-applying the 'id' function - let sequenceResultM xs = traverseResultM id xs - - /// - /// Applies a function to each element of a sequence and returns a single result - /// - /// The initial state - /// The function to apply to each element - /// The input sequence - /// A result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence - let inline traverseResultA' - state - ([] f: 'okInput -> Result<'okOutput, 'error>) - xs - = - let folder state x = - match state, f x with - | Error errors, Error e -> - Seq.append errors (Seq.singleton e) - |> Error - | Ok oks, Ok ok -> - Seq.append oks (Seq.singleton ok) - |> Ok - | Ok _, Error e -> - Seq.singleton e - |> Error - | Error _, Ok _ -> state - - Seq.fold folder state xs - - /// - /// Applies a function to each element of a sequence and returns a single result - /// - /// The function to apply to each element - /// The input sequence - /// A result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence - /// This function is equivalent to but applying and initial state of 'Seq.empty' - let traverseResultA f xs = traverseResultA' (Ok Seq.empty) f xs - - /// - /// Converts a sequence of results into a single result - /// - /// The input sequence - /// A result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence - /// This function is equivalent to but auto-applying the 'id' function - let sequenceResultA xs = traverseResultA id xs - - /// - /// Applies a function to each element of a sequence and returns a single async result - /// - /// The initial state - /// The function to apply to each element - /// The input sequence - /// An async result with the ok elements in a sequence or the first error occurring in the sequence - let inline traverseAsyncResultM' - state - ([] f: 'okInput -> Async>) - (xs: 'okInput seq) - = + async { + if enumerator.MoveNext() then + match! f enumerator.Current with + | Ok ok -> + return! + loop ( + seq { + yield ok + yield! oks + } + ) + | Error e -> return Error e + else + return Ok(Seq.rev oks) + } + + return! loop oks + } + +/// +/// Applies a function to each element of a sequence and returns a single async result +/// +/// The function to apply to each element +/// The input sequence +/// An async result with the ok elements in a sequence or the first error occurring in the sequence +/// This function is equivalent to but applying and initial state of 'Seq.empty' +let traverseAsyncResultM f xs = + traverseAsyncResultM' (async { return Ok Seq.empty }) f xs + +/// +/// Converts a sequence of async results into a single async result +/// +/// The input sequence +/// An async result with the ok elements in a sequence or the first error occurring in the sequence +/// This function is equivalent to but auto-applying the 'id' function +let sequenceAsyncResultM xs = traverseAsyncResultM id xs + +/// +/// Applies a function to each element of a sequence and returns a single async result +/// +/// The initial state +/// The function to apply to each element +/// The input sequence +/// An async result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence +let inline traverseAsyncResultA' + state + ([] f: 'okInput -> Async>) + xs + = + let folder state x = async { - match! state with - | Error _ -> return! state - | Ok oks -> - use enumerator = xs.GetEnumerator() - - let rec loop oks = - async { - if enumerator.MoveNext() then - match! f enumerator.Current with - | Ok ok -> - return! - loop ( - seq { - yield ok - yield! oks - } - ) - | Error e -> return Error e - else - return Ok(Seq.rev oks) - } - - return! loop oks + let! state = state + let! result = f x + + return + match state, result with + | Error errors, Error e -> + Seq.append errors (Seq.singleton e) + |> Error + | Ok oks, Ok ok -> + Seq.append oks (Seq.singleton ok) + |> Ok + | Ok _, Error e -> + Seq.singleton e + |> Error + | Error _, Ok _ -> state } - /// - /// Applies a function to each element of a sequence and returns a single async result - /// - /// The function to apply to each element - /// The input sequence - /// An async result with the ok elements in a sequence or the first error occurring in the sequence - /// This function is equivalent to but applying and initial state of 'Seq.empty' - let traverseAsyncResultM f xs = - traverseAsyncResultM' (async { return Ok Seq.empty }) f xs - - /// - /// Converts a sequence of async results into a single async result - /// - /// The input sequence - /// An async result with the ok elements in a sequence or the first error occurring in the sequence - /// This function is equivalent to but auto-applying the 'id' function - let sequenceAsyncResultM xs = traverseAsyncResultM id xs - - /// - /// Applies a function to each element of a sequence and returns a single async result - /// - /// The initial state - /// The function to apply to each element - /// The input sequence - /// An async result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence - let inline traverseAsyncResultA' - state - ([] f: 'okInput -> Async>) - xs - = - let folder state x = - async { - let! state = state - let! result = f x - - return - match state, result with - | Error errors, Error e -> - Seq.append errors (Seq.singleton e) - |> Error - | Ok oks, Ok ok -> - Seq.append oks (Seq.singleton ok) - |> Ok - | Ok _, Error e -> - Seq.singleton e - |> Error - | Error _, Ok _ -> state - } - - Seq.fold folder state xs - - /// - /// Applies a function to each element of a sequence and returns a single async result - /// - /// The function to apply to each element - /// The input sequence - /// An async result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence - /// This function is equivalent to but applying and initial state of 'Seq.empty' - let traverseAsyncResultA f xs = - traverseAsyncResultA' (async { return Ok Seq.empty }) f xs - - /// - /// Converts a sequence of async results into a single async result - /// - /// The input sequence - /// An async result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence - /// This function is equivalent to but auto-applying the 'id' function - let sequenceAsyncResultA xs = traverseAsyncResultA id xs - - /// - /// Applies a function to each element of a sequence and returns a single option - /// - /// The initial state - /// The function to apply to each element - /// The input sequence - /// An option containing Some sequence of elements or None if any of the function applications return None - let inline traverseOptionM' - state - ([] f: 'okInput -> 'okOutput option) - (xs: 'okInput seq) - = - match state with - | None -> state + Seq.fold folder state xs + +/// +/// Applies a function to each element of a sequence and returns a single async result +/// +/// The function to apply to each element +/// The input sequence +/// An async result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence +/// This function is equivalent to but applying and initial state of 'Seq.empty' +let traverseAsyncResultA f xs = + traverseAsyncResultA' (async { return Ok Seq.empty }) f xs + +/// +/// Converts a sequence of async results into a single async result +/// +/// The input sequence +/// An async result with the ok elements in a sequence or a sequence of all errors occuring in the original sequence +/// This function is equivalent to but auto-applying the 'id' function +let sequenceAsyncResultA xs = traverseAsyncResultA id xs + +/// +/// Applies a function to each element of a sequence and returns a single option +/// +/// The initial state +/// The function to apply to each element +/// The input sequence +/// An option containing Some sequence of elements or None if any of the function applications return None +let inline traverseOptionM' + state + ([] f: 'okInput -> 'okOutput option) + (xs: 'okInput seq) + = + match state with + | None -> state + | Some values -> + use enumerator = xs.GetEnumerator() + + let rec loop values = + if enumerator.MoveNext() then + match f enumerator.Current with + | Some value -> + loop ( + seq { + yield value + yield! values + } + ) + | None -> None + else + Some(Seq.rev values) + + loop values + +/// +/// Applies a function to each element of a sequence and returns a single option +/// +/// The function to apply to each element +/// The input sequence +/// An option containing Some sequence of elements or None if any of the function applications return None +/// This function is equivalent to but applying and initial state of 'Seq.empty' +let traverseOptionM f xs = traverseOptionM' (Some Seq.empty) f xs + +/// +/// Converts a sequence of options into a single option +/// +/// The input sequence +/// An option containing Some sequence of elements or None if any of the function applications return None +/// This function is equivalent to but auto-applying the 'id' function +let sequenceOptionM xs = traverseOptionM id xs + +/// +/// Applies a function to each element of a sequence and returns a single async option +/// +/// The initial state +/// The function to apply to each element +/// The input sequence +/// An async option containing Some sequence of elements or None if any of the function applications return None +let inline traverseAsyncOptionM' + state + ([] f: 'okInput -> Async<'okOutput option>) + (xs: 'okInput seq) + = + async { + match! state with + | None -> return! state | Some values -> use enumerator = xs.GetEnumerator() let rec loop values = - if enumerator.MoveNext() then - match f enumerator.Current with - | Some value -> - loop ( - seq { - yield value - yield! values - } - ) - | None -> None - else - Some(Seq.rev values) - - loop values - - /// - /// Applies a function to each element of a sequence and returns a single option - /// - /// The function to apply to each element - /// The input sequence - /// An option containing Some sequence of elements or None if any of the function applications return None - /// This function is equivalent to but applying and initial state of 'Seq.empty' - let traverseOptionM f xs = traverseOptionM' (Some Seq.empty) f xs - - /// - /// Converts a sequence of options into a single option - /// - /// The input sequence - /// An option containing Some sequence of elements or None if any of the function applications return None - /// This function is equivalent to but auto-applying the 'id' function - let sequenceOptionM xs = traverseOptionM id xs - - /// - /// Applies a function to each element of a sequence and returns a single async option - /// - /// The initial state - /// The function to apply to each element - /// The input sequence - /// An async option containing Some sequence of elements or None if any of the function applications return None - let inline traverseAsyncOptionM' - state - ([] f: 'okInput -> Async<'okOutput option>) - (xs: 'okInput seq) - = - async { - match! state with - | None -> return! state - | Some values -> - use enumerator = xs.GetEnumerator() - - let rec loop values = - async { - if enumerator.MoveNext() then - match! f enumerator.Current with - | Some value -> - return! - loop ( - seq { - yield value - yield! values - } - ) - | None -> return None - else - return Some(Seq.rev values) - } - - return! loop values - } - - /// - /// Applies a function to each element of a sequence and returns a single async option - /// - /// The function to apply to each element - /// The input sequence - /// An async option containing Some sequence of elements or None if any of the function applications return None - /// This function is equivalent to but applying and initial state of 'Async { return Some Seq.empty }' - let traverseAsyncOptionM f xs = - traverseAsyncOptionM' (async { return Some Seq.empty }) f xs - - /// - /// Converts a sequence of async options into a single async option - /// - /// The input sequence - /// An async option containing Some sequence of elements or None if any of the function applications return None - /// This function is equivalent to but auto-applying the 'id' function - let sequenceAsyncOptionM xs = traverseAsyncOptionM id xs + async { + if enumerator.MoveNext() then + match! f enumerator.Current with + | Some value -> + return! + loop ( + seq { + yield value + yield! values + } + ) + | None -> return None + else + return Some(Seq.rev values) + } + + return! loop values + } + +/// +/// Applies a function to each element of a sequence and returns a single async option +/// +/// The function to apply to each element +/// The input sequence +/// An async option containing Some sequence of elements or None if any of the function applications return None +/// This function is equivalent to but applying and initial state of 'Async { return Some Seq.empty }' +let traverseAsyncOptionM f xs = + traverseAsyncOptionM' (async { return Some Seq.empty }) f xs + +/// +/// Converts a sequence of async options into a single async option +/// +/// The input sequence +/// An async option containing Some sequence of elements or None if any of the function applications return None +/// This function is equivalent to but auto-applying the 'id' function +let sequenceAsyncOptionM xs = traverseAsyncOptionM id xs #if !FABLE_COMPILER - /// - /// Applies a function to each element of a sequence and returns a single voption - /// - /// The initial state - /// The function to apply to each element - /// The input sequence - /// A voption containing Some sequence of elements or None if any of the function applications return None - let inline traverseVOptionM' - state - ([] f: 'okInput -> 'okOutput voption) - (xs: 'okInput seq) - = - match state with - | ValueNone -> state - | ValueSome values -> - use enumerator = xs.GetEnumerator() - - let rec loop values = - if enumerator.MoveNext() then - match f enumerator.Current with - | ValueSome value -> - loop ( - seq { - yield value - yield! values - } - ) - | ValueNone -> ValueNone - else - ValueSome(Seq.rev values) - - loop values - - /// - /// Applies a function to each element of a sequence and returns a single voption - /// - /// The function to apply to each element - /// The input sequence - /// A voption containing Some sequence of elements or None if any of the function applications return None - /// This function is equivalent to but applying and initial state of 'ValueSome Seq.empty' - let traverseVOptionM f xs = - traverseVOptionM' (ValueSome Seq.empty) f xs - - /// - /// Converts a sequence of voptions into a single voption - /// - /// The input sequence - /// A voption containing Some sequence of elements or None if any of the function applications return None - /// This function is equivalent to but auto-applying the 'id' function - let sequenceVOptionM xs = traverseVOptionM id xs +/// +/// Applies a function to each element of a sequence and returns a single voption +/// +/// The initial state +/// The function to apply to each element +/// The input sequence +/// A voption containing Some sequence of elements or None if any of the function applications return None +let inline traverseVOptionM' + state + ([] f: 'okInput -> 'okOutput voption) + (xs: 'okInput seq) + = + match state with + | ValueNone -> state + | ValueSome values -> + use enumerator = xs.GetEnumerator() + + let rec loop values = + if enumerator.MoveNext() then + match f enumerator.Current with + | ValueSome value -> + loop ( + seq { + yield value + yield! values + } + ) + | ValueNone -> ValueNone + else + ValueSome(Seq.rev values) + + loop values + +/// +/// Applies a function to each element of a sequence and returns a single voption +/// +/// The function to apply to each element +/// The input sequence +/// A voption containing Some sequence of elements or None if any of the function applications return None +/// This function is equivalent to but applying and initial state of 'ValueSome Seq.empty' +let traverseVOptionM f xs = + traverseVOptionM' (ValueSome Seq.empty) f xs + +/// +/// Converts a sequence of voptions into a single voption +/// +/// The input sequence +/// A voption containing Some sequence of elements or None if any of the function applications return None +/// This function is equivalent to but auto-applying the 'id' function +let sequenceVOptionM xs = traverseVOptionM id xs #endif diff --git a/src/FsToolkit.ErrorHandling/TaskOptionCE.fs b/src/FsToolkit.ErrorHandling/TaskOptionCE.fs index 69e59823..8f448e07 100644 --- a/src/FsToolkit.ErrorHandling/TaskOptionCE.fs +++ b/src/FsToolkit.ErrorHandling/TaskOptionCE.fs @@ -76,10 +76,8 @@ type TaskOptionBuilderBase() = /// Note that this requires that the first step has no result. /// This prevents constructs like `task { return 1; return 2; }`. member inline _.Combine - ( - task1: TaskOptionCode<'TOverall, unit>, - task2: TaskOptionCode<'TOverall, 'T> - ) : TaskOptionCode<'TOverall, 'T> = + (task1: TaskOptionCode<'TOverall, unit>, task2: TaskOptionCode<'TOverall, 'T>) + : TaskOptionCode<'TOverall, 'T> = ResumableCode.Combine( task1, @@ -90,10 +88,8 @@ type TaskOptionBuilderBase() = /// Builds a step that executes the body while the condition predicate is true. member inline _.While - ( - [] condition: unit -> bool, - body: TaskOptionCode<'TOverall, unit> - ) : TaskOptionCode<'TOverall, unit> = + ([] condition: unit -> bool, body: TaskOptionCode<'TOverall, unit>) + : TaskOptionCode<'TOverall, unit> = let mutable keepGoing = true ResumableCode.While( @@ -115,19 +111,15 @@ type TaskOptionBuilderBase() = /// Wraps a step in a try/with. This catches exceptions both in the evaluation of the function /// to retrieve the step, and in the continuation of the step (if any). member inline _.TryWith - ( - body: TaskOptionCode<'TOverall, 'T>, - catch: exn -> TaskOptionCode<'TOverall, 'T> - ) : TaskOptionCode<'TOverall, 'T> = + (body: TaskOptionCode<'TOverall, 'T>, catch: exn -> TaskOptionCode<'TOverall, 'T>) + : TaskOptionCode<'TOverall, 'T> = ResumableCode.TryWith(body, catch) /// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function /// to retrieve the step, and in the continuation of the step (if any). member inline _.TryFinally - ( - body: TaskOptionCode<'TOverall, 'T>, - [] compensation: unit -> unit - ) : TaskOptionCode<'TOverall, 'T> = + (body: TaskOptionCode<'TOverall, 'T>, [] compensation: unit -> unit) + : TaskOptionCode<'TOverall, 'T> = ResumableCode.TryFinally( body, ResumableCode<_, _>(fun _sm -> @@ -137,10 +129,8 @@ type TaskOptionBuilderBase() = ) member inline this.For - ( - sequence: seq<'T>, - body: 'T -> TaskOptionCode<'TOverall, unit> - ) : TaskOptionCode<'TOverall, unit> = + (sequence: seq<'T>, body: 'T -> TaskOptionCode<'TOverall, unit>) + : TaskOptionCode<'TOverall, unit> = ResumableCode.Using( sequence.GetEnumerator(), // ... and its body is a while loop that advances the enumerator and runs the body on each element. @@ -153,10 +143,8 @@ type TaskOptionBuilderBase() = ) member inline internal this.TryFinallyAsync - ( - body: TaskOptionCode<'TOverall, 'T>, - compensation: unit -> ValueTask - ) : TaskOptionCode<'TOverall, 'T> = + (body: TaskOptionCode<'TOverall, 'T>, compensation: unit -> ValueTask) + : TaskOptionCode<'TOverall, 'T> = ResumableCode.TryFinallyAsync( body, ResumableCode<_, _>(fun sm -> @@ -198,10 +186,8 @@ type TaskOptionBuilderBase() = ) member inline this.Using<'Resource, 'TOverall, 'T when 'Resource :> IAsyncDisposable> - ( - resource: 'Resource, - body: 'Resource -> TaskOptionCode<'TOverall, 'T> - ) : TaskOptionCode<'TOverall, 'T> = + (resource: 'Resource, body: 'Resource -> TaskOptionCode<'TOverall, 'T>) + : TaskOptionCode<'TOverall, 'T> = this.TryFinallyAsync( (fun sm -> (body resource).Invoke(&sm)), (fun () -> @@ -425,10 +411,8 @@ module TaskOptionCEExtensionsLowPriority = and ^Awaiter :> ICriticalNotifyCompletion and ^Awaiter: (member get_IsCompleted: unit -> bool) and ^Awaiter: (member GetResult: unit -> 'TResult1 option)> - ( - task: ^TaskLike, - continuation: ('TResult1 -> TaskOptionCode<'TOverall, 'TResult2>) - ) : TaskOptionCode<'TOverall, 'TResult2> = + (task: ^TaskLike, continuation: ('TResult1 -> TaskOptionCode<'TOverall, 'TResult2>)) + : TaskOptionCode<'TOverall, 'TResult2> = TaskOptionCode<'TOverall, _>(fun sm -> if __useResumableCode then @@ -457,7 +441,13 @@ module TaskOptionCEExtensionsLowPriority = sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm) false else - TaskOptionBuilderBase.BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall>( + TaskOptionBuilderBase.BindDynamic< + ^TaskLike, + 'TResult1, + 'TResult2, + ^Awaiter, + 'TOverall + >( &sm, task, continuation @@ -491,10 +481,8 @@ module TaskOptionCEExtensionsLowPriority = } member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IDisposable> - ( - resource: 'Resource, - body: 'Resource -> TaskOptionCode<'TOverall, 'T> - ) = + (resource: 'Resource, body: 'Resource -> TaskOptionCode<'TOverall, 'T>) + = ResumableCode.Using(resource, body) [] diff --git a/src/FsToolkit.ErrorHandling/TaskResultCE.fs b/src/FsToolkit.ErrorHandling/TaskResultCE.fs index f0a87aa7..6f6befaf 100644 --- a/src/FsToolkit.ErrorHandling/TaskResultCE.fs +++ b/src/FsToolkit.ErrorHandling/TaskResultCE.fs @@ -85,10 +85,12 @@ type TaskResultBuilderBase() = /// Builds a step that executes the body while the condition predicate is true. member inline _.While - ( - [] condition: unit -> bool, - body: TaskResultCode<'TOverall, 'Error, unit> - ) : TaskResultCode<'TOverall, 'Error, unit> = + ([] condition: unit -> bool, body: TaskResultCode<'TOverall, 'Error, unit>) : TaskResultCode< + 'TOverall, + 'Error, + unit + > + = let mutable keepGoing = true ResumableCode.While( @@ -120,10 +122,12 @@ type TaskResultBuilderBase() = /// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function /// to retrieve the step, and in the continuation of the step (if any). member inline _.TryFinally - ( - body: TaskResultCode<'TOverall, 'Error, 'T>, - [] compensation: unit -> unit - ) : TaskResultCode<'TOverall, 'Error, 'T> = + (body: TaskResultCode<'TOverall, 'Error, 'T>, [] compensation: unit -> unit) : TaskResultCode< + 'TOverall, + 'Error, + 'T + > + = // printfn "TryFinally Called --> " @@ -136,10 +140,8 @@ type TaskResultBuilderBase() = ) member inline this.For - ( - sequence: seq<'T>, - body: 'T -> TaskResultCode<'TOverall, 'Error, unit> - ) : TaskResultCode<'TOverall, 'Error, unit> = + (sequence: seq<'T>, body: 'T -> TaskResultCode<'TOverall, 'Error, unit>) + : TaskResultCode<'TOverall, 'Error, unit> = // A for loop is just a using statement on the sequence's enumerator... ResumableCode.Using( sequence.GetEnumerator(), @@ -153,10 +155,8 @@ type TaskResultBuilderBase() = ) member inline internal this.TryFinallyAsync - ( - body: TaskResultCode<'TOverall, 'Error, 'T>, - compensation: unit -> ValueTask - ) : TaskResultCode<'TOverall, 'Error, 'T> = + (body: TaskResultCode<'TOverall, 'Error, 'T>, compensation: unit -> ValueTask) + : TaskResultCode<'TOverall, 'Error, 'T> = ResumableCode.TryFinallyAsync( body, ResumableCode<_, _>(fun sm -> @@ -200,10 +200,8 @@ type TaskResultBuilderBase() = ) member inline this.Using<'Resource, 'TOverall, 'T, 'Error when 'Resource :> IAsyncDisposable> - ( - resource: 'Resource, - body: 'Resource -> TaskResultCode<'TOverall, 'Error, 'T> - ) : TaskResultCode<'TOverall, 'Error, 'T> = + (resource: 'Resource, body: 'Resource -> TaskResultCode<'TOverall, 'Error, 'T>) + : TaskResultCode<'TOverall, 'Error, 'T> = this.TryFinallyAsync( (fun sm -> (body resource).Invoke(&sm)), (fun () -> @@ -479,7 +477,13 @@ module TaskResultCEExtensionsLowPriority = sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm) false else - TaskResultBuilderBase.BindDynamic<'TResult1, 'TResult2, ^Awaiter, 'TOverall, 'Error>( + TaskResultBuilderBase.BindDynamic< + 'TResult1, + 'TResult2, + ^Awaiter, + 'TOverall, + 'Error + >( &sm, awaiter, continuation @@ -532,10 +536,8 @@ module TaskResultCEExtensionsLowPriority = } member inline _.Using<'Resource, 'TOverall, 'T, 'Error when 'Resource :> IDisposable> - ( - resource: 'Resource, - body: 'Resource -> TaskResultCode<'TOverall, 'Error, 'T> - ) = + (resource: 'Resource, body: 'Resource -> TaskResultCode<'TOverall, 'Error, 'T>) + = ResumableCode.Using(resource, body) [] diff --git a/src/FsToolkit.ErrorHandling/TaskResultOptionCE.fs b/src/FsToolkit.ErrorHandling/TaskResultOptionCE.fs index e80d0513..ded83937 100644 --- a/src/FsToolkit.ErrorHandling/TaskResultOptionCE.fs +++ b/src/FsToolkit.ErrorHandling/TaskResultOptionCE.fs @@ -207,7 +207,10 @@ module TaskResultOptionCE = (code: TaskResultOptionCode<'T, 'Error, 'T>) : TaskResultOption<'T, 'Error> = if __useResumableCode then - __stateMachine, TaskResultOption<'T, 'Error>> + __stateMachine< + TaskResultOptionStateMachineData<'T, 'Error>, + TaskResultOption<'T, 'Error> + > (MoveNextMethodImpl<_>(fun sm -> //-- RESUMABLE CODE START __resumeAt sm.ResumptionPoint diff --git a/src/FsToolkit.ErrorHandling/ValidationCE.fs b/src/FsToolkit.ErrorHandling/ValidationCE.fs index f6713ca9..d63f4ea9 100644 --- a/src/FsToolkit.ErrorHandling/ValidationCE.fs +++ b/src/FsToolkit.ErrorHandling/ValidationCE.fs @@ -88,27 +88,24 @@ module ValidationCE = result member inline this.For - ( - sequence: #seq<'ok>, - [] binder: 'ok -> Validation - ) : Validation = + (sequence: #seq<'ok>, [] binder: 'ok -> Validation) + : Validation = this.Using( sequence.GetEnumerator(), fun enum -> this.While(enum.MoveNext, this.Delay(fun () -> binder enum.Current)) ) member inline _.BindReturn - ( - input: Validation<'okInput, 'error>, - [] mapper: 'okInput -> 'okOutput - ) : Validation<'okOutput, 'error> = + (input: Validation<'okInput, 'error>, [] mapper: 'okInput -> 'okOutput) : Validation< + 'okOutput, + 'error + > + = Validation.map mapper input member inline _.MergeSources - ( - left: Validation<'left, 'error>, - right: Validation<'right, 'error> - ) : Validation<'left * 'right, 'error> = + (left: Validation<'left, 'error>, right: Validation<'right, 'error>) + : Validation<'left * 'right, 'error> = Validation.zip left right /// diff --git a/src/FsToolkit.ErrorHandling/ValueOptionCE.fs b/src/FsToolkit.ErrorHandling/ValueOptionCE.fs index 9b570098..8029dee8 100644 --- a/src/FsToolkit.ErrorHandling/ValueOptionCE.fs +++ b/src/FsToolkit.ErrorHandling/ValueOptionCE.fs @@ -12,27 +12,20 @@ module ValueOptionCE = member inline _.ReturnFrom(m: 'value voption) : 'value voption = m member inline _.Bind - ( - input: 'input voption, - [] binder: 'input -> 'output voption - ) : 'output voption = + (input: 'input voption, [] binder: 'input -> 'output voption) + : 'output voption = ValueOption.bind binder input // Could not get it to work solely with Source. In loop cases it would potentially match the #seq overload and ask for type annotation member inline this.Bind - ( - input: 'input when 'input: null, - [] binder: 'input -> 'output voption - ) : 'output voption = + (input: 'input when 'input: null, [] binder: 'input -> 'output voption) : 'output voption = this.Bind(ValueOption.ofObj input, binder) member inline this.Zero() : unit voption = this.Return() member inline _.Combine - ( - input: 'input voption, - [] binder: 'input -> 'output voption - ) : 'output voption = + (input: 'input voption, [] binder: 'input -> 'output voption) + : 'output voption = ValueOption.bind binder input member inline this.Combine(input: unit voption, output: 'output voption) : 'output voption = @@ -55,10 +48,8 @@ module ValueOptionCE = compensation () member inline this.Using - ( - resource: 'T :> IDisposable, - [] binder - ) : _ voption = + (resource: 'T :> IDisposable, [] binder) + : _ voption = this.TryFinally( (fun () -> binder resource), (fun () -> @@ -68,10 +59,7 @@ module ValueOptionCE = ) member inline this.While - ( - [] guard: unit -> bool, - [] generator: unit -> _ voption - ) : _ voption = + ([] guard: unit -> bool, [] generator: unit -> _ voption) : _ voption = let mutable doContinue = true let mutable result = ValueSome() @@ -87,10 +75,8 @@ module ValueOptionCE = result member inline this.For - ( - sequence: #seq<'T>, - [] binder: 'T -> _ voption - ) : _ voption = + (sequence: #seq<'T>, [] binder: 'T -> _ voption) + : _ voption = this.Using( sequence.GetEnumerator(), fun enum -> this.While(enum.MoveNext, this.Delay(fun () -> binder enum.Current))