I'm using F# v 1.9.6.2, and I've defined a very simple computation expression:
type MaybeBuilder() =
member this.Let(x, f) =
printfn "this.Let: %A" x
this.Bind(Some x, f)
member this.Bind(x, f) =
printfn "this.Bind: %A" x
match x with
| Some(x) when x >= 0 && x <= 100 -> f(x)
| _ -> None
member this.Delay(f) = f()
member this.Return(x) = Some x
let maybe = MaybeBuilder()
I've sprinkled some print statements in the code to tell me which methods are being called in a computation expression. When I execute the following statement:
maybe {
let x = 12
let! y = Some 11
let! z = Some 30
return x + y + z
}
I expect the console to print out the following:
this.Let 12 this.Bind Some 12 this.Bind Some 11 this.Bind Some 30
But my actual results are as follows:
this.Bind: Some 11 this.Bind: Some 30
In other words, F# doesn't appear to be executing the Let
member. When I re-write Let
to throw an exception, the code run without an exception. Additionally, when I comment out the Let
member entirely, I do not get an error message stating The field, constructor or member 'Let' is not defined
, and the code executes as expected.
(I've tried investigating the code with Reflector, but as is usually the case, decompiled F# is mangled beyond readability.)
It looks like the spec for computation expressions has changed. Are let
bindings no longer treated as syntax sugar, and is the Let
members no longer required in computation workflows?