`<-`

. This
operator is special for do-notation, and is used to pull a value out of its
wrapper (in this case, `Maybe`). Once we've extracted the value, we can
manipulate it with normal functions, like `yearToAge`. When we complete our
do-block, we have to return a value wrapped up in that container again. That's
what the `return` function does.
do-notation isn't available for all `Functor`s; it's a special feature reserved
only for `Monad`s. `Monad`s are an extension of `Functor`s that provide a
little extra power. We're not really taking advantage of any of that extra
power here; we'll need to make our program more complicated to demonstrate
it.
## Dealing with two variables
It's kind of limiting that we have a hard-coded year to compare against. Let's
fix that by allowing the user to specify the "future year." We'll start off
with a simple implementation using pattern matching and then move back to do
notation.
```active haskell
import Safe (readMay)
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
let maybeAge =
case readMay birthYearString of
Nothing -> Nothing
Just birthYear ->
case readMay futureYearString of
Nothing -> Nothing
Just futureYear -> Just (futureYear - birthYear)
displayAge maybeAge
```
OK, it gets the job done... but it's very tedious. Fortunately, do-notation makes this kind of code really simple:
```active haskell
import Safe (readMay)
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
yearDiff futureYear birthYear = futureYear - birthYear
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
let maybeAge = do
birthYear <- readMay birthYearString
futureYear <- readMay futureYearString
return $ yearDiff futureYear birthYear
displayAge maybeAge
```
This is very convenient: we've now slurped our two values in our do-notation.
If either parse returns `Nothing`, then the entire do-block will return
`Nothing`. This demonstrates an important property about `Maybe`: it provides
__short circuiting__.
Without resorting to other helper functions or pattern matching, there's no way
to write this code using just `fmap`. So we've found an example of code that
requires more power than `Functor`s provide, and `Monad`s provide that power.
## Partial application
But maybe there's something else that provides enough power to write our
two-variable code without the full power of `Monad`. To see what this might be,
let's look more carefully at our types.
We're working with two values: `readMay birthYearString` and `readMay
futureYearString`. Both of these values have the type `Maybe Integer`. And we
want to apply the function `yearDiff`, which has the type `Integer -> Integer
-> Integer`.
If we go back to trying to use `fmap`, we'll seemingly run into a bit of a
problem. The type of `fmap`- specialized for `Maybe` and `Integer`- is
`(Integer -> a) -> Maybe Integer -> Maybe a`. In other words, it takes a
function that takes a single argument (an `Integer`) and returns a value of
some type `a`, takes a second argument of a `Maybe Integer`, and gives back a
value of type `Maybe a`. But our function- `yearDiff`- actually takes two
arguments, not one. So `fmap` can't be used at all, right?
Not true actually. This is where one of Haskell's very powerful features comes
into play. Any time we have a function of two arguments, we can also look at is
as a function of one argument which returns a __function__. We can make this
more clear with parentheses:
```haskell
yearDiff :: Integer -> Integer -> Integer
yearDiff :: Integer -> (Integer -> Integer)
```
So how does that help us? We can look at the `fmap` function as:
```haskell
fmap :: (Integer -> (Integer -> Integer))
-> Maybe Integer -> Maybe (Integer -> Integer)
```
Then when we apply `fmap` to `yearDiff`, we end up with:
```haskell
fmap yearDiff :: Maybe Integer -> Maybe (Integer -> Integer)
```
That's pretty cool. We can apply *this* to our `readMay futureYearString` and
end up with:
```haskell
fmap yearDiff (readMay futureYearString) :: Maybe (Integer -> Integer)
```
That's certainly very interesting, but it doesn't help us. We need to somehow
apply this value of type `Maybe (Integer -> Integer)` to our `readMay
birthYearString` of type `Maybe Integer`. We can do this with do-notation:
```active haskell
import Safe (readMay)
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
yearDiff futureYear birthYear = futureYear - birthYear
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
let maybeAge = do
yearToAge <- fmap yearDiff (readMay futureYearString)
birthYear <- readMay birthYearString
return $ yearToAge birthYear
displayAge maybeAge
```
We can even use `fmap` twice and avoid the second slurp:
```active haskell
import Safe (readMay)
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
yearDiff futureYear birthYear = futureYear - birthYear
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
let maybeAge = do
yearToAge <- fmap yearDiff (readMay futureYearString)
fmap yearToAge (readMay birthYearString)
displayAge maybeAge
```
But we don't have a way to apply our `Maybe (Integer -> Integer)` function to
our `Maybe Integer` directly.
## Applicative functors
And now we get to our final concept: applicative functors. The idea is simple:
we want to be able to apply a function which is *inside* a functor to a value
inside a functor. The magic operator for this is `<*>`

. Let's
see how it works in our example:
```active haskell
import Safe (readMay)
import Control.Applicative ((<*>))
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
yearDiff futureYear birthYear = futureYear - birthYear
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
let maybeAge =
fmap yearDiff (readMay futureYearString)
<*> readMay birthYearString
displayAge maybeAge
```
In fact, the combination of `fmap` and `<*>` is so common that we have a
special operator, `<$>`, which is a synonym for `fmap`. That means we can make
our code just a little prettier:
```active haskell
import Safe (readMay)
import Control.Applicative ((<$>), (<*>))
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
yearDiff futureYear birthYear = futureYear - birthYear
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
-- show
let maybeAge = yearDiff
<$> readMay futureYearString
<*> readMay birthYearString
-- /show
displayAge maybeAge
```
Notice the distinction between `<$>` and `<*>`. The former uses a function
which is *not* wrapped in a functor, while the latter applies a function which
is wrapped up.
## So we don't need Monads?
So if we can do such great stuff with functors and applicative functors, why do
we need monads at all? The terse answer is __context sensitivity__: with a
monad, you can make decisions on which processing path to follow based on
previous results. With applicative functors, you have to always apply the same
functions.
Let's give a contrived example: if the future year is less than the birth year,
we'll assume that the user just got confused and entered the values in reverse,
so we'll automatically fix it by reversing the arguments to `yearDiff`. With
do-notation and an if statement, it's easy:
```active haskell
import Safe (readMay)
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
yearDiff futureYear birthYear = futureYear - birthYear
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
let maybeAge = do
futureYear <- readMay futureYearString
birthYear <- readMay birthYearString
return $
if futureYear < birthYear
then yearDiff birthYear futureYear
else yearDiff futureYear birthYear
displayAge maybeAge
```
## Exercises
1. Implement `fmap` using `<*>` and `return`.
```active haskell
import Control.Applicative ((<*>), Applicative)
import Prelude (return, Monad)
import qualified Prelude
fmap :: (Applicative m, Monad m) => (a -> b) -> (m a -> m b)
-- show
fmap ... ... = FIXME
-- /show
main =
case fmap (Prelude.+ 1) (Prelude.Just 2) of
Prelude.Just 3 -> Prelude.putStrLn "Good job!"
_ -> Prelude.putStrLn "Try again"
```
@@@SHOW SOLUTION
```active haskell
import Control.Applicative ((<*>))
-- show
myFmap function wrappedValue = return function <*> wrappedValue
main = print $ myFmap (+ 1) $ Just 5
-- /show
```
@@@
2. How is `return` implemented for the `Maybe` monad? Try replacing `return`
with its implementation in the code above.
```haskell active
-- show
returnMaybe = FIXME
-- /show
main
| returnMaybe "Hello" == Just "Hello" = putStrLn "Correct!"
| otherwise = putStrLn "Incorrect, please try again"
```
@@@SHOW SOLUTION
`return` is simply the `Just` constructor. This gets defined as:
```haskell
instance Monad Maybe where
return = Just
```
@@@
3. `yearDiff` is really just subtraction. Try to replace the calls to
`yearDiff` with explicit usage of the `-` operator.
```haskell active
import Safe (readMay)
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
let maybeAge = do
futureYear <- readMay futureYearString
birthYear <- readMay birthYearString
return $
-- show
if futureYear < birthYear
then yearDiff birthYear futureYear
else yearDiff futureYear birthYear
-- /show
displayAge maybeAge
```
@@@SHOW SOLUTION
```haskell
import Safe (readMay)
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
let maybeAge = do
futureYear <- readMay futureYearString
birthYear <- readMay birthYearString
return $
-- show
if futureYear < birthYear
then birthYear - futureYear
else futureYear - birthYear
-- /show
displayAge maybeAge
```
@@@
4. It's possible to write an applicative functor version of the
auto-reverse-arguments code by modifying the `yearDiff` function. Try to do
so.
```active haskell
import Safe (readMay)
import Control.Applicative ((<$>), (<*>))
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
-- show
yearDiff futureYear birthYear = FIXME
-- /show
main
| yearDiff 5 6 == 1 = putStrLn "Correct!"
| otherwise = putStrLn "Please try again"
```
@@@ SHOW SOLUTION
```active haskell
import Safe (readMay)
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
-- show
yearDiff futureYear birthYear
| futureYear > birthYear = futureYear - birthYear
| otherwise = birthYear - futureYear
-- /show
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
let maybeAge = do
futureYear <- readMay futureYearString
birthYear <- readMay birthYearString
return $
if futureYear < birthYear
then yearDiff birthYear futureYear
else yearDiff futureYear birthYear
displayAge maybeAge
```
@@@
* Now try to do it without modifying `yearDiff` directly, but by using a
helper function which is applied to `yearDiff`.
```active haskell
import Safe (readMay)
import Control.Applicative ((<$>), (<*>))
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
yearDiff futureYear birthYear = futureYear - birthYear
-- show
yourHelperFunction f ...
-- /show
main
| yourHelperFunction yearDiff 5 6 == 1 = putStrLn "Correct!"
| otherwise = putStrLn "Please try again"
```
@@@ SHOW SOLUTION
```active haskell
import Safe (readMay)
displayAge maybeAge =
case maybeAge of
Nothing -> putStrLn "You provided invalid input"
Just age -> putStrLn $ "In that year, you will be: " ++ show age
yearDiff futureYear birthYear = futureYear - birthYear
main = do
putStrLn "Please enter your birth year"
birthYearString <- getLine
putStrLn "Please enter some year in the future"
futureYearString <- getLine
let maybeAge = do
futureYear <- readMay futureYearString
birthYear <- readMay birthYearString
return $
if futureYear < birthYear
then yourHelperFunction yearDiff birthYear futureYear
else yourHelperFunction yearDiff futureYear birthYear
displayAge maybeAge
-- show
yourHelperFunction f x y
| x > y = f x y
| otherwise = f y x
-- /show
```
@@@