diff --git a/src/FsToolkit.ErrorHandling/AsyncValidationCE.fs b/src/FsToolkit.ErrorHandling/AsyncValidationCE.fs index aa64e4f7..7eef703a 100644 --- a/src/FsToolkit.ErrorHandling/AsyncValidationCE.fs +++ b/src/FsToolkit.ErrorHandling/AsyncValidationCE.fs @@ -23,82 +23,53 @@ module AsyncValidationCE = member inline this.Zero() : AsyncValidation = this.Return() member inline _.Delay - ([] generator: unit -> AsyncValidation<'ok, 'error>) - : unit -> AsyncValidation<'ok, 'error> = - generator - - member inline _.Run ([] generator: unit -> AsyncValidation<'ok, 'error>) : AsyncValidation<'ok, 'error> = - generator () + async.Delay generator member inline this.Combine ( - result: AsyncValidation, - [] binder: unit -> AsyncValidation<'ok, 'error> + validation1: AsyncValidation, + validation2: AsyncValidation<'ok, 'error> ) : AsyncValidation<'ok, 'error> = - this.Bind(result, binder) + this.Bind(validation1, (fun () -> validation2)) - member inline this.TryWith + member inline _.TryWith ( - [] generator: unit -> AsyncValidation<'ok, 'error>, + computation: AsyncValidation<'ok, 'error>, [] handler: exn -> AsyncValidation<'ok, 'error> ) : AsyncValidation<'ok, 'error> = - async { - return! - try - this.Run generator - with e -> - handler e - } - - member inline this.TryFinally + async.TryWith(computation, handler) + + member inline _.TryFinally ( - [] generator: unit -> AsyncValidation<'ok, 'error>, + computation: AsyncValidation<'ok, 'error>, [] compensation: unit -> unit ) : AsyncValidation<'ok, 'error> = - async { - return! - try - this.Run generator - finally - compensation () - } - - member inline this.Using + async.TryFinally(computation, compensation) + + member inline _.Using ( resource: 'disposable :> IDisposable, [] binder: 'disposable -> AsyncValidation<'okOutput, 'error> ) : AsyncValidation<'okOutput, 'error> = - this.TryFinally( - (fun () -> binder resource), - (fun () -> - if not (obj.ReferenceEquals(resource, null)) then - resource.Dispose() - ) - ) + async.Using(resource, binder) member inline this.While ( [] guard: unit -> bool, - [] generator: unit -> AsyncValidation + computation: AsyncValidation ) : AsyncValidation = - let mutable doContinue = true - let mutable result = Ok() - - async { - while doContinue - && guard () do - let! x = generator () - - match x with - | Ok() -> () - | Error e -> - doContinue <- false - result <- Error e - - return result - } + if guard () then + let mutable whileAsync = Unchecked.defaultof<_> + + whileAsync <- + this.Bind(computation, (fun () -> if guard () then whileAsync else this.Zero())) + + whileAsync + else + this.Zero() + member inline this.For ( diff --git a/tests/FsToolkit.ErrorHandling.Tests/AsyncValidationCE.fs b/tests/FsToolkit.ErrorHandling.Tests/AsyncValidationCE.fs index b1125bf4..31ece1a8 100644 --- a/tests/FsToolkit.ErrorHandling.Tests/AsyncValidationCE.fs +++ b/tests/FsToolkit.ErrorHandling.Tests/AsyncValidationCE.fs @@ -279,9 +279,9 @@ let ``AsyncValidationCE try Tests`` = } ] -let makeDisposable () = +let makeDisposable callback = { new System.IDisposable with - member this.Dispose() = () + member _.Dispose() = callback () } let ``AsyncValidationCE using Tests`` = @@ -289,30 +289,39 @@ let ``AsyncValidationCE using Tests`` = testCaseAsync "use normal disposable" <| async { let data = 42 + let mutable isFinished = false let! actual = asyncValidation { - use d = makeDisposable () + use d = makeDisposable (fun () -> isFinished <- true) return data } - Expect.equal actual (Ok data) "Should be ok" + Expect.equal actual (Result.Ok data) "Should be ok" + Expect.isTrue isFinished "" } + testCaseAsync "use! normal wrapped disposable" <| async { let data = 42 + let mutable isFinished = false let! actual = asyncValidation { use! d = - makeDisposable () + makeDisposable (fun () -> isFinished <- true) |> Ok return data } Expect.equal actual (Ok data) "Should be ok" + Expect.isTrue isFinished "" } + +#if !FABLE_COMPILER && NETSTANDARD2_1 + // Fable can't handle null disposables you get + // TypeError: Cannot read property 'Dispose' of null testCaseAsync "use null disposable" <| async { let data = 42 @@ -325,6 +334,7 @@ let ``AsyncValidationCE using Tests`` = Expect.equal actual (Ok data) "Should be ok" } +#endif ] let ``AsyncValidationCE loop Tests`` =