
to illustrate why some of us are concerned about this extension, a few examples might help. consider: f (g (<- mx)) does this stand for (a) mx >>= \x-> f (g x) (b) f (mx >>= \x-> (g x)) (c) none of the above, because there's no do (d) something else entirely if (a/b), does the decision depend on the type of g (if g is pure, then (a), if g is monadic itself, then (b))? if (d), what? if (a/b), then this is no longer preprocessing, but depends on the types, which means that the type system must work in the presence of this extension, rather than its pre-processed form. if you want to avoid that, you're left with (c), but is that any better? if (c), then the following are no longer equivalent 1. return ... 2. do return ... in particular, do return .. is no longer a unit of the monad (in (a/b), even return .. isn't). so if you write f (do g (<- mx)) you mean (b), while if you write do f (g (<- mx)) you mean (a), and if you write f (g (<- mx)) you mean either an error, if there is no surrounding 'do', or something else, if there is a surrounding 'do'. and woe to those who think they can insert some 'do' notation whereever they like - they need to check the subexpressions for (<-) first! now, consider nesting monadic subexpressions: f (<- g (<- mx)) surely means the same as f =<< (g =<< mx), namely mx >>= \x-> g x >>= \gx-> f gx right? wrong! we forgot the 'do'. without a 'do'-context, this means nothing in (c). so if you have do .. fx <- f (<- g (<- mx)) .. fx <- f (<- g (<- mx)) .. and there are no free variables, then you can do the usual sharing to improve readability, right? let fgmx = f (<- g (<- mx)) in do .. fx <- fgmx .. fx <- fgmx .. wrong again! this is syntax, not expression, so the latter variant changes the scope the (<-)s refer to (some outer 'do', if one exists). you could have written do let fgmx = f (<- g (<- mx)) .. fx <- fgmx .. fx <- fgmx .. perhaps, and at this stage you might no longer be surprised that do and let no longer commute. or were you? if you weren't, here's a quick question: we've already seen the left- and right-identity laws in danger, so what about associativity? do { do { a; b}; c } is still the same as do { a; do { b; c } } yes? no? perhaps? sometimes? how long did it take you? could someone please convince me that i'm painting far too gloomy a picture here?-) claus