Basically, monads are also applicative functors [1]. So, whenever you find yourself using liftM
, liftM2
, etc., you could chain the computation together using <*>
. In some sense, you can think of applicative functors as analogous to functions. A pure function f
can be lifted by doing f <$> x <*> y <*> z
.
Compared to monads, applicative functors cannot run its arguments selectively. The side effects of all the arguments will take place.
import Control.Applicative
ifte condition trueClause falseClause = do
c <- condition
if c then trueClause else falseClause
x = ifte (return True) (putStrLn "True") (putStrLn "False")
ifte' condition trueClause falseClause =
if condition then trueClause else falseClause
y = ifte' <$> (pure True) <*> (putStrLn "True") <*> (putStrLn "False")
x
only outputs True
, whereas y
outputs True
and False
sequentially.
[1] The Typeclassopedia. Highly recommended.
[2] http://www.soi.city.ac.uk/~ross/papers/Applicative.html. Although this is an academic paper, it's not hard to follow.
[3] http://learnyouahaskell.com/functors-applicative-functors-and-monoids#applicative-functors. Explains the deal very well.
[4] http://book.realworldhaskell.org/read/using-parsec.html#id652399. Shows how the monadic Parsec
library can also be used in an applicative way.