WTF is a Computation Expression...
Tags: fsharp
Published: 2020-07-22 06:58:11

---
title: WTF is a Computation Expression...
published: true
date: 2020-07-20 08:00:00 UTC
tags: fsharp
canonical_url: https://SimonReynolds.ie/wtf-is-a-computation-expression/
---

 ![WTF is a Computation Expression...](https://images.unsplash.com/photo-1477313372947-d68a7d410e9f?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=2000&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ)

...and why should I care?

Every time computation expressions in F# are discussed it's only a matter of time before the dreaded M-word is mentioned. So let's get it out of the way early....

> Monad

Right, that's that done and let's not mention it again. Suffice to say, they're an interesting concept with no equivalent in C# and no necromancy is required to use or make them.

If you've done any async work in F# or anything involving sequences then odds are you've already used a computation expression (CE).

<!--kg-card-begin: markdown-->
```fsharp
let mySequence =
    seq {
        "First Item"
        "Second Item"
    }
    
let myAsyncThing =
    async {
        let! result = DoTheAsyncThing
        return result
    }
```
<!--kg-card-end: markdown-->

The F# compiler has no built-in tricks or optimisations for these, they're just plain computation expressions, just like you can write too!

Every computation expression needs a backing builder class, usually named after the computation, so `async` would have a builder of type `AsyncBuilder`. All it has to do to be used as a CE is implement certain methods, which map to particular keywords inside a CE.

* * *
<!--kg-card-begin: markdown-->

| Method | Typical signature(s) | Description |
| --- | --- | --- |
| Bind | `M<'T> * ('T -> M<'U>) -> M<'U>` | Called for `let!` and `do!` in computation expressions. |
| Delay | `(unit -> M<'T>) -> M<'T>` | Wraps a computation expression as a function. |
| Return | `'T -> M<'T>` | Called for `return` in computation expressions. |
| ReturnFrom | `M<'T> -> M<'T>` | Called for `return!` in computation expressions. |
| Run | `M<'T> -> M<'T>` or `M<'T> -> 'T` | Executes a computation expression. |
| Combine | `M<'T> * M<'T> -> M<'T>` or `M<unit> * M<'T> -> M<'T>` | Called for sequencing in computation expressions. |
| For | `seq<'T> * ('T -> M<'U>) -> M<'U>` or `seq<'T> * ('T -> M<'U>) -> seq<M<'U>>` | Called for `for...do` expressions in computation expressions. |
| TryFinally | `M<'T> * (unit -> unit) -> M<'T>` | Called for `try...finally` expressions in computation expressions. |
| TryWith | `M<'T> * (exn -> M<'T>) -> M<'T>` | Called for `try...with` expressions in computation expressions. |
| Using | `'T * ('T -> M<'U>) -> M<'U> when 'T :> IDisposable` | Called for `use` bindings in computation expressions. |
| While | `(unit -> bool) * M<'T> -> M<'T>` | Called for `while...do` expressions in computation expressions. |
| Yield | `'T -> M<'T>` | Called for `yield` expressions in computation expressions. |
| YieldFrom | `M<'T> -> M<'T>` | Called for `yield!` expressions in computation expressions. |
| Zero | `unit -> M<'T>` | Called for empty `else` branches of `if...then` expressions in computation expressions. |
| Quote | `Quotations.Expr<'T> -> Quotations.Expr<'T>` | Indicates that the computation expression is passed to the Run member as a quotation. It translates all instances of a computation into a quotation. |

<!--kg-card-end: markdown-->

Now that all looks complicated so let's take a quick look at what advantages a CE gives us over writing plain code.

Let's consider an example where we need to pass an item through several validation checks

<!--kg-card-begin: markdown-->
```fsharp
let itemToValidate = SomeThingThatNeedsValidating()

// Each validation methhod has signature Item -> Result<Item, Error>

let firstValidation = firstValidationCheck itemToValidate

let secondValidation =
    match firstValidation with
    | Error e -> e
    | Ok item -> secondValidationCheck item

let thirdValidation =
    match secondValidation with
    | Error e -> e
    | Ok item -> thirdValidationCheck item
```
<!--kg-card-end: markdown-->

You probably look at that and think there must be a better way to write that. And you'd be right, this is a great example where we can use a computation expression.

To build it, let's look at the `Result` type and see if it has anything that can help us.

There is already a `Result.bind` that does the same as the `match` statements above, so let's use that instead of reinventing the wheel.

<!--kg-card-begin: markdown-->
```fsharp
type ResultBuilder() =

    // This can be used in a CE via the let! keyword
    // Result<'a,'b> * ('a -> Result<'c,'d>) -> Result<'c,'d>
    member __.Bind(r, f) = Result.bind f r
    
    // This can be used in a CE via the return keyword
    // 'a -> Result<'a, 'b>
    member __.Return(x) = Ok x
    
// This exposes the builder type as a computation expression
// It's what allows to use it like below...
let result = ResultBuilder()
```
<!--kg-card-end: markdown-->

Short, sharp and to the point, right? But now we can express the validation checks above like this...

<!--kg-card-begin: markdown-->
```fsharp
let itemToValidate = SomeThingThatNeedsValidating()

let validatedItem =
    result { // result here is the created instance of ResultBuilder from above
        let! firstCheck = firstValidationCheck itemToValidate
        let! secondCheck = secondValidationCheck firstCheck
        let! thirdCheck = thirdValidationCheck secondCheck
        return thirdCheck
    }
```
<!--kg-card-end: markdown-->

The beauty of this approach is that the `let!` keyword will only bind the successful validation and allow the CE to continue evaluating. If an error is returned from any of the validation checks then the entire CE will short circuit and return that error immediately.

Congratulations, you now have a basic working CE of your very own! But a lot of that code looks like we shouldn't need it. Why assign each intermediate result to a variable along the way, surely we should just be able to pipe each step in to the next, right?

Let's  add two further items to where we create our `ResultBuilder`

<!--kg-card-begin: markdown-->
```fsharp
// F# allows us to define our own operators
// By convention, >>= usually refers to a bind method
let (>>=) result binder = Result.bind binder result

type ResultBuilder() =

    // This can be used in a CE via the let! keyword
    // Result<'a,'b> * ('a -> Result<'c,'d>) -> Result<'c,'d>
    member __.Bind(r, f) = Result.bind f r
    
    // This can be used in a CE via the return keyword
    // 'a -> Result<'a, 'b>
    member __.Return(x) = Ok x
    
    // This can be used in a CE via the return! keyword
    // Result<'a, 'b> -> Result<'a, 'b>
    member __.ReturnFrom x = x
    
let result = ResultBuilder()
```
<!--kg-card-end: markdown-->

Now we can chain together our validation checks and it becomes a lot easier to be able to add new checks, compose smaller ones together, or reorder them without having to rename every variable along the way.

<!--kg-card-begin: markdown-->
```fsharp
let itemToValidate = SomeThingThatNeedsValidating()

let validatedItem =
    result {
        return!
            firstValidationCheck itemToValidate
            >>= secondValidationCheck
            >>= thirdValidationCheck
    }
```
<!--kg-card-end: markdown-->

Now if we found we needed an extra check that should be between `secondValidationCheck` and `thirdValidationCheck`, it is as simple as adding it in.

Hopefully this has helped to show you the power of a computation expression and that they aren't as scary as they first seemed. Of course this was a relatively simple example but from here you can see how they can be extended with additional functionality and even custom keywords that can be used to create miniature programming languages to solve problems. More to come on that front....