@@ -4,28 +4,43 @@ open System
44open BenchmarkDotNet
55open BenchmarkDotNet.Attributes
66open FsToolkit.ErrorHandling
7+
78module AsyncResultCE =
89
910
1011 type AsyncResultInlinedLambdaBuilder () =
1112
12- member _.Return ( value : 'T ) : Async < Result < 'T , 'TError >> = async.Return <| result.Return value
13+ member _.Return ( value : 'T ) : Async < Result < 'T , 'TError >> =
14+ async.Return
15+ <| result.Return value
1316
14- member inline _.ReturnFrom ( asyncResult : Async < Result < 'T , 'TError >>) : Async < Result < 'T , 'TError >> = asyncResult
17+ member inline _.ReturnFrom
18+ ( asyncResult : Async < Result < 'T , 'TError >>)
19+ : Async < Result < 'T , 'TError >> =
20+ asyncResult
1521
16- member _.Zero () : Async < Result < unit , 'TError >> = async.Return <| result.Zero()
22+ member _.Zero () : Async < Result < unit , 'TError >> =
23+ async.Return
24+ <| result.Zero()
1725
1826 member inline _.Bind
1927 (
2028 asyncResult : Async < Result < 'T , 'TError >>,
2129 [<InlineIfLambda>] binder : 'T -> Async < Result < 'U , 'TError >>
2230 ) : Async < Result < 'U , 'TError >> =
23- async.Bind( asyncResult, fun r ->
24- match r with
25- | Ok x -> binder x
26- | Error e -> Error e |> async.Return
31+ async.Bind(
32+ asyncResult,
33+ fun r ->
34+ match r with
35+ | Ok x -> binder x
36+ | Error e ->
37+ Error e
38+ |> async.Return
2739 )
28- member inline _.Delay ( [<InlineIfLambda>] generator : unit -> Async < Result < 'T , 'TError >>) : Async < Result < 'T , 'TError >> =
40+
41+ member inline _.Delay
42+ ( [<InlineIfLambda>] generator : unit -> Async < Result < 'T , 'TError >>)
43+ : Async < Result < 'T , 'TError >> =
2944 async.Delay generator
3045
3146 /// <summary>
@@ -34,9 +49,8 @@ module AsyncResultCE =
3449 /// See https://stackoverflow.com/questions/35286541/why-would-you-use-builder-source-in-a-custom-computation-expression-builder
3550 /// </summary>
3651 member inline _.Source ( result : Async < Result < _ , _ >>) : Async < Result < _ , _ >> = result
37- open AsyncResultCE
38-
3952
53+ open AsyncResultCE
4054
4155
4256[<AutoOpen>]
@@ -45,6 +59,7 @@ open AsyncResultCE
4559module AsyncResultCEExtensions =
4660
4761 type AsyncResultInlinedLambdaBuilder with
62+
4863 /// <summary>
4964 /// Needed to allow `for..in` and `for..do` functionality
5065 /// </summary>
@@ -54,55 +69,69 @@ module AsyncResultCEExtensions =
5469 /// Method lets us transform data types into our internal representation.
5570 /// </summary>
5671 member inline _.Source ( result : Result < _ , _ >) : Async < Result < _ , _ >> = Async.singleton result
72+
5773 let rec fib n =
58- if n < 2 L then n
59- else fib ( n - 1 L) + fib ( n - 2 L)
60-
61- let rec afib ( n , level ) = async {
62- if n < 0 L then return Error " No"
63- elif n < 2 L then
64- return Ok n
65- elif n < level then
66- return Ok ( fib n)
74+ if n < 2 L then
75+ n
6776 else
68- let! n2a = afib ( n-2 L, level) |> Async.StartChild
69- let! n1 = afib ( n-1 L, level)
70- let! n2 = n2a
71- match n1, n2 with
72- | Ok n1, Ok n2 ->
73- return Ok ( n2 + n1)
74- | Error e, _
75- | _, Error e -> return Error e
77+ fib ( n - 1 L)
78+ + fib ( n - 2 L)
79+
80+ let rec afib ( n , level ) =
81+ async {
82+ if n < 0 L then
83+ return Error " No"
84+ elif n < 2 L then
85+ return Ok n
86+ elif n < level then
87+ return Ok( fib n)
88+ else
89+ let! n2a =
90+ afib ( n - 2 L, level)
91+ |> Async.StartChild
92+
93+ let! n1 = afib ( n - 1 L, level)
94+ let! n2 = n2a
95+
96+ match n1, n2 with
97+ | Ok n1, Ok n2 -> return Ok( n2 + n1)
98+ | Error e, _
99+ | _, Error e -> return Error e
76100 }
101+
77102 let asyncResultInlinedIfLambda = AsyncResultInlinedLambdaBuilder()
78103
79104 [<MemoryDiagnoser>]
80- type AsyncResult_BindCEBenchmarks () =
105+ type AsyncResult_BindCEBenchmarks () =
81106
82107 [<Benchmark( Baseline = true ) >]
83- member this.afib () =
84- afib( 10 , 5 )
108+ member this.afib () =
109+ afib ( 10 , 5 )
85110 |> Async.StartImmediateAsTask
86111
87112 [<Benchmark>]
88- member this.Result_Normal_Bind_CE () =
89- let action () = asyncResult {
90- let! a = Ok 10
91- let! b = Ok 5
92- let! c = afib( a, b)
93- return c
94- }
113+ member this.Result_Normal_Bind_CE () =
114+ let action () =
115+ asyncResult {
116+ let! a = Ok 10
117+ let! b = Ok 5
118+ let! c = afib ( a, b)
119+ return c
120+ }
121+
95122 action ()
96123 |> Async.StartImmediateAsTask
97124
98125
99126 [<Benchmark>]
100- member this.Result_Alt_Inlined_Bind_CE () =
101- let action () = asyncResultInlinedIfLambda {
102- let! a = Ok 10
103- let! b = Ok 5
104- let! c = afib( a, b)
105- return c
106- }
127+ member this.Result_Alt_Inlined_Bind_CE () =
128+ let action () =
129+ asyncResultInlinedIfLambda {
130+ let! a = Ok 10
131+ let! b = Ok 5
132+ let! c = afib ( a, b)
133+ return c
134+ }
135+
107136 action ()
108137 |> Async.StartImmediateAsTask
0 commit comments