[Haskell-cafe] Re: monad subexpressions
Dan Doel
dan.doel at gmail.com
Fri Aug 3 19:04:52 EDT 2007
On Friday 03 August 2007, Sebastian Sylvan wrote:
> On 03/08/07, Claus Reinke <claus.reinke at talk21.com> wrote:
> > ah, a concrete example. but isn't that the typical use case for ap?
> >
> > mytransaction = foo `liftM` r xvar0 `ap` r xvar1 ..
> > where r = readTVar
>
> I really find it difficult to articulate why this isn't acceptable,
> because it seems so obvious to me! It's short yes, but I really don't
> think it's very clear...
> I have a hard time believing that anyone finds that natural. After
> lots and lots of mind-bending forays into various branches of
> mathematics, then yes maybe you can get used to it, but it's hardly as
> natural as saying "add this one symbol to your values to extract
> monadic values left-to-right".
Note that if this is the example we're using, idiom brackets solve things:
mytransaction = [[ foo (r xvar0) (r xvar1) ...]]
where r = readTVar
and are, possibly, less fraught with peril, considering all the discussions
about where the desugaring should place the implicit binding, and what
happens if there isn't an enclosing do and so on (as idiom brackets desugar
to the "foo `liftM` r xvar0 `ap` r xvar1 ..." mentioned above, and the entire
expression is delimited, there are no such questions to be pondered, I
think).
Also, note, if you use the operators in Control.Applicative, then:
return $ foo $(bar1) $(bar2) $(bar3) ...
can be:
return foo <*> bar1 <*> bar2 <*> bar3 ...
or:
foo <$> bar1 <*> bar2 <*> bar3
I don't (personally) see how that's any more cryptic than placing brackets
around around the monadic values themselves. In either case, there's some
magic going on that the user may or may not understand. In the applicative
case, it's using a different kind of (Monadic/Applicative) function
application via an operator. In the monad brackets case, it's doing a macro
expansion. I, personally find the former clearer, but perhaps that's because
I understand Applicative fairly well, but only have a vague idea of what,
specifically, the macro will be doing so far.
To get outside the scope of idiom brackets/applicative, you'd need a use case
like:
if $(mexpr) then branch1 else branch2
or (lest that be to easy):
case $(mexpr) of
p1 -> branch1
p2 -> branch2
...
In other words, something where you're not simply applying a pure function to
a bunch of monadic arguments. I can't say I've run into such patterns much
myself, but I've been told they're common in xmonad, and may be elsewhere.
In general, I guess you'd need the monad brackets when you'd need to interact
with other syntax (since it isn't first-class). Record update would probably
be another example. But applications of pure functions to monadic values
doesn't seem like a particularly compelling motivator, in my opinion.
-- Dan
More information about the Haskell-Cafe
mailing list