[Haskell-cafe] Re: monad subexpressions
apfelmus
apfelmus at quantentunnel.de
Sat Aug 4 04:18:33 EDT 2007
Sebastian Sylvan wrote:
> Claus Reinke wrote:
>>> mytransaction = do {
>>> x0 <- readTVar xvar0
>>> x1 <- readTVar xvar1
>>> :
>>> xn <- readTVar xvarn
>>> 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 ..
>> 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.
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` ...
reads
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
Then, mytransaction reads
mytransaction = return foo `apT` xvar0 `apT` xvar1 `apT` ...
Regards,
apfelmus
More information about the Haskell-Cafe
mailing list