It appears to me that: * Many people don't like having to "extract values" from a monad on a separate line, but would like to be able to mix monadic return values into pure expressions, on the way to calculating a monadic result. * Some people want to fix this by doing an implicit lifting operation on functions, when their parameters are monadic * It is not really clear what values are "monadic" and which aren't, so the implicit lifting is a guessing game, and likely to produce confounding errors. * If you aren't going to be precise about what's in the monad and what's not, you might as well use ML. I propose instead an explicit, lightweight notation, with a simple rewrite rule. Instead of: do putStr "What is your name? " s <- getLine putStrLn ("Hello " ++ s) I would like to write something like: do putStr "What is your name? " putStrLn ("Hello " ++ {* getLine *}) In other words, we use some kind of special brackets (I don't care what) to indicate that this value needs to be extracted from the monad on a previous line, and inserted back here as a "pure" value. If these occur multiply nested, they can be flattened out according to a dependency rule. E.g., do m1 {* m2 {* m3 *} v4 *} {* m5 *} ...would be rewritten as... do v3 <- m3 v2 <- m2 v3 v4 v5 <- m5 m1 v2 v5 ...and... do m1 {* {* m2 *} *} ...would become... do m2a <- m2 v2 <- m2a m1 v2 I'm sure this has been suggested before... but what do folks think? - Lyle