[Haskell-cafe] monad subexpressions
Claus Reinke
claus.reinke at talk21.com
Fri Aug 3 12:12:13 EDT 2007
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
More information about the Haskell-Cafe
mailing list