On Tue, Jun 06, 2000 at 11:30:41AM -0700, John Launchbury wrote:
> I don't think that's a very accurate description. The "let" in "do"
> is a bit of a different beast from the usual "let..in" construct.
> For a start, it doesn't have an "in" keyword.
But it is in the translation, of course:
do {let decls; stmts} = let decls in do {stmts}
Going off on a somewhat trivial syntactic tangent, if we think of
p <- e; s as a representation of monadic let, wouldn't it make sense
to have a monadic letrec, with a syntax like that in O'Haskell:
do x <- foo
rec p1 <- e1
...
pn <- en
stmts
(though O'Haskell uses "fix" instead of "rec".) Then for the example
in section 3.2 of the mdo paper you could write
do putStr "forming a list of 1s"
rec ones <- return (1:ones)
putStr "forming a list of 2s"
rec twos <- return (2:twos)
return (ones, twos)
(ignoring the fact that these bindings could be plain let's)
In connection with that example, it's a bit worrying that understanding
the extent of the the mfix's added and even the termination behaviour
seems to require following the segmentation algorithm. I get the
impression that the segmented translation is mainly there because of
the awkwardness of writing things like the version at the top of p3.
(BTW there's a typo there: "ones" for "twos".) Without segmentation,
I imagine you'd often be writing stuff like
do ...
(x,y,z) <- mdo
x <- e1
y <- e2
z <- e3
return (x,y,z)
...
corresponding to "rec" above.
BTW, my arrow notation proposal also has recursive bindings (for
appropriate arrows), with a "rec" keyword as above. It also forces
monomorphic let's (even when no recursion is present).