I'm looking to learn F#, but one thing that's confusing to me is the computation expression (do-notation??) syntax and desugaring.
In haskell, you have a very simple Monad typeclass and rules for desugaring do-notation into bind and return. There's no magic involved in adding keywords; the only thing must match up are the types.
In F# there's a bunch of builders, and keywords, and complexity.
Is there a good explanation of how to map one concept to the other?
I basically want to know how I map
do
x <- monadicComputation
foo x
someOtherMonadicComputation
let y = somePureComputation x
return $ bar y
to F#.
The only keywords in the haskell are do, (<-) and let.
You can't write generic monadic code in F#, instead you have to specify the monad you're working in by naming the builder associated with the expression. Your example code would look like:
let example = async {
let! a = someAsyncComputation
foo a
do! someOtherAsyncComputation
let y = somePureComputation a
return (bar y)
}
for the async
computation expression type. The 'bang' pattern (do!, let! etc.) is used when binding monadic values, while the regular keywords are used for non-monadic values.
let!
corresponds to bind (>>=)
while let
corresponds to let
in do
notation. return
corresponds to return
, while return!
is used to yield an existing monadic value. do!
is similar to (>>)
which executes a monadic value for its effects, while do
is for non-monadic effects, which has no parallel in Haskell.