Building Custom Computation Expressions

Return / ReturnFrom return / return! Yield / YieldFrom yield / yield! if without else Combine + Delay Sequencing multiple expressions For / While TryWith / TryFinally / Using MergeSources / BindReturn and! (applicative) Custom keywords like where, select

Resumable code (F# 6) lets builders compile to efficient state machines (this is how task { } is so fast).

// A result builder
type ResultBuilder() =
    member _.Bind(m, f) = Result.bind f m
    member _.Return(x) = Ok x
    member _.ReturnFrom(m: Result<_, _>) = m
    member _.Zero() = Ok ()
    member _.Combine(m, f) = Result.bind f m
    member _.Delay(f: unit -> Result<_, _>) = f
    member _.Run(f) = f ()

let result = ResultBuilder()

let parseInt (s: string) =
    match System.Int32.TryParse s with
    | true, v -> Ok v
    | _ -> Error $"Not a number: {s}"

let addStrings a b = result {
    let! x = parseInt a
    let! y = parseInt b
    if y = 0 then return! Error "Second value is zero"
    else return x + y
}
addStrings "2" "3"            // Ok 5
addStrings "2" "x"            // Error "Not a number: x"

// An option builder
type OptionBuilder() =
    member _.Bind(m, f) = Option.bind f m
    member _.Return(x) = Some x
    member _.ReturnFrom(m) = m
let option = OptionBuilder()

let tryDivide x y = if y = 0 then None else Some (x / y)
option {
    let! a = tryDivide 100 5
    let! b = tryDivide a 2
    return a + b
}                              // Some 30

// A logging builder (Writer-like)
type LoggingBuilder() =
    member _.Bind((value, logs: string list), f) =
        le
…