Skip to content

Commit

Permalink
Added documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
1eyewonder authored and TheAngryByrd committed Jun 21, 2023
1 parent ae08b58 commit 474897e
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 1 deletion.
11 changes: 10 additions & 1 deletion gitbook/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,17 @@
* [ofResult](validation/ofResult.md)
* [Operators](validation/operators.md)
* [Result.tryCreate](validation/tryCreate.md)
* [Computation Expression](validation/ce.md)

* [AsyncValidation](asyncValidation/index.md)
* [map2](asyncValidation/map2.md)
* [map3](asyncValidation/map3.md)
* [apply](asyncValidation/apply.md)
* [ofResult](asyncValidation/ofResult.md)
* [Operators](asyncValidation/operators.md)
* [Computation Expression](asyncValidation/ce.md)

* [Test](test/index.md)
* [testing](test/testing.md)
* [testing-nested1](test/testing-nested1.md)
* [testing-nested2](test/testing-nested2.md)
* [testing-nested2](test/testing-nested2.md)
13 changes: 13 additions & 0 deletions gitbook/asyncValidation/apply.md
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
43 changes: 43 additions & 0 deletions gitbook/asyncValidation/ce.md
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?" ] }
```

5 changes: 5 additions & 0 deletions gitbook/asyncValidation/index.md
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>>`.
16 changes: 16 additions & 0 deletions gitbook/asyncValidation/map2.md
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
17 changes: 17 additions & 0 deletions gitbook/asyncValidation/map3.md
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
13 changes: 13 additions & 0 deletions gitbook/asyncValidation/ofResult.md
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
72 changes: 72 additions & 0 deletions gitbook/asyncValidation/operators.md
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
```

0 comments on commit 474897e

Please sign in to comment.