You are previewing Programming F#.

Programming F#

Cover of Programming F# by Chris Smith Published by O'Reilly Media, Inc.

Computation Expression Builders

Computation expressions in a nutshell are syntactic transforms for F# code, just like let_with_check in the previous example. Let’s look at how you can leverage F#’s support for computation expressions to simplify your code.

Example 10-4 shows how to create a custom workflow. We’ll go over what’s going on behind the scenes in a moment. For now, just look at the implementation of the Bind method, the defined { } block, and the use of the let! keyword.

Example 10-4. The success/failure computation expression

type Result = Success of float | DivByZero

let divide x y =
    match y with
    | 0.0 -> DivByZero
    | _   -> Success(x / y)

type DefinedBuilder() =

    member this.Bind ((x : Result), (rest : float -> Result)) =
        // If the result is Success(_) then execute the
        // rest of the function. Otherwise terminate it
        // prematurely.
        match x with
        | Success(x) -> rest x
        | DivByZero  -> DivByZero

    member this.Return (x : 'a) = x

// Create an instance of our computation expression builder
let defined = DefinedBuilder()

let totalResistance r1 r2 r3 =
    defined {
        let! x = divide 1.0 r1
        let! y = divide 1.0 r2
        let! z = divide 1.0 r3
        return divide 1.0 (x + y + z)

You can test this in FSI and verify that the computation expression version gets the same results, and in one-third the lines of code!

> totalResistance 0.01 0.75 0.33;;
val it : Result = Success 0.009581881533
> totalResistance 0.00 0.55 0.75;;
val it : Result = DivByZero

All computation expressions do is break the expression ...

The best content for your career. Discover unlimited learning on demand for around $1/day.