Skip to content

Commit 93804f4

Browse files
authored
Add TaskValidation module (#313)
* Implement TaskValidation module * Implement TaskValidationOp functions * Implement TaskValidation computation expression * Add TaskValidation tests * Finish TaskValidation tests; fix formatting * Move TaskValidation tests to FsToolkit.ErrorHandling.TaskResult.Tests project * Add gitbook documentation for TaskValidation * Add overload for plain Result case; add test handling multiple errors case
1 parent db649d1 commit 93804f4

21 files changed

+2515
-0
lines changed

gitbook/SUMMARY.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,21 @@
228228
* [ofChoice](asyncValidation/ofChoice.md)
229229
* [ofResult](asyncValidation/ofResult.md)
230230

231+
* [TaskValidation](taskValidation/index.md)
232+
* [apply](taskValidation/apply.md)
233+
* [Computation Expression](taskValidation/ce.md)
234+
* [error](taskValidation/error.md)
235+
* [map](taskValidation/map.md)
236+
* [map2](taskValidation/map2.md)
237+
* [map3](taskValidation/map3.md)
238+
* [mapError](taskValidation/mapError.md)
239+
* [mapErrors](taskValidation/mapErrors.md)
240+
* [Operators](taskValidation/operators.md)
241+
* [zip](taskValidation/zip.md)
242+
* Transforms
243+
* [ofChoice](taskValidation/ofChoice.md)
244+
* [ofResult](taskValidation/ofResult.md)
245+
231246
* FsToolkit.ErrorHandling.AsyncSeq
232247
* AsyncSeq
233248
* [Computation Expression](pr.md)

gitbook/taskValidation/apply.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## TaskValidation.apply
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
Function Signature:
6+
7+
```fsharp
8+
Task<Result<('a -> 'b), 'c list>>
9+
-> Task<Result<'a, 'c list>>
10+
-> Task<Result<'b, 'c list>>
11+
```
12+
13+
## Examples

gitbook/taskValidation/ce.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
## TaskValidation Computation Expression
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
The `TaskValidation` type is defined as:
6+
7+
```fsharp
8+
type TaskValidation<'a,'err> = Task<Result<'a, 'err list>>
9+
```
10+
11+
This CE can take advantage of the [and! operator](https://github.com/fsharp/fslang-suggestions/issues/579) to join multiple error results into a list.
12+
13+
## Examples
14+
15+
See [here](../validation/ce.md) for other validation-like examples
16+
17+
```fsharp
18+
// Result<string, string> -> Task<Result<string, string>>
19+
let downloadTask stuff = task {
20+
return stuff
21+
}
22+
23+
// TaskValidation<string, string>
24+
let addResult = taskValidation {
25+
let! x = downloadTask (Ok "I")
26+
and! y = downloadTask (Ok "am")
27+
and! z = downloadTask (Ok "async!")
28+
return sprintf "%s %s %s" x y z
29+
}
30+
// task { return Ok "I am async!" }
31+
32+
// TaskValidation<string, string>
33+
let addResult = taskValidation {
34+
let! x = downloadTask (Error "Am")
35+
and! y = downloadTask (Error "I")
36+
and! z = downloadTask (Error "async?")
37+
return sprintf "%s %s %s" x y z
38+
}
39+
40+
// task { return Error [ "Am"; "I"; "async?" ] }
41+
```

gitbook/taskValidation/error.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## TaskValidation.error
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
Lift an `'error` value into an `Task<Validation<'ok, 'error>>`
6+
7+
## Function Signature:
8+
9+
```fsharp
10+
'error -> Task<Validation<'ok, 'error>>
11+
```
12+
13+
## Examples
14+
15+
### Example 1
16+
17+
18+
```fsharp
19+
let result : Task<Validation<int, string>> =
20+
TaskValidation.error "Something bad happened"
21+
```
22+

gitbook/taskValidation/index.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# TaskValidation
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
This module provides utility functions and infix operators to work with `Task<Result<'a, 'b list>>`.

gitbook/taskValidation/map.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# TaskValidation.map
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
`map` applies a transformation to the value inside an `TaskValidation` if it represents a successful result (`Ok`). It allows you to perform a computation on the value while preserving the success/error status of the original `TaskValidation`. If the original `TaskValidation` is an `Error`, `map` does nothing and returns the same `Error` unchanged.
6+
7+
## Function Signature
8+
9+
```fsharp
10+
('okInput -> 'okOutput) -> TaskValidation<'okInput, 'error> -> TaskValidation<'okOutput, 'error>
11+
```
12+
13+
## Examples
14+
15+
Take the following functions for example
16+
17+
```fsharp
18+
// string -> int
19+
let remainingCharacters (prompt: string) =
20+
280 - prompt.Length
21+
```
22+
23+
### Example 1
24+
25+
```fsharp
26+
let validation =
27+
TaskValidation.ok "foo" // TaskValidation<string, string>
28+
|> TaskValidation.map remainingCharacters // TaskValidation<int, string>
29+
30+
// task { Ok 277 }
31+
```
32+
33+
### Example 2
34+
35+
```fsharp
36+
let result =
37+
TaskValidation.error "bad things happened" // TaskValidation<string, string>
38+
|> TaskValidation.map remainingCharacters // TaskValidation<int, string>
39+
40+
// task { Error ["bad things happened"] }
41+
```

gitbook/taskValidation/map2.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
## TaskValidation.map2
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
Function Signature:
6+
7+
```fsharp
8+
('a -> 'b -> 'c)
9+
-> Task<Result<'a, 'd list>>
10+
-> Task<Result<'b, 'd list>>
11+
-> Task<Result<'c, 'd list>>
12+
```
13+
14+
Like [Result.map2](../result/map2.md), but collects the errors from both arguments.
15+
16+
## Examples

gitbook/taskValidation/map3.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## TaskValidation.map3
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
Function Signature:
6+
7+
```
8+
('a -> 'b -> 'c -> 'd)
9+
-> Task<Result<'a, 'e list>>
10+
-> Task<Result<'b, 'e list>>
11+
-> Task<Result<'c, 'e list>>
12+
-> Task<Result<'d, 'e list>>
13+
```
14+
15+
Like [Result.map3](../result/map3.md), but collects the errors from all arguments.
16+
17+
## Examples

gitbook/taskValidation/mapError.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# TaskValidation.mapError
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
`mapError` takes an task validation and a normal function and returns a new task validation value based on the input error value and the function
6+
7+
## Function Signature
8+
9+
```fsharp
10+
('errorInput -> 'errorOutput) -> TaskValidation<'ok, 'errorInput>
11+
-> TaskValidation<'ok, 'errorOutput>
12+
```
13+
14+
## Examples
15+
16+
Take the following functions for example
17+
18+
```fsharp
19+
// string -> int
20+
let getErrorCode (message: string) =
21+
match message with
22+
| "bad things happened" -> 1
23+
| _ -> 0
24+
```
25+
26+
### Example 1
27+
28+
```fsharp
29+
let result =
30+
TaskValidation.ok "all good" // TaskValidation<string, string>
31+
|> TaskValidation.mapError getErrorCode // TaskValidation<string, int>
32+
33+
// task { Ok "all good" }
34+
```
35+
36+
### Example 2
37+
38+
```fsharp
39+
let result =
40+
TaskValidation.error "bad things happened" // TaskValidation<string, string>
41+
|> TaskValidation.mapError getErrorCode // TaskValidation<string, int>
42+
43+
// task { Error [1] }
44+
```

gitbook/taskValidation/mapErrors.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# TaskValidation.mapErrors
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
Similar to [TaskValidation.mapError](../taskValidation/mapError.md), except that the mapping function is passed the full list of errors, rather than each one individually.
6+
7+
## Function Signature
8+
9+
```fsharp
10+
('errorInput list -> 'errorOutput list) -> TaskValidation<'ok, 'errorInput>
11+
-> TaskValidation<'ok, 'errorOutput>
12+
```
13+
14+
## Examples
15+
16+
Take the following functions for example
17+
18+
```fsharp
19+
// string -> int
20+
let getErrorCode (messages: string list) =
21+
match messages |> List.tryFind ((=) "bad things happened") with
22+
| Some _ -> [1]
23+
| _ -> [0]
24+
```
25+
26+
### Example 1
27+
28+
```fsharp
29+
let result =
30+
TaskValidation.ok "all good" // TaskValidation<string, string>
31+
|> TaskValidation.mapErrors getErrorCode // TaskValidation<string, int>
32+
33+
// task { Ok "all good" }
34+
```
35+
36+
### Example 2
37+
38+
```fsharp
39+
let result : TaskValidation<string, int> =
40+
TaskValidation.error "bad things happened" // TaskValidation<string, string>
41+
|> TaskValidation.mapErrors getErrorCode // TaskValidation<string, int>
42+
43+
// task { Error [1] }
44+
```

gitbook/taskValidation/ofChoice.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# TaskValidation.ofChoice
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
Transforms a `Choice<'T, 'Error>` into a `Task<Result<'T, 'Error list>>`
6+
7+
## Function Signature
8+
9+
```fsharp
10+
Choice<'T, 'Error> -> Task<Result<'T, 'Error list>>
11+
```
12+
13+
## Examples
14+
15+
### Example 1
16+
17+
```fsharp
18+
let result = TaskValidation.ofChoice (Choice1Of2 42)
19+
// task { return Ok 42 }
20+
```
21+
22+
### Example 2
23+
24+
```fsharp
25+
let result = TaskValidation.ofChoice (Choice2Of2 "error")
26+
// task { return Error ["error"] }
27+
```

gitbook/taskValidation/ofResult.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# TaskValidation.ofResult
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
Transforms a `Result<'T, 'Error>` into a `Task<Result<'T, 'Error list>>`
6+
7+
## Function Signature
8+
9+
```fsharp
10+
Result<'T, 'Error> -> Task<Result<'T, 'Error list>>
11+
```
12+
13+
## Examples
14+
15+
### Example 1
16+
17+
```fsharp
18+
let result = TaskValidation.ofResult (Ok 42)
19+
// task { return Ok 42 }
20+
```
21+
22+
### Example 2
23+
24+
```fsharp
25+
let result = TaskValidation.ofResult (Error "error")
26+
// task { return Error ["error"] }
27+
```

0 commit comments

Comments
 (0)