Skip to content

Commit 1f276ac

Browse files
committed
Update ValueOption/Option CE for F# 9 nullness
1 parent a899a02 commit 1f276ac

File tree

12 files changed

+136
-239
lines changed

12 files changed

+136
-239
lines changed

.paket/Paket.Restore.targets

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,14 +235,15 @@
235235
<Splits>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length)</Splits>
236236
<PackageName>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0])</PackageName>
237237
<PackageVersion>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1])</PackageVersion>
238+
<Reference>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[2])</Reference>
238239
<AllPrivateAssets>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4])</AllPrivateAssets>
239240
<CopyLocal Condition="%(PaketReferencesFileLinesInfo.Splits) &gt;= 6">$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5])</CopyLocal>
240241
<OmitContent Condition="%(PaketReferencesFileLinesInfo.Splits) &gt;= 7">$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[6])</OmitContent>
241242
<ImportTargets Condition="%(PaketReferencesFileLinesInfo.Splits) &gt;= 8">$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[7])</ImportTargets>
242243
<Aliases Condition="%(PaketReferencesFileLinesInfo.Splits) &gt;= 9">$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[8])</Aliases>
243244
</PaketReferencesFileLinesInfo>
244-
<PackageReference Include="%(PaketReferencesFileLinesInfo.PackageName)">
245-
<Version>%(PaketReferencesFileLinesInfo.PackageVersion)</Version>
245+
<PackageReference Condition=" '$(ManagePackageVersionsCentrally)' != 'true' Or '%(PaketReferencesFileLinesInfo.Reference)' == 'Direct' " Include="%(PaketReferencesFileLinesInfo.PackageName)">
246+
<Version Condition=" '$(ManagePackageVersionsCentrally)' != 'true' ">%(PaketReferencesFileLinesInfo.PackageVersion)</Version>
246247
<PrivateAssets Condition=" ('%(PaketReferencesFileLinesInfo.AllPrivateAssets)' == 'true') Or ('$(PackAsTool)' == 'true') ">All</PrivateAssets>
247248
<ExcludeAssets Condition=" %(PaketReferencesFileLinesInfo.CopyLocal) == 'false' or %(PaketReferencesFileLinesInfo.AllPrivateAssets) == 'exclude'">runtime</ExcludeAssets>
248249
<ExcludeAssets Condition=" %(PaketReferencesFileLinesInfo.OmitContent) == 'true'">$(ExcludeAssets);contentFiles</ExcludeAssets>
@@ -252,6 +253,10 @@
252253
<AllowExplicitVersion>true</AllowExplicitVersion>
253254

254255
</PackageReference>
256+
257+
<PackageVersion Include="%(PaketReferencesFileLinesInfo.PackageName)">
258+
<Version>%(PaketReferencesFileLinesInfo.PackageVersion)</Version>
259+
</PackageVersion>
255260
</ItemGroup>
256261

257262
<PropertyGroup>

src/FsToolkit.ErrorHandling.JobResult/JobOptionCE.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ module JobOptionCE =
1010
type JobOptionBuilder() =
1111

1212
member inline _.Return(value: 'T) : Job<_ option> =
13-
option.Return value
13+
Some value
1414
|> job.Return
1515

1616
member inline _.ReturnFrom(jobResult: Job<_ option>) : Job<_ option> = jobResult
1717

1818
member inline _.Zero() : Job<_ option> =
19-
option.Zero()
19+
Some()
2020
|> job.Return
2121

2222
member inline _.Bind

src/FsToolkit.ErrorHandling/AsyncOptionCE.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module AsyncOptionCE =
1212
member inline _.ReturnFrom(value: Async<'value option>) : Async<'value option> = value
1313

1414
member inline _.Zero() : Async<unit option> =
15-
option.Zero()
15+
Some()
1616
|> async.Return
1717

1818
member inline _.Bind

src/FsToolkit.ErrorHandling/AsyncResultOptionCE.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ module AsyncResultOptionCE =
2828

2929
member inline _.Delay([<InlineIfLambda>] f: unit -> Async<'a>) : Async<'a> = async.Delay f
3030

31-
member inline _.Zero() = Async.singleton (Ok(option.Zero()))
31+
member inline _.Zero() = Async.singleton (Ok(Some()))
3232

3333
member inline _.TryWith
3434
(

src/FsToolkit.ErrorHandling/FsToolkit.ErrorHandling.fsproj

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<OutputType>Library</OutputType>
4-
<TargetFrameworks>net9.0;netstandard2.1;netstandard2.0</TargetFrameworks>
4+
<TargetFrameworks>netstandard2.1;netstandard2.0;net9.0</TargetFrameworks>
55
<DebugType>portable</DebugType>
66
<NoWarn>$(NoWarn);FS1204;FS3511;FS3513;FS0057</NoWarn>
77
<PackageTags>$(PackageTags), fable-library, fable-dotnet, fable-javascript, fable-python</PackageTags>
@@ -12,6 +12,7 @@
1212
<Compile Include="ResultCE.fs" />
1313
<Compile Include="ResultOp.fs" />
1414
<Compile Include="Option.fs" />
15+
<Compile Include="ValueOption.fs" />
1516
<Compile Include="OptionCE.fs" />
1617
<Compile Include="OptionOp.fs" />
1718
<Compile Include="ResultOption.fs" />
@@ -32,8 +33,6 @@
3233
<Compile Include="AsyncValidation.fs" />
3334
<Compile Include="AsyncValidationOp.fs" />
3435
<Compile Include="AsyncValidationCE.fs" />
35-
<Compile Include="ValueOption.fs" />
36-
<Compile Include="ValueOptionCE.fs" />
3736
<Compile Include="AsyncOption.fs" />
3837
<Compile Include="AsyncOptionCE.fs" />
3938
<Compile Include="AsyncOptionOp.fs" />

src/FsToolkit.ErrorHandling/Nullness.fs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@ namespace FsToolkit.ErrorHandling
22
open System
33

44
type ExceptionNull =
5-
#if NET9_0 && !FABLE_COMPILER
5+
#if NET9_0_OR_GREATER && !FABLE_COMPILER
66
Exception | null
77
#else
88
Exception
99
#endif
1010

1111
type IDisposableNull =
12-
#if NET9_0 && !FABLE_COMPILER
12+
#if NET9_0_OR_GREATER && !FABLE_COMPILER
1313
IDisposable | null
1414
#else
1515
IDisposable
1616
#endif
1717

1818
type IAsyncDisposableNull =
19-
#if NET9_0 && !FABLE_COMPILER
19+
#if NET9_0_OR_GREATER && !FABLE_COMPILER
2020
IAsyncDisposable | null
2121
#else
2222
IAsyncDisposable

src/FsToolkit.ErrorHandling/OptionCE.fs

Lines changed: 72 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,50 @@ namespace FsToolkit.ErrorHandling
44
module 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

src/FsToolkit.ErrorHandling/ResultOptionCE.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module ResultOptionCE =
1111
member inline _.ReturnFrom value : Result<'ok option, 'error> = value
1212

1313
member inline _.Zero() =
14-
option.Zero()
14+
Some()
1515
|> Ok
1616

1717
member inline _.Bind

0 commit comments

Comments
 (0)