Skip to content

Commit af4b826

Browse files
Add support voption to require function (#243)
* added voption to result * added voption to async result * fixed formatting * added voption to job result * added voption to task result * added bind task/job/async result and require voption * added voption to docs --------- Co-authored-by: Jimmy Byrd <[email protected]>
1 parent a7edd80 commit af4b826

File tree

12 files changed

+393
-0
lines changed

12 files changed

+393
-0
lines changed

gitbook/asyncResult/others.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@ Converts an async-wrapped Option to a Result, using the given error if Some.
2828
'a -> Async<'b option> -> Async<Result<unit, 'a>>`
2929
```
3030

31+
### requireValueSome
32+
33+
Converts an async-wrapped ValueOption to a Result, using the given error if ValueNone.
34+
```fsharp
35+
'a -> Async<'b voption> -> Async<Result<'b, 'a>>
36+
```
37+
38+
### requireValueNone
39+
40+
Converts an async-wrapped ValueOption to a Result, using the given error if ValueSome.
41+
42+
```fsharp
43+
'a -> Async<'b voption> -> Async<Result<unit, 'a>>
44+
```
3145

3246
### requireEqual
3347

gitbook/jobResult/others.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,19 @@ Converts an job-wrapped Option to a Result, using the given error if Some.
2828
'a -> job<'b option> -> job<Result<unit, 'a>>`
2929
```
3030

31+
### requireValueSome
32+
33+
Converts an job-wrapped ValueOption to a Result, using the given error if ValueNone.
34+
```fsharp
35+
'a -> job<'b voption> -> job<Result<'b, 'a>>
36+
```
37+
### requireValueNone
38+
39+
Converts an job-wrapped ValueOption to a Result, using the given error if ValueSome.
40+
41+
```fsharp
42+
'a -> job<'b voption> -> job<Result<unit, 'a>>
43+
```
3144

3245
### requireEqual
3346

gitbook/result/requireFunctions.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,70 @@ let result : Result<unit, string> =
128128
// Error "Value must be None"
129129
```
130130

131+
## requireValueSome
132+
133+
Converts an ValueOption to a Result, using the given error if ValueNone.
134+
135+
### Function Signature
136+
137+
```fsharp
138+
'a -> 'b voption -> Result<'b, 'a>
139+
```
140+
141+
### Examples
142+
143+
#### Example 1
144+
145+
```fsharp
146+
let result : Result<unit, string> =
147+
ValueSome 1
148+
|> Result.requireValueSome "Value must be ValueSome"
149+
150+
// Ok ()
151+
```
152+
153+
#### Example 2
154+
155+
```fsharp
156+
let result : Result<unit, string> =
157+
None
158+
|> Result.requireValueSome "Value must be ValueSome"
159+
160+
// Error "Value must be ValueSome"
161+
```
162+
163+
## requireValueNone
164+
165+
Converts an ValueOption to a Result, using the given error if ValueSome.
166+
167+
### Function Signature
168+
169+
```fsharp
170+
'a -> 'b voption -> Result<unit, 'a>
171+
```
172+
173+
### Examples
174+
175+
#### Example 1
176+
177+
```fsharp
178+
let result : Result<unit, string> =
179+
ValueNone
180+
|> Result.requireValueNone "Value must be ValueNone"
181+
182+
// Ok ()
183+
```
184+
185+
#### Example 2
186+
187+
```fsharp
188+
let result : Result<unit, string> =
189+
ValueSome 1
190+
|> Result.requireValueNone "Value must be ValueNone"
191+
192+
// Error "Value must be ValueNone"
193+
```
194+
131195
## requireNotNull
132196

133197
Converts a nullable value to a Result, using the given error if null.

gitbook/taskResult/others.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,19 @@ Converts an task-wrapped Option to a Result, using the given error if Some.
2828
'a -> Task<'b option> -> Task<Result<unit, 'a>>`
2929
```
3030

31+
### requireValueSome
32+
33+
Converts an task-wrapped ValueOption to a Result, using the given error if ValueNone.
34+
```fsharp
35+
'a -> Task<'b voption> -> Task<Result<'b, 'a>>
36+
```
37+
### requireValueNone
38+
39+
Converts an task-wrapped ValueOption to a Result, using the given error if ValueSome.
40+
41+
```fsharp
42+
'a -> Task<'b voption> -> Task<Result<unit, 'a>>
43+
```
3144

3245
### requireEqual
3346

src/FsToolkit.ErrorHandling.JobResult/JobResult.fs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,16 @@ module JobResult =
131131
option
132132
|> Job.map (Result.requireNone error)
133133

134+
// Converts an job-wrapped ValueOption to a Result, using the given error if ValueNone.
135+
let inline requireValueSome error voption =
136+
voption
137+
|> Job.map (Result.requireValueSome error)
138+
139+
// Converts an job-wrapped ValueOption to a Result, using the given error if ValueSome.
140+
let inline requireValueNone error voption =
141+
voption
142+
|> Job.map (Result.requireValueNone error)
143+
134144
/// Returns Ok if the job-wrapped value and the provided value are equal, or the specified error if not.
135145
let inline requireEqual x1 x2 error =
136146
x2
@@ -262,3 +272,19 @@ module JobResult =
262272
Result.requireNone error
263273
>> Job.singleton
264274
)
275+
276+
/// Bind the JobResult and requireValueSome on the inner voption value.
277+
let inline bindRequireValueSome error x =
278+
x
279+
|> bind (
280+
Result.requireValueSome error
281+
>> Job.singleton
282+
)
283+
284+
/// Bind the JobResult and requireValueNone on the inner voption value.
285+
let inline bindRequireValueNone error x =
286+
x
287+
|> bind (
288+
Result.requireValueNone error
289+
>> Job.singleton
290+
)

src/FsToolkit.ErrorHandling.TaskResult/TaskResult.fs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ module TaskResult =
119119
option
120120
|> Task.map (Result.requireNone error)
121121

122+
// Converts an task-wrapped ValueOption to a Result, using the given error if ValueNone.
123+
let inline requireValueSome error voption =
124+
voption
125+
|> Task.map (Result.requireValueSome error)
126+
127+
// Converts an task-wrapped ValueOption to a Result, using the given error if ValueSome.
128+
let inline requireValueNone error voption =
129+
voption
130+
|> Task.map (Result.requireValueNone error)
131+
122132
/// Returns Ok if the task-wrapped value and the provided value are equal, or the specified error if not.
123133
let inline requireEqual x1 x2 error =
124134
x2
@@ -250,10 +260,27 @@ module TaskResult =
250260
Result.requireNone error
251261
>> Task.singleton
252262
)
263+
264+
/// Bind the TaskResult and requireValueSome on the inner voption value.
265+
let inline bindRequireValueSome error x =
266+
x
267+
|> bind (
268+
Result.requireValueSome error
269+
>> Task.singleton
270+
)
253271

272+
/// Bind the TaskResult and requireValueNone on the inner voption value.
273+
let inline bindRequireValueNone error x =
274+
x
275+
|> bind (
276+
Result.requireValueNone error
277+
>> Task.singleton
278+
)
279+
254280
let inline foldResult
255281
([<InlineIfLambda>] onSuccess: 'input -> 'output)
256282
([<InlineIfLambda>] onError: 'inputError -> 'output)
257283
(input: Task<Result<'input, 'inputError>>)
258284
: Task<'output> =
259285
Task.map (Result.either onSuccess onError) input
286+

src/FsToolkit.ErrorHandling/AsyncResult.fs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,22 @@ module AsyncResult =
168168
value
169169
|> Async.map (Result.requireNone error)
170170

171+
// Converts an async-wrapped ValueOption to a Result, using the given error if ValueNone.
172+
let inline requireValueSome
173+
(error: 'error)
174+
(value: Async<'ok voption>)
175+
: Async<Result<'ok, 'error>> =
176+
value
177+
|> Async.map (Result.requireValueSome error)
178+
179+
// Converts an async-wrapped ValueOption to a Result, using the given error if ValueSome.
180+
let inline requireValueNone
181+
(error: 'error)
182+
(value: Async<'ok voption>)
183+
: Async<Result<unit, 'error>> =
184+
value
185+
|> Async.map (Result.requireValueNone error)
186+
171187
/// Returns Ok if the async-wrapped value and the provided value are equal, or the specified error if not.
172188
let inline requireEqual
173189
(value1: 'value)
@@ -349,3 +365,19 @@ module AsyncResult =
349365
Result.requireNone error
350366
>> Async.singleton
351367
)
368+
369+
/// Bind the AsyncResult and requireValueSome on the inner voption value.
370+
let inline bindRequireValueSome error x =
371+
x
372+
|> bind (
373+
Result.requireValueSome error
374+
>> Async.singleton
375+
)
376+
377+
/// Bind the AsyncResult and requireValueNone on the inner voption value.
378+
let inline bindRequireValueNone error x =
379+
x
380+
|> bind (
381+
Result.requireValueNone error
382+
>> Async.singleton
383+
)

src/FsToolkit.ErrorHandling/Result.fs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,18 @@ module Result =
180180
| Some _ -> Error error
181181
| None -> Ok()
182182

183+
/// Converts an ValueOption to a Result, using the given error if ValueNone.
184+
let inline requireValueSome (error: 'error) (voption: 'ok voption) : Result<'ok, 'error> =
185+
match voption with
186+
| ValueSome x -> Ok x
187+
| ValueNone -> Error error
188+
189+
/// Converts an ValueOption to a Result, using the given error if ValueSome.
190+
let inline requireValueNone (error: 'error) (voption: 'value voption) : Result<unit, 'error> =
191+
match voption with
192+
| ValueSome _ -> Error error
193+
| ValueNone -> Ok()
194+
183195
/// Converts a nullable value into a Result, using the given error if null
184196
let inline requireNotNull (error: 'error) (value: 'ok) : Result<'ok, 'error> =
185197
match value with

tests/FsToolkit.ErrorHandling.JobResult.Tests/JobResult.fs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,38 @@ let requireNoneTests =
300300
|> Expect.hasJobErrorValueSync err
301301
]
302302

303+
[<Tests>]
304+
let requireValueSomeTests =
305+
testList "JobResult.requireValueSome Tests" [
306+
testCase "requireValueSome happy path"
307+
<| fun _ ->
308+
toJob (ValueSome 42)
309+
|> JobResult.requireValueSome err
310+
|> Expect.hasJobOkValueSync 42
311+
312+
testCase "requireValueSome error path"
313+
<| fun _ ->
314+
toJob ValueNone
315+
|> JobResult.requireValueSome err
316+
|> Expect.hasJobErrorValueSync err
317+
]
318+
319+
[<Tests>]
320+
let requireValueNoneTests =
321+
testList "JobResult.requireValueNone Tests" [
322+
testCase "requireValueNone happy path"
323+
<| fun _ ->
324+
toJob ValueNone
325+
|> JobResult.requireValueNone err
326+
|> Expect.hasJobOkValueSync ()
327+
328+
testCase "requireValueNone error path"
329+
<| fun _ ->
330+
toJob (ValueSome 42)
331+
|> JobResult.requireValueNone err
332+
|> Expect.hasJobErrorValueSync err
333+
]
334+
303335
[<Tests>]
304336
let requireEqualToTests =
305337
testList "JobResult.requireEqualTo Tests" [
@@ -738,6 +770,28 @@ let bindRequireTests =
738770
}
739771
]
740772

773+
[<Tests>]
774+
let bindRequireValueOptionTests =
775+
testList "JobResult Bind + RequireValueOption tests" [
776+
testCaseJob "bindRequireValueNone"
777+
<| job {
778+
return!
779+
ValueSome "john_doe"
780+
|> JobResult.ok
781+
|> JobResult.bindRequireValueNone "user exists"
782+
|> Expect.hasJobErrorValue "user exists"
783+
}
784+
785+
testCaseJob "bindRequireValueSome"
786+
<| job {
787+
return!
788+
ValueSome "john_doe"
789+
|> JobResult.ok
790+
|> JobResult.bindRequireValueSome "user doesn't exists"
791+
|> Expect.hasJobOkValue "john_doe"
792+
}
793+
]
794+
741795
type CreatePostResult =
742796
| PostSuccess of NotifyNewPostRequest
743797
| NotAllowedToPost

0 commit comments

Comments
 (0)