On Wed, 17 Sep 2003, Brandon Michael Moore wrote:
The problem with that is that not all monads support recursive bindings. We can deal with that, but the desuagring of a do statement wouldn't be so trivial any more. The most sensible approach I can think of is to analyze the bindings and generate a translation involving mfix if the bindings are recursive, and a translation without if they are not. I don't like complicating the translation, but at least it is still purely syntactic.
I'm also worried about making the typing of a statement depend on the binding structure, rather than just the types of subexpressions and how they are used. It's probably a bit simpler than the normal mental typechecking we do, but it is different. If we do this we should try for nice warnings about recursively defined variables if failures to staisfy the MonadFix constraint suggest the do statement was wrong.
In any case, I don't see the need for explicit rec groups. Can't GHC just find the strongly connected components like it already does with let bindings? Don't the laws for loop and mfix justify the transformation? If you really need to specify the binding groups (or at least provide an upper bound on their size) you can use explicit nested mdo statements.
I don't think we should force the programmer to explicitly identify groups of recursive bindings. It's probably not even worth providing synatx beyond nested mdo statements uness is is frequently necessary. I agree with Iavor that we should try for simplicity and consistency. Are there any gaping holes in my musings on his proposal?
We were rooting for a single "do" construct that'll capture recursion automatically from the start. However, there are a couple of issues: 1. Shadowing (you've already pointed that out.) 2. Polymorphic let bindings inside the do notation, when they are used in a prior statement. (This complicates things quite a bit from type-checking perspective.) 3. The need for automatic segmentation to overcome right-shrinking issues. (Not a real problem in reality, but at least "mdo" makes it obvious that something different is going on.) After much discussion, the consensus was to keep recursive-do separate at least for the time being. Maybe Haskell-2 can incorporate it right away without the need for "mdo." Again, all this stuff is discussed in chapter 7 of the thesis (especially section 7.2), available at: http://www.cse.ogi.edu/pacsoft/projects/rmb -Levent.