Skip to content

Commit 101df35

Browse files
committed
Add parallelAsyncResult docs
1 parent b8bb712 commit 101df35

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

gitbook/parallelAsyncResult/ce.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
## ParallelAsyncResult Computation Expression
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
This CE operates on the same type as `asyncResult`, but it adds the `and!` operator for running workflows in parallel.
6+
7+
Concurrent workflows are run with the same semantics as [`Async.Parallel`](https://fsharp.github.io/fsharp-core-docs/reference/fsharp-control-fsharpasync.html#Parallel), so only the first exception is returned.
8+
9+
10+
## Examples
11+
12+
### Example 1
13+
14+
Suppose we want to download 3 files.
15+
16+
Here is our simulated download function:
17+
18+
```fsharp
19+
// string -> Async<Result<string, string>>
20+
let downloadAsync stuff : Async<Result<string, string>> = async {
21+
do! Async.Sleep 3_000
22+
return Ok stuff
23+
}
24+
```
25+
26+
This workflow will download each item in sequence:
27+
28+
```fsharp
29+
let downloadAllSequential = ayncResult {
30+
let! x = downloadAsync (Ok "We")
31+
let! y = downloadAsync (Ok "run")
32+
let! z = downloadAsync (Ok "sequentially :(")
33+
return sprintf "%s %s %s" x y z
34+
}
35+
```
36+
37+
It takes 9 seconds to complete.
38+
39+
However, using `parallelAsyncResult`, we can download all 3 concurrently:
40+
41+
```fsharp
42+
// Async<Result<string, string>>
43+
let downloadAll = parallelAsyncResult {
44+
let! x = downloadAsync (Ok "We")
45+
and! y = downloadAsync (Ok "run")
46+
and! z = downloadAsync (Ok "concurrently!")
47+
return sprintf "%s %s %s" x y z
48+
}
49+
```
50+
51+
This takes just 3 seconds.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
## ParallelAsyncResult.map2
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
Function Signature:
6+
7+
```fsharp
8+
('a -> 'b -> 'c) -> Async<Result<'a, 'd>> -> Async<Result<'b, 'd>>
9+
-> Async<Result<'c, 'd>>
10+
```
11+
12+
## Examples
13+
14+
Note: Many use-cases requiring `map2` operations can also be solved using [the `parallelAsyncResult` computation expression](../parallelAsyncResult/ce.md).
15+
16+
### Example 1
17+
18+
Given the functions
19+
20+
```fsharp
21+
getFollowerIds : UserId -> Async<Result<UserId list, exn>>
22+
createPost : CreatePostRequest -> Async<Result<PostId, exn>>
23+
```
24+
25+
And the type
26+
27+
```fsharp
28+
type NotifyNewPostRequest =
29+
{ UserIds : UserId list
30+
NewPostId : PostId }
31+
static member Create userIds newPostsId =
32+
{UserIds = userIds; NewPostId = newPostsId}
33+
```
34+
35+
We can create a `NotifyNewPostRequest` using `ParallelAsyncResult.map2` as below:
36+
37+
```fsharp
38+
let createPostAndGetNotifyRequest (req : CreatePostRequest) =
39+
// Async<Result<UserId list, exn>>
40+
let getFollowersResult = getFollowerIds req.UserId
41+
42+
// Async<Result<PostId, exn>>
43+
let createPostResult = createPost req
44+
45+
// Async<Result<NotifyNewPostRequest, exn>>
46+
let newPostRequestResult =
47+
ParallelAsyncResult.map2
48+
NotifyNewPostRequest.Create getFollowersResult createPostResult
49+
50+
// ...
51+
```
52+
53+
This workflow will run the sub-tasks `getFollowersResult` and `createPostResult` concurrently, which can increase throughput.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## ParallelAsyncResult.map3
2+
3+
Namespace: `FsToolkit.ErrorHandling`
4+
5+
Function Signature:
6+
7+
```fsharp
8+
('a -> 'b -> 'c -> 'd)
9+
-> Async<Result<'a, 'e>>
10+
-> Async<Result<'b, 'e>>
11+
-> Async<Result<'c, 'e>>
12+
-> Async<Result<'d, 'e>>
13+
```
14+
15+
## Examples
16+
17+
Note: Many use-cases requiring `map3` operations can also be solved using [the `parallelAsyncResult` computation expression](../parallelAsyncResult/ce.md).

0 commit comments

Comments
 (0)