I do not understand the difference between the three syntaxes:
where a = f (b)do a <- f (b)do let a = f (b)
I do understand somehow though that a <- f(b) is different from the other two, in most cases where I tried all three worked. Also I read somewhere on the net that per block you should try to get along with one let binding only in order to be “idiomatic”. But I never seem to manage.
How do I decide what to use?
let foo = bar in ...simply definesfooto be the exact same thing asbarwithin the context of...; you could simply use textual substitution to replace all uses offooin...with(bar)and get the exact same result.whereclauses are similar tolet...inexpressions, but go at the end of a function clause, instead of being an expression. For instance,There is no way to rewrite this with
let...inwithout changing the guards intoif...then...elses. Often,whereclauses are used overlet...inclauses purely for reasons of style.The bind operator is something different entirely. It’s used in
donotation to “extract” a value from a monadic computation. That is, iffoohas the typem a, then afterx <- foo,xhas the typea. All the other “binding” forms just define names, but<-is used for binding a computation’s result to a name from within a monad.<-can only be used inside adoblock, so it’s exclusively used to build up a larger computation in the same monad as the action you’re binding the result of.let foo = barindonotation is just a convenience; you can rewrite:as
but that gets messy when you have a lot of such bindings, as the
doblocks get nested deeper and deeper.I don’t know what the advice you mentioned is talking about; you can define multiple variables in a
let...inblock just fine, andis more idiomatic than