tags:

views:

507

answers:

2

In a recent answer to a style question, I wrote

main = untilM (isCorrect 42) (read `liftM` getLine)

and

isCorrect num guess =
  case compare num guess of
    EQ -> putStrLn "You Win!" >> return True
    ...

Martijn helpfully suggested alternatives:

main = untilM (isCorrect 42) (read <$> getLine)

EQ -> True <$ putStrLn "You Win!"

Which common patterns in Haskell code can be made clearer using abstractions from Control.Applicative? What are helpful rules of thumb to keep in mind for using Control.Applicative effectively?

+11  A: 

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.

Wei Hu
That's the only place I've seen where the difference between `Monad` and `Applicative` is explained (in terms of what you can express with each one). Great job!Can we call `ifte` with the applicative functions: `z = ifte <$> ...` ?
Daniel Velkov
`ifte` is already a monadic function, so there's not much point lifting it one more time.
Wei Hu
You can write "ifte' <$> (pure True)" as "ifte' True"—"pure" is rarely necessary in combination with "<$>" and "<*>" (if at all).
Martijn
y = ifte' True <*> putStrLn "True" <*> putStrLn "False"
Edward Kmett
+2  A: 

See The basics of applicative functors, put to practical work by Bryan O'Sullivan.

Greg Bacon