[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