
do a <- x let b = a y b z
expands to
do {a <- x ; let {b = a} in do {y b >> z}}
I'm curious as to where the second `do' came from?
Well, the above translation isn't quite correct, the second 'do' wouldn't come until later. The point is that 'do { let x = y; foo }' translates to 'let x = y in do { foo }'.
Exatly, I should have checked better that example. I just thought it worth to show how 'let' translates in a 'do' expression, because it caused me a lot of trouble when I learned Haskell. Since I had read that 'do' expressions are supposed to chain (Monad m) => (m a) elements, I assumed from this use of 'let' that: (WARNING: WRONG ASSUMPTIONS!) * 'let a = b' has type (Monad m) => (m x), x the type of a and b. * Since 'let' is used in let expressions and also in do expressions, either Haskell allows redefinition of reserved keywords or 'let' is not a reserved keyword and there's some way in Haskell to define constructs like 'let ... in ...' using more basic primitives. * Haskell has some kind of overloading allowing one word to be used in unrelated contexts. That's of course completely nonsense, but I would be happy if I could avoid others from running into this kind of misunderstanding. Best, Maurício