
I think that defining lifted versions of every function is dangerous, especially in a widely-used library. Monadic code will start to look pure, and before long someone will be using let expressions and where blocks to share monadic computations rather than using do blocks to share the *results* of monadic computations.
yes. we actually had that fun with Conal Elliott's functional reactive programming libraries, where all expressions were lifted to a reader monad for time (expressions not mentioning time were constant, those mentioning time were dependent on the overall progress of time). the limitations of overloading (Bool, mostly) and the variations of sharing possible in expressions overloaded this way led to quite a bit of research as well as implementation and language extensions. it is a borderline case: it results in an embedded domain-specific language that looks a lot like haskell, but isn't haskell. as long as one keeps the difference in mind, it is useful, though. having such overloaded operations in an edsl for low-level imperative programming in haskell might be worthwhile, and since some people have been asking for it, i wanted to point out that it is possible. for general use, i agree that explicit control (using idioms perhaps) is safer. although there are functional languages that are based on the everything is monadic-io slogan (scheme, lisp, mls,..). the monad subexpressions under discussion are somewhere in between those extremes, with some syntactic differences, some control, and their own complications. claus