apfelmus apfelmus at quantentunnel.de
Sat Aug 4 04:18:33 EDT 2007

```Sebastian Sylvan wrote:
> Claus Reinke wrote:
>>> mytransaction = do {
>>>  :
>>>  return \$ foo x0 x1 .. xn
>>> }
>>
>> ah, a concrete example. but isn't that the typical use case for ap?
>>
>> mytransaction = foo `liftM` r xvar0 `ap` r xvar1 ..
>
> 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.

I think it's entirely natural :)

Applicative functors (Control.Applicative) are the pattern behind this.
The notation may seem a little weird first, but in the end, `ap` is a
kind of explicit function application and similar to \$. With the
notation from Control.Applicative, the line

return foo `ap` r xvar0 `ap` r xvar1 `ap` ...

pure foo <*> r xvar0 <*> r xvar1 <*> ...

or

foo <\$> r xvar0 <*> r xvar1 <*> ...

In other words, instead of using juxtaposition to apply an argument to a
function, we use <*>. The type of `ap` is

ap :: m (a -> b) -> m a -> m b

so that it can be thought of as a generalized function application where
the function is "under" a monad.

The difference to \$ is that <*> is left associative and allows for
currying. I.e. <*> is like \$ used in the following way

((foo \$ x0) \$ x1) \$ x2

Note that you can even incorporate the TVar by defining your own
generalized function application:

apT :: STM (a -> b) -> TVar a -> STM b
apT f x = f `ap` readTVar x