Update (12 September 2009): The community has provided a more elegant solution to this problem. See my more recent post for more details here: F# Pipelined Monads – Solutions From the Community. Thanks go to Keith Battocchi and Felix (felixmar on hubFS) for the revised solution. I have left this post unchanged and I advise you to use the revised solution in your own projects.
I recently completed my own construction of a couple of monads that I am using in a mini-project. I like the way that I am able to compose functions returning monadic values by using let! and do! directly. However, I was frustrated by the need to use multiple let! statements when I needed to chain constructs into a pipeline, for example:
let result = myBuilder {
let result1 = initialValue
let! r2 = r1 |> f1
let! r3 = r2 |> f2
let! r4 = r3 |> f3
return r4 }
It is important to use let! because each step in the pipeline is allowed to fail. More generally, the behaviour required is that bind must be incorporated into the pipeline. Additionally, the proliferation of intermediary variables greatly increased the possibility of error in my code because I might have referred to one of the intermediate results, rather than the most recent result. Compare this to a non-computation expression version:
let result =
initialValue
|> f1
|> f2
|> f3
The challenge before me was could I do any better?
Continue reading →