# Asynchronous monads by Mark Seemann

*Asynchronous computations form monads. An article for object-oriented programmers.*

This article is an instalment in an article series about monads. A previous article described how asynchronous computations form functors. In this article, you'll see that asynchronous computations also form monads. You'll learn about closely related monads: .NET Tasks and F# asynchronous workflows.

Before we start, I'm going to repeat the warning from the article about asynchronous functors. .NET Tasks aren't referentially transparent, whereas F# asynchronous computations are. You could argue, then, that .NET Tasks aren't proper monads, but you mostly observe the difference when you perform impure operations. As a general observation, when impure operations are allowed, the conclusions of this overall article series are precarious. We can't radically change how the .NET languages work, so we'll have to soldier on, pretending that impure operations are delegated to other parts of our system. Under this undue assumption, we can pretend that Task<T> forms a monad. Also, while there are differences, it sometimes helps to think of `Task<T>`

as a sort of poor man's IO monad.

### Monadic bind #

A monad must define either a *bind* or *join* function. In C#, monadic bind is called `SelectMany`

. You can define one as an extension method on the Task<T> class:

public async static Task<TResult> SelectMany<T, TResult>( this Task<T> source, Func<T, Task<TResult>> selector) { T x = await source; return await selector(x); }

With `SelectMany`

, you can compose various tasks and flatten as you go:

Task<int> x = AsyncValue( 42); Task<int> y = AsyncValue(1337); Task<int> z = x.SelectMany(async i => i + await y);

If you're wondering how this is useful, since C# already has `async`

and `await`

keywords for that purpose, I can understand you. Had you not had that language feature, monadic bind would have been helpful, but now it feels a little odd. (I haven't been deep into the bowels of how that language feature works, but from what little I've seen, monads play a central role - just as they do in the LINQ language feature.)

In F# you can define a `bind`

function that works on `Async<'a>`

values:

// ('a -> Async<'b>) -> Async<'a> -> Async<'b> let bind f x = async { let! x' = x return! f x' }

For both the C# and the F# examples, the exercise seems a little redundant, since they're both based on language features. The C# `SelectMany`

implementation uses the `async`

and `await`

keywords, and the F# `bind`

function uses the built-in `async`

computation expression. For that reason, I'll also skip the section on syntactic sugar that I've included in the previous articles in this article series. Syntactic sugar is already built into the languages.

### Flatten #

In the introduction you learned that if you have a `Flatten`

or `Join`

function, you can implement `SelectMany`

, and the other way around. Since we've already defined `SelectMany`

for `Task<T>`

, we can use that to implement `Flatten`

. In this article I use the name `Flatten`

rather than `Join`

. This is an arbitrary choice that doesn't impact behaviour. Perhaps you find it confusing that I'm inconsistent, but I do it in order to demonstrate that the behaviour is the same even if the name is different.

The concept of a monad is universal, but the names used to describe its components differ from language to language. What C# calls `SelectMany`

, Scala calls `flatMap`

, and what Haskell calls `join`

, other languages may call `Flatten`

.

You can always implement `Flatten`

by using `SelectMany`

with the identity function.

public static Task<T> Flatten<T>(this Task<Task<T>> source) { return source.SelectMany(x => x); }

The F# version uses the same implementation - it's just a bit terser:

// Async<Async<'a>> -> Async<'a> let flatten x = bind id x

In F#, `id`

is a built-in function.

### Return #

