https://wiki.haskell.org/api.php?action=feedcontributions&user=Cheater&feedformat=atomHaskellWiki - User contributions [en]2024-03-28T20:05:20ZUser contributionsMediaWiki 1.35.5https://wiki.haskell.org/index.php?title=Applicative_functor&diff=58607Applicative functor2014-07-25T11:45:13Z<p>Cheater: typo.</p>
<hr />
<div>[[Category:Glossary]]<br />
[[Category:Applicative Functor|*]]<br />
An applicative functor has more structure than a [[functor]] but less than a [[monad]]. See the Haddock docs for [http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Applicative.html Control.Applicative].<br />
<br />
== Example ==<br />
<br />
It has turned out that many applications do not require monad functionality but only those of applicative functors.<br />
Monads allow you to run actions depending on the outcomes of earlier actions.<br />
<haskell><br />
do text <- getLine<br />
if null text<br />
then putStrLn "You refuse to enter something?"<br />
else putStrLn ("You entered " ++ text)<br />
</haskell><br />
This is obviously necessary in some cases, but in other cases it is disadvantageous.<br />
<br />
Consider an extended IO monad which handles automated closing of allocated resources.<br />
This is possible with a monad.<br />
<haskell><br />
openDialog, openWindow :: String -> CleanIO ()<br />
<br />
liftToCleanup :: IO a -> CleanIO a<br />
<br />
runAndCleanup :: CleanIO a -> IO a<br />
<br />
runAndCleanup $<br />
do text <- liftToCleanup getLine<br />
if null text<br />
then openDialog "You refuse to enter something?"<br />
else openWindow ("You entered " ++ text)<br />
</haskell><br />
The (fictive) functions <hask>openDialog</hask> and <hask>openWindow</hask><br />
could not only open dialogs and windows but could also register some cleanup routine in the <hask>CleanIO</hask>.<br />
<hask> runAndCleanup </hask> would first run the opening actions and afterwards the required cleanup actions.<br />
I.e. if the dialog was opened, the dialog must be closed, but not the window.<br />
That is, the cleanup procedure depends on the outcomes of earlier actions.<br />
<br />
Now consider the slightly different task, where functions shall register ''initialization'' routines<br />
that shall be run before the actual action takes place.<br />
(See the original discussion started by Michael T. Richter in Haskell-Cafe:<br />
[http://www.haskell.org/pipermail/haskell-cafe/2007-June/027517.html Practical Haskell Question])<br />
This is impossible in the monadic framework.<br />
Consider the example above where the choice between <hask>openDialog</hask> and <hask>openWindow</hask><br />
depends on the outcome of <hask> getLine </hask>.<br />
You cannot run initialization code for either <hask>openDialog</hask> or <hask>openWindow</hask>,<br />
because you do not know which one will be called before executing <hask> getLine </hask>.<br />
If you eliminate this dependency, you end up in an applicative functor<br />
and there you can do the initialization trick.<br />
You could write<br />
<haskell><br />
initializeAndRun $<br />
liftA2<br />
(liftToInit getLine)<br />
(writeToWindow "You requested to open a window")<br />
</haskell><br />
where <hask> writeToWindow </hask> registers an initialization routine which opens the window.<br />
<br />
== Usage ==<br />
<br />
If you have the variables<br />
<haskell><br />
f :: a -> b -> c<br />
a :: f a<br />
b :: f b<br />
</haskell><br />
you can combine them in the following ways with the same result of type <hask>f c</hask>:<br />
<haskell><br />
pure f <*> a <*> b<br />
<br />
liftA2 f a b<br />
</haskell><br />
<br />
But how to cope with <hask>let</hask> and sharing in the presence of effects?<br />
Consider the non-functorial expression:<br />
<haskell><br />
x :: x<br />
g :: x -> y<br />
h :: y -> y -> z<br />
<br />
let y = g x<br />
in h y y<br />
</haskell><br />
Very simple.<br />
Now we like to generalize this to<br />
<haskell><br />
fx :: f x<br />
fg :: f (x -> y)<br />
fh :: f (y -> y -> z)<br />
</haskell><br />
However, we note that<br />
<haskell><br />
let fy = fg <*> fx<br />
in fh <*> fy <*> fy<br />
</haskell><br />
runs the effect of <hask>fy</hask> twice.<br />
E.g. if <hask>fy</hask> writes something to the terminal then <hask>fh <*> fy <*> fy</hask> writes twice.<br />
This could be intended, but how can we achieve,<br />
that the effect is run only once and the result is used twice?<br />
<br />
Actually, using the <hask>liftA</hask> commands we can pull results of applicative functors<br />
into a scope where we can talk exclusively about functor results and not about effects.<br />
Note that functor results can also be functions.<br />
This scope is simply a function, which contains the code that we used in the non-functorial setting.<br />
<haskell><br />
liftA3<br />
(\x g h -> let y = g x in h y y)<br />
fx fg fh<br />
</haskell><br />
The order of effects is entirely determined by the order of arguments to <hask>liftA3</hask>.<br />
<br />
== Some advantages of applicative functors ==<br />
<br />
* Code that uses only on the <hask>Applicative</hask> interface are more general than ones uses the <hask>Monad</hask> interface, because there are more applicative functors than monads. The <hask>ZipList</hask> is an applicative functor on lists, where <hask>liftA2</hask> is implemented by <hask>zipWith</hask>. It is a typical example of an applicative functor that is not a monad.<br />
* Programming with <hask>Applicative</hask> has a more applicative/functional feel. Especially for newbies, it may encourage functional style even when programming with effects. Monad programming with [[Do notation considered harmful|do notation]] encourages a more sequential & imperative style.<br />
<br />
== Applicative transformers ==<br />
<br />
From the [[Monad Transformer Library]] we are used to have two flavours of every monad:<br />
A base monad like <hask>State</hask> and a transformer variant <hask>StateT</hask>.<br />
In the [http://hackage.haskell.org/package/transformers/ transformers] package we even have only monad transformers<br />
except the <hask>Identity</hask> monad.<br />
So where are applicative transformers?<br />
The answer is, that we do not need special transformers for applicative functors<br />
since they can be combined in a generic way.<br />
<haskell><br />
h :: f (g (a -> b))<br />
a :: f (g a)<br />
<br />
liftA2 (<*>) h a :: f (g b)<br />
</haskell><br />
That is <hask>liftA2 (<*>)</hask> is essentially the definition for <hask><*></hask><br />
for the composition of the functors <hask>f</hask> and <hask>g</hask>.<br />
This is implemented in the {{HackagePackage|id=TypeCompose}} library as type constructor <hask>O</hask> and in {{HackagePackage|id=transformers}} library in module <hask>Data.Functor.Compose</hask>.<br />
The first one needs a lot of type extensions, whereas the second one is entirely Haskell 98.<br />
<br />
It can be useful to use the applicative composition even when you have a monad transformer at hand.<br />
In the example above <hask>f</hask> might be <hask>Writer (Sum Int)</hask><br />
that is used for counting the number of involved applicative actions.<br />
Since in an applicative functor the number of run actions is independent from interim results,<br />
the writer can count the actions at compile time.<br />
<br />
== How to switch from monads ==<br />
<br />
* Start using <hask>liftM</hask>, <hask>liftM2</hask>, etc or <hask>ap</hask> where you can, in place of <hask>do</hask>/<hask>(>>=)</hask>. You will often encounter code like<br />
<haskell><br />
do x <- fx<br />
y <- fy<br />
return (g x y)<br />
</haskell><br />
:It can be rewritten to <hask>liftM2 g fx fy</hask>. In general, whenever the choice or construction of monadic actions does not depend on the outcomes of previous monadic actions, then it should be possible to rewrite everything with <hask>liftM</hask>.<br />
* When you notice you're ''only'' using those monad methods, then import <hask>Control.Applicative</hask> and replace<hask>return</hask> with <hask>pure</hask>, <hask>liftM</hask> with <hask>(<$>)</hask> (or <hask>fmap</hask> or <hask>liftA</hask>), <hask>liftM2</hask> with <hask>liftA2</hask>, etc, and <hask>ap</hask> with <hask>(<*>)</hask>. If your function signature was <hask>Monad m => ...</hask>, change to <hask>Applicative m => ...</hask> (and maybe rename <hask>m</hask> to <hask>f</hask> or whatever).<br />
<br />
<br />
== Alternative terms ==<br />
<br />
Applicative functors were introduced by several people under different names:<br />
* Ross Paterson called them [http://www.haskell.org/arrows/arrows/Control.Sequence.html Sequence]<br />
* Conor McBride called them [http://www.haskell.org/pipermail/haskell/2004-July/014315.html Idiom]<br />
* The same kind of structure is used in the [http://www.cs.uu.nl/wiki/Center/UtrechtParserCombinators UU Parsing-Combinators].<br />
<br />
<br />
== See also ==<br />
<br />
* [http://www.soi.city.ac.uk/~ross/papers/Applicative.html Applicative Programming with Effects]<br />
* The blog article [http://www.serpentine.com/blog/2008/02/06/the-basics-of-applicative-functors-put-to-practical-work/ The basics of applicative functors, put to practical work]</div>Cheater