@@ -4,51 +4,50 @@ namespace FsToolkit.ErrorHandling
44module OptionCE =
55 open System
66
7- type OptionBuilder () =
8- member inline _.Return ( x : 'value ) : 'value option = Some x
97
10- member inline _.ReturnFrom ( m : 'value option ) : 'value option = m
8+ type OptionBuilderBase () =
9+
10+ member inline _.Bind ( x : 'b voption , [<InlineIfLambda>] f : 'b -> voption < 'c >) : voption < 'c > =
11+ ValueOption.bind f x
12+
13+ member inline _.BindReturn ( x : 'b voption , [<InlineIfLambda>] f : 'b -> 'c ) : voption < 'c > =
14+ ValueOption.map f x
1115
12- member inline _.Bind
13- ( input : 'input option , [<InlineIfLambda>] binder : 'input -> 'output option )
14- : 'output option =
15- Option.bind binder input
16+ member inline _.Return ( x : 'a ) = ValueSome x
1617
18+ member inline _.ReturnFrom ( x : 'a voption ) = x
1719
18- member inline this.Zero () : unit option = this.Return()
20+ member inline _.Zero () = ValueSome()
21+
22+ member inline _.Delay ( [<InlineIfLambda>] f : unit -> voption < _ >) = f
1923
2024 member inline _.Combine
21- ( m : 'input option , [<InlineIfLambda>] binder : 'input -> 'output option )
22- : 'output option =
23- Option .bind binder m
25+ ( m : 'input voption , [<InlineIfLambda>] binder : 'input -> 'output voption )
26+ : 'output voption =
27+ ValueOption .bind binder m
2428
25- member inline this.Combine ( m1 : unit option , m2 : 'output option ) : 'output option =
29+ member inline this.Combine ( m1 : unit voption , m2 : 'output voption ) : 'output voption =
2630 this.Bind( m1, ( fun () -> m2))
2731
28- member inline _.Delay
29- ( [<InlineIfLambda>] delayer : unit -> 'value option )
30- : ( unit -> 'value option ) =
31- delayer
32-
33- member inline _.Run ( [<InlineIfLambda>] delayed ) = delayed ()
3432
3533 member inline this.TryWith ( [<InlineIfLambda>] computation , handler ) : 'value =
3634 try
37- this.Run computation
35+ computation ()
3836 with e ->
3937 handler e
4038
4139 member inline this.TryFinally ( [<InlineIfLambda>] computation , compensation ) =
4240 try
43- this.Run computation
41+ computation ()
4442 finally
4543 compensation ()
4644
45+
4746 member inline this.Using
4847 (
4948 resource : 'disposable :> IDisposableNull ,
50- [<InlineIfLambda>] binder : 'disposable -> 'value option
51- ) : 'value option =
49+ [<InlineIfLambda>] binder : 'disposable -> 'value voption
50+ ) : 'value voption =
5251 this.TryFinally(
5352 ( fun () -> binder resource),
5453 ( fun () ->
@@ -60,88 +59,82 @@ module OptionCE =
6059 member inline this.While
6160 (
6261 [<InlineIfLambda>] guard : unit -> bool ,
63- [<InlineIfLambda>] generator : unit -> unit option
64- ) : unit option =
62+ [<InlineIfLambda>] generator : unit -> unit voption
63+ ) : unit voption =
6564
6665 let mutable doContinue = true
67- let mutable result = Some ()
66+ let mutable result = ValueSome ()
6867
6968 while doContinue
7069 && guard () do
7170 match generator () with
72- | Some () -> ()
73- | None ->
71+ | ValueSome () -> ()
72+ | ValueNone ->
7473 doContinue <- false
75- result <- None
74+ result <- ValueNone
7675
7776 result
7877
7978 member inline this.For
80- ( sequence : #seq<'value> , [<InlineIfLambda>] binder : 'value -> unit option )
81- : unit option =
82- this.Using(
83- sequence.GetEnumerator(),
84- fun enum -> this.While( enum .MoveNext, this.Delay( fun () -> binder enum .Current))
79+ ( sequence : #seq<'value> voption , [<InlineIfLambda>] binder : 'value -> unit voption )
80+ : unit voption =
81+ sequence
82+ |> ValueOption.bind ( fun sequence ->
83+ this.Using(
84+ sequence.GetEnumerator(),
85+ fun enum ->
86+ this.While( enum .MoveNext, this.Delay( fun () -> binder enum .Current))
87+ )
8588 )
8689
87- member inline _.BindReturn
88- ( input : 'input option , [<InlineIfLambda>] mapper : 'input -> 'output )
89- : 'output option =
90- Option.map mapper input
9190
91+ [<AutoOpen>]
92+ module BuilderExtensions =
93+ type OptionBuilderBase with
94+ member inline _.Source ( o ) = ValueOption.ofObj o
95+ member inline _.Source ( o : Nullable < 'a >) = ValueOption.ofNullable o
9296
93- /// <summary>
94- /// Method lets us transform data types into our internal representation. This is the identity method to recognize the self type.
95- ///
96- /// See https://stackoverflow.com/questions/35286541/why-would-you-use-builder-source-in-a-custom-computation-expression-builder
97- /// </summary>
98- member inline _.Source ( result : 'value option ) : 'value option = result
97+ [<AutoOpen>]
98+ module BuilderExtensions3 =
99+ type OptionBuilderBase with
100+ /// <summary>
101+ /// Needed to allow `for..in` and `for..do` functionality
102+ /// </summary>
103+ // member inline _.Source(s: string) = ValueOption.ofObj s
104+ #if NET9_ 0_ OR_ GREATER
99105
100- /// <summary>
101- /// The default instance of the `OptionBuilder` type.
102- /// </summary>
103- let option = OptionBuilder ()
106+ member inline _.Source ( s : # seq<'value> ) = ValueOption.ofObj s
107+ #else
108+ member inline _.Source ( s : # seq<'value> ) = ValueOption.ofNull s
109+ #endif
104110
105- [<AutoOpen>]
106- module OptionExtensionsLower =
107- type OptionBuilder with
111+ type OptionBuilder () =
108112
113+ inherit OptionBuilderBase()
109114
110- member inline _.BindReturn
111- ( x : 'input , [<InlineIfLambda>] f : 'input -> 'output )
112- : 'output option =
113- Option.map f ( Option.ofObj x)
115+ member inline _.Source ( o : 'a option ) = Option.toValueOption o
114116
115- // Could not get it to work solely with Source. In loop cases it would potentially match the #seq overload and ask for type annotation
116- member inline this.Bind
117- ( m : 'input when 'input : null , [<InlineIfLambda>] binder : 'input -> 'output option )
118- : 'output option =
119- this.Bind( Option.ofObj m, binder)
117+ member inline _.Run ( f ) =
118+ match f () with
119+ | ValueSome x -> Some x
120+ | ValueNone -> None
120121
121122
122- member inline _.Source ( nullableObj : 'value when 'value : null ) : 'value option =
123- Option.ofObj nullableObj
123+ type ValueOptionBuilder () =
124124
125- member inline _.Source ( m : string ) : string option = Option.ofObj m
125+ inherit OptionBuilderBase ()
126126
127- [<AutoOpen>]
128- module OptionExtensions =
129- open System
127+ member inline _.Source ( o : 'a voption ) = o
130128
131- type OptionBuilder with
129+ member inline _.Run ( f ) = f ()
132130
133- /// <summary>
134- /// Needed to allow `for..in` and `for..do` functionality
135- /// </summary>
136- member inline _.Source ( s : # seq<'value> ) : # seq<'value> = s
131+ [<AutoOpen>]
132+ module OptionCEExtensions =
133+ let option = OptionBuilder ()
134+ let voption = ValueOptionBuilder ()
137135
138- /// <summary>
139- /// Method lets us transform data types into our internal representation.
140- /// </summary>
141- member inline _.Source ( nullable : Nullable < 'value >) : 'value option =
142- Option.ofNullable nullable
136+ type ValueOptionBuilder with
137+ member inline _.Source ( o : 'a option ) = Option.toValueOption o
143138
144- /// <summary>
145- /// Method lets us transform data types into our internal representation.
146- /// </summary>
147- member inline _.Source ( vopt : 'value voption ) : 'value option = Option.ofValueOption vopt
139+ type OptionBuilder with
140+ member inline _.Source ( o : 'a voption ) = o
0 commit comments