Skip to content

Commit 993f738

Browse files
JmaharmanTheAngryByrd
authored andcommitted
Converted TaskOptionCE to use Source overload and added Task/Async
1 parent b2f6b41 commit 993f738

File tree

2 files changed

+67
-28
lines changed

2 files changed

+67
-28
lines changed

src/FsToolkit.ErrorHandling.TaskResult/TaskOptionCE.fs

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,6 @@ module TaskOptionCE =
1818
: Ply<Option<_>> =
1919
uply.ReturnFrom taskResult
2020

21-
member inline this.ReturnFrom
22-
(asyncResult: Async<Option<_>>)
23-
: Ply<Option<_>> =
24-
this.ReturnFrom (Async.StartAsTask asyncResult)
25-
26-
member inline _.ReturnFrom
27-
(result: Option<_>)
28-
: Ply<Option<_>> =
29-
uply.Return result
30-
3121
member inline _.Zero () : Ply<Option<_>> =
3222
uply.Return <| option.Zero()
3323

@@ -40,20 +30,6 @@ module TaskOptionCE =
4030
| Some x -> binder x
4131
| None -> uply.Return None
4232
uply.Bind(taskResult, binder')
43-
44-
member inline this.Bind
45-
(asyncResult: Async<Option<_>>,
46-
binder: 'T -> Ply<Option<_>>)
47-
: Ply<Option<_>> =
48-
this.Bind(Async.StartAsTask asyncResult, binder)
49-
50-
member inline this.Bind
51-
(result: Option<_>, binder: 'T -> Ply<Option<_>>)
52-
: Ply<Option<_>> =
53-
let result =
54-
result
55-
|> Task.singleton
56-
this.Bind(result, binder)
5733

5834
member inline _.Delay
5935
(generator: unit -> Ply<Option<_>>) =
@@ -117,4 +93,40 @@ module TaskOptionCE =
11793

11894
member inline _.Run(f : unit -> Ply<'m>) = task.Run f
11995

96+
/// <summary>
97+
/// Method lets us transform data types into our internal representation. This is the identity method to recognize the self type.
98+
/// See https://stackoverflow.com/questions/35286541/why-would-you-use-builder-source-in-a-custom-computation-expression-builder
99+
/// </summary>
100+
member inline _.Source(task : Task<Option<_>>) : Task<Option<_>> = task
101+
102+
/// <summary>
103+
/// Method lets us transform data types into our internal representation.
104+
/// </summary>
105+
member inline _.Source(async : Async<Option<_>>) : Task<Option<_>> = async |> Async.StartAsTask
106+
120107
let taskOption = TaskOptionBuilder()
108+
109+
[<AutoOpen>]
110+
// Having members as extensions gives them lower priority in
111+
// overload resolution and allows skipping more type annotations.
112+
module TaskOptionCEExtensions =
113+
114+
type TaskOptionBuilder with
115+
/// <summary>
116+
/// Needed to allow `for..in` and `for..do` functionality
117+
/// </summary>
118+
member inline __.Source(s: #seq<_>) = s
119+
120+
/// <summary>
121+
/// Method lets us transform data types into our internal representation.
122+
/// </summary>
123+
member inline __.Source(r: Option<'t>) = Task.singleton r
124+
/// <summary>
125+
/// Method lets us transform data types into our internal representation.
126+
/// </summary>
127+
member inline __.Source(a: Task<'t>) = a |> Task.map Some
128+
129+
/// <summary>
130+
/// Method lets us transform data types into our internal representation.
131+
/// </summary>
132+
member inline __.Source(a: Async<'t>) = a |> Async.StartAsTask |> Task.map Some

tests/FsToolkit.ErrorHandling.TaskResult.Tests/TaskOptionCE.fs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,35 @@ let ceTests =
3333
}
3434
Expect.equal actual expected "Should return value wrapped in option"
3535
}
36-
36+
3737
testCaseTask "ReturnFrom Async None" <| task {
3838
let expected = None
3939
let! actual = taskOption {
4040
return! (async.Return None)
4141
}
4242
Expect.equal actual expected "Should return value wrapped in option"
4343
}
44-
45-
#if !FABLE_COMPILER
44+
testCaseTask "ReturnFrom Async" <| task {
45+
let expected = Some 42
46+
let! actual = taskOption {
47+
return! (async.Return 42)
48+
}
49+
Expect.equal actual expected "Should return value wrapped in option"
50+
}
4651
testCaseTask "ReturnFrom Task None" <| task {
4752
let expected = None
4853
let! actual = taskOption {
4954
return! (Task.FromResult None)
5055
}
5156
Expect.equal actual expected "Should return value wrapped in option"
5257
}
53-
#endif
58+
testCaseTask "ReturnFrom Task" <| task {
59+
let expected = Some 42
60+
let! actual = taskOption {
61+
return! (Task.FromResult 42)
62+
}
63+
Expect.equal actual expected "Should return value wrapped in option"
64+
}
5465
testCaseTask "Bind Some" <| task {
5566
let expected = Some 42
5667
let! actual = taskOption {
@@ -75,6 +86,14 @@ let ceTests =
7586
}
7687
Expect.equal actual expected "Should bind value wrapped in option"
7788
}
89+
testCaseTask "Bind Async" <| task {
90+
let expected = Some 42
91+
let! actual = taskOption {
92+
let! value = async.Return 42
93+
return value
94+
}
95+
Expect.equal actual expected "Should bind value wrapped in option"
96+
}
7897
testCaseTask "Bind Task None" <| task {
7998
let expected = None
8099
let! actual = taskOption {
@@ -83,6 +102,14 @@ let ceTests =
83102
}
84103
Expect.equal actual expected "Should bind value wrapped in option"
85104
}
105+
testCaseTask "Bind Task" <| task {
106+
let expected = Some 42
107+
let! actual = taskOption {
108+
let! value = Task.FromResult 42
109+
return value
110+
}
111+
Expect.equal actual expected "Should bind value wrapped in option"
112+
}
86113
testCaseTask "Zero/Combine/Delay/Run" <| task {
87114
let data = 42
88115
let! actual = taskOption {

0 commit comments

Comments
 (0)