Apart from monadic bind, a monad must also define a way to put a normal value into the monad. Conceptually, I call this function *return* (because that's the name that Haskell uses). You don't, however, have to define a static method called `Return`

. What's of importance is that the capability exists. For `Task<T>`

this function already exists: It's called FromResult.

In F#, it's not built-in, but easy to implement:

// 'a -> Async<'a> let fromValue x = async { return x }

I called it `fromValue`

inspired by the C# method name (and also because `return`

is a reserved keyword in F#).

### Left identity #

We need to identify the *return* function in order to examine the monad laws. Now that this is done, let's see what the laws look like for the asynchronous monads, starting with the left identity law.

[Property(QuietOnSuccess = true)] public void TaskHasLeftIdentity(Func<int, string> h_, int a) { Func<int, Task<int>> @return = Task.FromResult; Task<string> h(int x) => Task.FromResult(h_(x)); Assert.Equal(@return(a).SelectMany(h).Result, h(a).Result); }

Like in the previous article the test uses FsCheck 2.11.0 and xUnit.net 2.4.0. FScheck can generate arbitrary functions in addition to arbitrary values, but it unfortunately, it can't generate asynchronous computations. Instead, I've asked FsCheck to generate a function that I then convert to an asynchronous computation.

The code I'm using for this article is quite old, and neither FsCheck 2.11.0 nor xUnit.net 2.4.0 can handle asynchronous unit tests (a capability that later versions do have). Thus, the assertion has to force the computations to run by accessing the `Result`

property. Not modern best practice, but it gets the point across, I hope.

In F# I wrote monad law examples using Kleisli composition. I first defined a function called `fish`

:

// ('a -> Async<'b>) -> ('b -> Async<'c>) -> 'a -> Async<'c> let fish f g x = async { let! x' = f x return! g x' }

Keep in mind that *fish* is also a verb, so that's okay for a function name. The function then implements the *fish operator:*

`let (>=>) = Async.fish`

This enables us to give an example of the left identity law using Kleisli composition:

[<Property(QuietOnSuccess = true)>] let ``Async fish has left identity`` (h' : int -> string) a = let h x = async { return h' x } let left = Async.fromValue >=> h let right = h Async.RunSynchronously (left a) =! Async.RunSynchronously (right a)

The `=!`

operator is an Unquote operator that I usually read as *must equal*. It's a test assertion that'll throw an exception if the left and right sides aren't equal.

### Right identity #

In a similar manner, we can showcase the right identity law as a test - first in C#:

[Property(QuietOnSuccess = true)] public void TaskHasRightIdentity(int a) { Func<int, Task<int>> @return = Task.FromResult; Task<int> m = Task.FromResult(a); Assert.Equal(m.SelectMany(@return).Result, m.Result); }

Here's a Kleisli-composition-based F# property that demonstrates the right identity law for asynchronous workflows:

[<Property(QuietOnSuccess = true)>] let ``Async fish has right identity`` (f' : int -> string) a = let f x = async { return f' x } let left = f let right = f >=> Async.fromValue Async.RunSynchronously (left a) =! Async.RunSynchronously (right a)

As always, even a property-based test constitutes no *proof* that the law holds. I show it only to illustrate what the laws look like in 'real' code.

### Associativity #

The last monad law is the associativity law that describes how (at least) three functions compose.

[Property(QuietOnSuccess = true)] public void TaskIsAssociative( Func<DateTime, int> f_, Func<int, string> g_, Func<string, byte> h_, DateTime a) { Task<int> f(DateTime x) => Task.FromResult(f_(x)); Task<string> g(int x) => Task.FromResult(g_(x)); Task<byte> h(string x) => Task.FromResult(h_(x)); Task<int> m = f(a); Assert.Equal(m.SelectMany(g).SelectMany(h).Result, m.SelectMany(x => g(x).SelectMany(h)).Result); }

This property once more relies on FsCheck's ability to generate arbitrary pure functions, which it then converts to asynchronous computations. The same does the Kleisli-composition-based F# property:

[<Property(QuietOnSuccess = true)>] let ``Async fish is associative`` (f' : int -> string) (g' : string -> byte) (h' : byte -> bool) a = let f x = async { return f' x } let g x = async { return g' x } let h x = async { return h' x } let left = (f >=> g) >=> h let right = f >=> (g >=> h) Async.RunSynchronously (left a) =! Async.RunSynchronously (right a)

It's easier to see the associativity that the law is named after when using Kleisli composition, but as the article about the monad laws explained, the two variations are equivalent.

### Conclusion #

Whether you do asynchronous programming with `Task<T>`

or `Async<'a>`

, asynchronous computations form monads. This enables you to piecemeal compose asynchronous workflows.

**Next:** The State monad.