My first attempt as implementing a Computational Expression in F#

So this is my first attempt at implementing a computational expression in F#. I’m not going to go into definitions or the likes as to what computational expressions are as there are far better posts out there on this subject than I could probably write, at this time. I’ll list some in a “further reading” section at the end of the post.

What I’m going to present here is a builder which really just creates a list of names – nothing particularly clever – but it gives a basic idea on getting started with computational expressions (I hope).

So first off we need to create a builder type, mine’s called CurveBuilder

type Items = Items of string list

type CurveBuilder() =
    member this.Yield (()) = Items []

    [<CustomOperation ("create", MaintainsVariableSpace = true)>]
    member this.Create (Items sources, name: string) = 
        Items [ yield! sources
                yield name ]

As this is just a simple demo, the only thing I’m doing is creating a list of strings which you would be correct in thinking that I could do easier using a collection class, but I’m really just interested in seeing the builder and it’s interactions without too much clutter, so go with me on this one…

Before we discuss the builder code, let’s take a look at how we’d use a builder in our application

let builder = CurveBuilder()

let curves = 
   builder {
      create "risky_curve1.gbp"
      create "risky_curve2.usd"
   }

In this code we first create an instance of a CurveBuilder, then when we use the builder to create a list of the curves. The Yield method is first called on the CurveBuilder, returning an empty Items value. Subsequent calls to the create method then call the Create method of the CurveBuilder and, as can be seen, create a new Items value containing the previous Items plus our new curve name.

Simple enough but surely there’s more to this than meets the eye

The example above is a minimal implementation, of course, of a builder. You’ll notice that we have an attribute on one method (the Create method) and not on the Yield method.

So the attribute CustomOperation is used on a member of a builder to create new “query operators”. Basically it extends the builder functionality with new operators named whatever you want to name them.

On the other hand the Yield method is a “standard” builder method. There are several other methods which F# knows about implicitly within a builder class, including Return, Zero, Bind, For, YieldFrom, ReturnFrom, Delay, Combine, Run and more, see Computation Expressions (F#)
for a full list of “built-in workflows”. With these we can obviously produce something more complex than the example presented in this post – which is in essence a glorified “list” builder with snazzy syntax.

Discriminated Union gotcha

One thing I got caught out with from the above code is that I wanted to simply list the curves I’d created but couldn’t figure out how to “deconstruct” the discriminated union

type Items = Items of string list

to a simple string list – at this point I claim ignorance as I’m not using F# as much as I’d like so am still fairly inexperienced with it.

My aim was to produce something like this

for curve in curves do
   printfn "Curve: %s" curve

but this failed with the error The type ‘Items’ is not a type whose values can be enumerated with this syntax, i.e. is not compatible with either seq<_>, IEnumerable<_> or IEnumerable and does not have a GetEnumerator method

I need to in essence disconnect the Items from the string list, to achieve this I found the excellent post Discriminated Unions.

The solution is as follows

let (Items items) = curves

for curve in items do
    printfn "Curve: %s" curve

Note: the let (Items items) = curves

Further Reading
Implementing a builder: Zero and Yield
Implementing a builder: Combine
Implementing a builder: Delay and Run
Implementing a builder: Overloading
Implementing a builder: Adding laziness
Implementing a builder: The rest of the standard methods

Computation Expressions (F#)