Lecture 8 (2018-02-08)
Applicative
A lot of this material is borrowed/based on two resources written by
[Brent Yorgey](https://byorgey.wordpress.com/): his [Haskell course
from Spring
2013](http://www.seas.upenn.edu/~cis194/spring13/lectures.html) and
his [Typeclassopedia](https://wiki.haskell.org/Typeclassopedia). I
encourage you to go read these excellent resources!
## A problem in Functortown

We looked at how we might define arithmetic evaluation with the possibility of errors:
```Haskell
evalA' :: Store -> AExp -> Either Error Int`
evalA' st (Neg e) = myNegate $ evalA' st e
where myNegate (Left err) = Left err
myNegate (Right n) = Right $ negate n
```
We observed that `myNegate = fmap negate`, so we can instead write:
```Haskell
evalA' :: Store -> AExp -> Either Error Int`
evalA' st (Neg e) = negate <$> evalA' st e
```
(Recall that `(<$>)` is the same thing as `fmap`, but infix---it's
deliberately designed to look like application, `($)`.)
We then tried to work out the case for `Plus`:
```Haskell
evalA' :: Store -> AExp -> Either Error Int`
evalA' st (Neg e) = negate <$> evalA' st e
evalA' st (Plus e1 e2) = fmap2 (+) (evalA' st e1) (evalA' st e2)
```
What would this function `fmap2` be? For our concrete example, we succeeded in defining a function:
```Haskell
fmap2 :: (a -> b -> c) -> Either e a -> Either e b -> Either e c
fmap2 _ (Left err1) _ = Left err1
fmap2 _ _ (Left err2) = Left err2
fmap2 f (Right v1) (Right v2) = Right $ f v1 v2
```
But can we go more general? We tried writing a different function
`fmap2`, but that didn't go well either.
> fmap2 :: Functor f => (a -> b -> c) -> f a -> f b -> f c
> fmap2 f a b = undefined
> where fa = fmap f a -- where do we go from here?
`Functor` is a fine type class, but it only lets us operate
opaquely. Once a function is trapped in `Functor`, we can't get it
out!
A different type class, `Applicative`, solves this problem.
```
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b -- pronounced 'ap'
```
NB that `Applicative` is a subclass of `Functor`.
> fmap2' :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
> fmap2' f a b = (fmap f a) <*> b
```
pure :: a -> f a
fmap :: (a -> b) -> f a -> f b
fmap2 :: (a -> b -> c) -> f a -> f b -> f c
```
Note that to be an `Applicative`, you must be a `Functor`. Can we
write `fmap` using the `<*>`?
> fmap' :: Applicative f => (a -> b) -> f a -> f b
> fmap' f a = pure f <*> a
In fact, using `fmap` with `Applicative`s is so common that we have
the definition `<$> = fmap`.
> fmap2Best :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
> fmap2Best f a b = f <$> a <*> b -- note left associativity and tight binding of <$>
Finally, note that `fmap2` is called `liftA2` in Haskell.
### Obey the laws

Like `Functor`, the `Applicative` type class is governed by laws.
*Identity:* `pure id <*> v = v`
*Composition:* `pure (.) <*> u <*> v <*> w = u <*> (v <*> w)`
*Homomorphism:* `pure f <*> pure x = pure (f x)`
*Interchange:* `u <*> pure y = pure ($ y) <*> u`
Note that `identity` is a generalization of `id <$> v = v` from
`Functor`, since `f <$> x = pure f <*> x`.
## Another way in

> type Name = String
>
> data Employee = Employee { name :: Name
> , phone :: String }
> deriving Show
>
> maybeEmployee :: (Name -> String -> Employee) ->
> (Maybe Name -> Maybe String -> Maybe Employee)
> maybeEmployee f (Just n) (Just p) = Just $ f n p
> maybeEmployee _ _ _ = Nothing
>
> listEmployee :: (Name -> String -> Employee) ->
> ([Name] -> [String] -> [Employee])
> listEmployee f n p = zipWith f n p
>
> listEmployee' :: (Name -> String -> Employee) ->
> ([Name] -> [String] -> [Employee])
> listEmployee' f n p = map (\(name,phone) -> f name phone) allPairs
> where allPairs = Prelude.concat (map (\name -> map (\phone -> (name,phone)) p) n)
> -- map (uncurry f) $ concatMap (\name -> map (\phone -> (name,phone)) p) n
>
> funEmployee :: (Name -> String -> Employee) ->
> (e -> Name) -> (e -> String) -> (e -> Employee)
> funEmployee f mkName mkPhone = \e -> f (mkName e) (mkPhone e)
Another example of `Applicative`, highlighting how it bears some similarity to normal "application":
> name :: Maybe String -> Maybe String -> Maybe String
> name given family = (++) <$> given <*> family
>
> drdave = name (Just "Dave") (Just "Kauchak")
>
> prince = name (Just "Prince") Nothing
We wrote up a straightforward instance for `Maybe` and a more
interesting instance for `Either e`:
```Haskell
instance Applicative (Either e) where
pure x = Right x -- because Left x would be ill typed!
(Right f) <*> (Right v) = Right $ f v
err@(Left e) <*> _ = err
_ <*> err@(Left e) = err
```
Then we (very quickly, at the end) went over the `Applicative`
definitions for lists. There were two possibilities: Cartesian
product...
```Haskell
instance Applicative [] where
pure x = [x]
[] <*> _ = []
_ <*> [] = []
(f:fs) <*> xs = map f xs ++ fs <*> xs
```
...and zipping:
```
newtype ZipList a = ZipList { getZipList :: [a] }
deriving (Eq, Show, Functor)
instance Applicative ZipList where
pure = ZipList . repeat
ZipList fs <*> ZipList xs = ZipList (zipWith ($) fs xs)
```
(We wrote the infinite list differently, writing `pure x = x:pure
x`. That's not *quite* right, because we want an infinite `ZipList`,
not an infinite list. The above definition is the technically correct one.)
Haskell prefers the former definition based on Cartesian product,
because it doesn't involve any infinite lists. Infinite lists are fine
in Haskell, because Haskell is lazy... but even so, it's very easy to
accidentally use an infinite list to create an infinite loop. (For
example, a map is fine, but a fold? Not always...)