-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ae08b58
commit 474897e
Showing
8 changed files
with
189 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
## AsyncValidation.apply | ||
|
||
Namespace: `FsToolkit.ErrorHandling` | ||
|
||
Function Signature: | ||
|
||
```fsharp | ||
Async<Result<('a -> 'b), 'c list>> | ||
-> Async<Result<'a, 'c list>> | ||
-> Async<Result<'b, 'c list>> | ||
``` | ||
|
||
## Examples |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
## AsyncValidation Computation Expression | ||
|
||
Namespace: `FsToolkit.ErrorHandling` | ||
|
||
The `AsyncValidation` type is defined as: | ||
|
||
```fsharp | ||
type AsyncValidation<'a,'err> = Async<Result<'a, 'err list>> | ||
``` | ||
|
||
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. | ||
|
||
## Examples | ||
|
||
The example from [AsyncValidation.map3](../asyncValidation/map3.md#example-1) can be solved using the `asyncValidation` computation expression as below: | ||
|
||
```fsharp | ||
// Result<string, string> -> Async<Result<string, string>> | ||
let downloadAsync stuff = async { | ||
return stuff | ||
} | ||
// AsyncValidation<string, string> | ||
let addResult = asyncValidation { | ||
let! x = downloadAsync (Ok "I") | ||
and! y = downloadAsync (Ok "am") | ||
and! z = downloadAsync (Ok "async!") | ||
return sprintf "%s %s %s" x y z | ||
} | ||
// result = async { return Ok "I am async!" } | ||
// AsyncValidation<string, string> | ||
let addResult = asyncValidation { | ||
let! x = downloadAsync (Error "Am") | ||
and! y = downloadAsync (Error "I") | ||
and! z = downloadAsync (Error "async?") | ||
return sprintf "%s %s %s" x y z | ||
} | ||
// result = async { return Error [ "Am"; "I"; "async?" ] } | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## AsyncValidation | ||
|
||
Namespace: `FsToolkit.ErrorHandling` | ||
|
||
This module provides utility functions and infix operators to work with `Async<Result<'a, 'b list>>`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
## AsyncValidation.map2 | ||
|
||
Namespace: `FsToolkit.ErrorHandling` | ||
|
||
Function Signature: | ||
|
||
```fsharp | ||
('a -> 'b -> 'c) | ||
-> Async<Result<'a, 'd list>> | ||
-> Async<Result<'b, 'd list>> | ||
-> Async<Result<'c, 'd list>> | ||
``` | ||
|
||
Like [Result.map2](../result/map2.md), but collects the errors from both arguments. | ||
|
||
## Examples |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
## AsyncAsyncValidation.map3 | ||
|
||
Namespace: `FsToolkit.ErrorHandling` | ||
|
||
Function Signature: | ||
|
||
``` | ||
('a -> 'b -> 'c -> 'd) | ||
-> Async<Result<'a, 'e list>> | ||
-> Async<Result<'b, 'e list>> | ||
-> Async<Result<'c, 'e list>> | ||
-> Async<Result<'d, 'e list>> | ||
``` | ||
|
||
Like [Result.map3](../result/map3.md), but collects the errors from all arguments. | ||
|
||
## Examples |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
## AsyncValidation.ofResult | ||
|
||
Namespace: `FsToolkit.ErrorHandling` | ||
|
||
Function Signature: | ||
|
||
```fsharp | ||
Result<'a, 'b> -> Async<Result<'a, 'b list>> | ||
``` | ||
|
||
Simply wraps the error in a list and makes the result async. | ||
|
||
## Examples |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
## AsyncValidation Infix Operators | ||
|
||
Namespace: `FsToolkit.ErrorHandling.Operator.AsyncValidation` | ||
|
||
FsToolkit.ErrorHandling provides the standard infix operators for `map` (`<!>`), `apply` (`<*>`), and `bind` (`>>=`) to work with `Result<'a, 'b list>`. | ||
|
||
There are also variants of the `map` and `apply` operators (`<!^>` and `<*^>`) that accept `Result<'a, 'b>` (non-list) as the right-hand argument. | ||
|
||
## Examples | ||
|
||
### Example 1 | ||
|
||
Assume that we have following types and functions: | ||
|
||
```fsharp | ||
type Latitude = private Latitude of float with | ||
// float -> Async<Result<Latitude, string list>> | ||
static member TryCreate (lat : float) = | ||
// ... | ||
type Longitude = private Longitude of float with | ||
// float -> Async<Result<Longitude, string list>> | ||
static member TryCreate (lng : float) = | ||
// ... | ||
type Tweet = private Tweet of string with | ||
// string -> Async<Result<Tweet, string list>> | ||
static member TryCreate (tweet : string) = | ||
// ... | ||
// Latitude -> Longitude -> Tweet -> CreatePostRequest | ||
let createPostRequest lat long tweet = | ||
// ... | ||
``` | ||
|
||
We can make use of the standard operators in the AsyncValidation Operators module to perform the asyncValidation of the incoming request and capture all the errors as shown below: | ||
|
||
```fsharp | ||
open FsToolkit.ErrorHandling.Operator.AsyncValidation | ||
// float -> float -> string -> Async<Result<CreatePostRequest, string list>> | ||
let validateCreatePostRequest lat lng tweet = | ||
createPostRequest | ||
<!> Latitude.TryCreate lat | ||
<*> Longitude.TryCreate lng | ||
<*> Tweet.TryCreate tweet | ||
``` | ||
|
||
By using the `AsyncValidation` operators instead of the `Result` operators, we collect all the errors: | ||
```fsharp | ||
validateCreatePostRequest 300. 400. "" | ||
// Error | ||
["300.0 is a invalid latitude value" | ||
"400.0 is a invalid longitude value" | ||
"Tweet shouldn't be empty"] | ||
``` | ||
|
||
### Example 2 | ||
|
||
In the above example, all the `TryCreate` functions return a string list as the error type (`Async<Result<'a, string list>>`). If these functions instead returned `Async<Result<'a, string>>` (only a single error), we can use `<*^>` and `<!^>` to get the same result: | ||
|
||
|
||
```fsharp | ||
open FsToolkit.ErrorHandling.Operator.AsyncValidation | ||
// float -> float -> string -> Async<Result<CreatePostRequest, string list>> | ||
let validateCreatePostRequest lat lng tweet = | ||
createPostRequest | ||
<!^> Latitude.TryCreate lat | ||
<*^> Longitude.TryCreate lng | ||
<*^> Tweet.TryCreate tweet | ||
``` |