@@ -373,6 +373,46 @@ module AsyncResult =
373
373
let ofTaskCatch f x : AsyncResult < _ , _ > =
374
374
x |> ofTask |> catch f
375
375
376
+ /// Run asyncResults in Parallel, handles the errors and concats results
377
+ let ofParallelAsyncResults < 'Success , 'Error > ( f : exn -> 'Error ) ( results : AsyncResult < 'Success , 'Error > list ): AsyncResult < 'Success list , 'Error list > =
378
+ results
379
+ |> List.map ( mapError List.singleton)
380
+ |> Async.Parallel
381
+ |> ofAsyncCatch ( f >> List.singleton)
382
+ |> bind (
383
+ Seq.toList
384
+ >> Validation.ofResults
385
+ >> Result.mapError List.concat
386
+ >> ofResult
387
+ )
388
+
389
+ /// Run asyncs in Parallel, handles the errors and concats results
390
+ let ofParallelAsyncs < 'Success , 'Error > ( f : exn -> 'Error ) ( asyncs : Async < 'Success > list ): AsyncResult < 'Success list , 'Error list > =
391
+ asyncs
392
+ |> Async.Parallel
393
+ |> ofAsyncCatch ( f >> List.singleton)
394
+ |> map Seq.toList
395
+
396
+ /// Run asyncResults in Parallel, handles the errors and concats results
397
+ let ofSequentialAsyncResults < 'Success , 'Error > ( f : exn -> 'Error ) ( results : AsyncResult < 'Success , 'Error > list ): AsyncResult < 'Success list , 'Error list > =
398
+ results
399
+ |> List.map ( mapError List.singleton)
400
+ |> Async.Sequential
401
+ |> ofAsyncCatch ( f >> List.singleton)
402
+ |> bind (
403
+ Seq.toList
404
+ >> Validation.ofResults
405
+ >> Result.mapError List.concat
406
+ >> ofResult
407
+ )
408
+
409
+ /// Run asyncs in Parallel, handles the errors and concats results
410
+ let ofSequentialAsyncs < 'Success , 'Error > ( f : exn -> 'Error ) ( asyncs : Async < 'Success > list ): AsyncResult < 'Success list , 'Error list > =
411
+ asyncs
412
+ |> Async.Sequential
413
+ |> ofAsyncCatch ( f >> List.singleton)
414
+ |> map Seq.toList
415
+
376
416
//-----------------------------------
377
417
// Utilities lifted from Async
378
418
@@ -405,44 +445,43 @@ module AsyncResult =
405
445
/// The `asyncResult` computation expression is available globally without qualification
406
446
[<AutoOpen>]
407
447
module AsyncResultComputationExpression =
448
+ open System
408
449
409
450
type AsyncResultBuilder () =
410
- member __.Return ( x ) = AsyncResult.retn x
411
- member __.Bind ( x , f ) = AsyncResult.bind f x
451
+ member __.Return ( value : 'Success ): AsyncResult < 'Success , 'Error > =
452
+ async.Return <| result.Return value
412
453
413
- member __.ReturnFrom ( x ) = x
414
- member this.Zero () = this.Return ()
454
+ member __.ReturnFrom ( asyncResult : AsyncResult < 'Success , 'Error >): AsyncResult < 'Success , 'Error > =
455
+ asyncResult
415
456
416
- member __.Delay ( f ) = f
417
- member __.Run ( f ) = f ()
457
+ member __.Zero (): AsyncResult < unit , 'Error > =
458
+ async.Return <| result.Zero ()
418
459
419
- member this.While ( guard , body ) =
420
- if not ( guard())
421
- then this.Zero()
422
- else this.Bind( body(), fun () ->
423
- this.While( guard, body))
460
+ member __.Bind ( asyncResult : AsyncResult < 'SuccessA , 'Error >, ( f : 'SuccessA -> AsyncResult < 'SuccessB , 'Error >)): AsyncResult < 'SuccessB , 'Error > =
461
+ asyncResult |> AsyncResult.bind f
424
462
425
- member this.TryWith ( body , handler ) =
426
- try this.ReturnFrom( body())
427
- with e -> handler e
463
+ member __.Delay ( generator : unit -> AsyncResult < 'Success , 'Error >): AsyncResult < 'Success , 'Error > =
464
+ async.Delay generator
428
465
429
- member this.TryFinally ( body , compensation ) =
430
- try this.ReturnFrom( body())
431
- finally compensation()
466
+ member this.Combine ( computation1 : AsyncResult < unit , 'Error >, computation2 : AsyncResult < 'U , 'Error >): AsyncResult < 'U , 'Error > =
467
+ this.Bind( computation1, fun () -> computation2)
432
468
433
- member this.Using ( disposable : #System.IDisposable , body ) =
434
- let body ' = fun () -> body disposable
435
- this.TryFinally( body', fun () ->
436
- match disposable with
437
- | null -> ()
438
- | disp -> disp.Dispose())
469
+ member __.TryWith ( computation : AsyncResult < 'Success , 'Error >, handler : exn -> AsyncResult < 'Success , 'Error >): AsyncResult < 'Success , 'Error > =
470
+ async.TryWith( computation, handler)
439
471
440
- member this.For ( sequence : seq < _ >, body ) =
441
- this.Using( sequence.GetEnumerator(), fun enum ->
442
- this.While( enum .MoveNext,
443
- this.Delay( fun () -> body enum .Current)))
472
+ member __.TryFinally ( computation : AsyncResult < 'Success , 'Error >, compensation : unit -> unit ): AsyncResult < 'Success , 'Error > =
473
+ async.TryFinally( computation, compensation)
444
474
445
- member this.Combine ( a , b ) =
446
- this.Bind( a, fun () -> b())
475
+ member __.Using ( resource : 'SuccessA when 'SuccessA :> IDisposable , binder : 'SuccessA -> AsyncResult < 'SuccessB , 'Error >): AsyncResult < 'SuccessB , 'Error > =
476
+ async.Using( resource, binder)
477
+
478
+ member this.While ( guard : unit -> bool , computation : AsyncResult < unit , 'Error >): AsyncResult < unit , 'Error > =
479
+ if not <| guard () then this.Zero ()
480
+ else this.Bind( computation, fun () -> this.While ( guard, computation))
481
+
482
+ member this.For ( sequence : #seq<'Success> , binder : 'Success -> AsyncResult < unit , 'Error >): AsyncResult < unit , 'Error > =
483
+ this.Using( sequence.GetEnumerator (), fun enum ->
484
+ this.While( enum .MoveNext,
485
+ this.Delay( fun () -> binder enum .Current)))
447
486
448
487
let asyncResult = AsyncResultBuilder()
0 commit comments