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?
You had the answer yourself. From the F# spec that describes how computation expressions are translated:
So no, you don’t need to define let explicitly anymore, it’s translated by the compiler.
Update: this change is mentioned in the detailed release notes of the September CTP.