# Lecture 18 — 2015-11-09

## Functor and Applicative

A few words on abstraction and why we bother.

A lot of this material is borrowed/based on two resources written by Brent Yorgey: his Haskell course from Spring 2013 and his Typeclassopedia. I encourage you to go read these excellent resources!

``````{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
module Lec18 where

import Prelude hiding (map)
import Lec17

import Control.Applicative
import Data.Char

import System.Environment
import System.Exit

import qualified Data.Map as Map
import Data.Map (Map, (!))

map :: (a -> b) -> [a] -> [b]
map f = foldr ((:) . f) []

data BinTree a = BTEmpty | BTNode (BinTree a) a (BinTree a) deriving Show

treeMap f BTEmpty = BTEmpty
treeMap f (BTNode l v r) = BTNode (treeMap f l) (f v) (treeMap f r)

maybeMap f Nothing = Nothing
maybeMap f (Just x) = Just (f x)``````
``````class Functor f where
fmap :: (a -> b) -> f a -> f b``````

Here `f` is a ‘container’, or, more broadly, a computational context.

``````instance Functor BinTree where
fmap = treeMap

add1 :: (Functor f, Num a) => f a -> f a

What other instances can we find for Functor?

Well, the `Listlike` type class we saw might do…

``````instance Listlike f => Functor f where
fmap = each``````

…but this leads to undecidability. What if `f` already has its own instance of `Functor`? We can use `newtype` to resolve this issue.

``````newtype AsList f a = AsList { getList :: f a } deriving Show

instance Listlike f => Functor (AsList f) where
fmap f = AsList . each f . getList

l2 = add1 (AsList (foldr cons nil [1..10] :: UnionTree Int))``````

What about other types? Let’s try pairs.

``````instance Functor (,) where
fmap f (a,b) = (f a, f b)``````

…nope! The kinds aren’t even right… `Functor` applies to types of kind `* -> *`, but `(,)` has kind `* -> * -> *`. So we’ll need to apply `(,)` to a type to make it work.

``````instance Functor ((,) e) where
fmap f (a,b) = (a, f b)``````

Okay… why does the left stay fixed? Because here `fmap : (a -> b) -> (e,a) -> (e,b)`.

We could, if we liked define pairs of values of the same type, as in:

``````data Pair a = Pair a a deriving Show

instance Functor Pair where
fmap f (Pair a b) = Pair (f a) (f b)``````

Okay, so much for pairs. What about sum types?

``````instance Functor Either where
fmap f (Left a)  = Left  \$ f a
fmap f (Right a) = Right \$ f a``````

Hmm… nope. The kinds don’t check out. We can do this, though:

``````instance Functor (Either e) where
fmap f (Left e)  = Left e
fmap f (Right a) = Right \$ f a``````

Again, we choose the left side out of convenience. We could define something similar to `Pair`, if we wanted:

``````data Choice a = ColumnA a | ColumnB a

instance Functor Choice where
fmap f (ColumnA a) = ColumnA \$ f a
fmap f (ColumnB a) = ColumnB \$ f a``````

At first, I said that a type constructor `f` that is a `Functor` could be thought of as a container: `fmap :: (a -> b) -> f a -> f b` runs a function on the contents of a container. Thinking of functors as containers isn’t a bad intuition, but it’s slightly inadequate.

More broadly, a functor is a computational context, not just a container. That is, functors may not always be traversible the way that code is.

``````instance Functor ((->) e) where
fmap f g = \e -> f (g e)``````

That is:

``````instance Functor ((->) e) where
fmap = (.)``````

The `Applicative` type class

``````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)``````

Can we use `Functor` to do this? The type above looks like `fmap`, but with two arguments instead of one. Can we write a different function `fmap2`?

``````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'``````
``````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``````

Finally, let’s note that this function is defined as `liftA2` in the module `Control.Applicative`.

Let’s write some `Applicative` instances and work with it more.

``````instance Applicative Pair where
pure a = Pair a a
(Pair f1 f2) <*> (Pair a1 a2) = Pair (f1 a1) (f2 a2)

instance Applicative Choice where
pure a = ColumnA a

ColumnA f <*> a = fmap f a
ColumnB f <*> a = fmap f a``````

How else could we have done it? Well, it turns out there are laws that should hold for `Functor` and `Applicative`. In particular:

`fmap id == id` `fmap (f . g) == fmap f . fmap g` `fmap f x === pure f <*> x`
``````instance Applicative BinTree where
pure a = BTNode BTEmpty a BTEmpty

BTEmpty <*> _ = BTEmpty
BTNode _ _ _ <*> BTEmpty = BTEmpty
BTNode lf f rf <*> BTNode la a ra = BTNode (lf <*> la) (f a) (rf <*> ra)``````

Does that law hold for the above? No, not considering what we defined as `Functor BinTree` above! We would need something like:

``````instance Applicative BinTree where
pure a = BTNode BTEmpty a BTEmpty

BTEmpty <*> _ = BTEmpty
BTNode _ f _ <*> t = treeMap f t``````

Let’s look at the `Applicative` instance for `Maybe`.

``````instance Applicative Maybe where
pure              = Just
Nothing <*> _     = Nothing
_ <*> Nothing     = Nothing
Just f <*> Just x = Just (f x)``````
``````m_name1, m_name2 :: Maybe Name
m_name1 = Nothing
m_name2 = Just "Brent"

m_phone1, m_phone2 :: Maybe String
m_phone1 = Nothing
m_phone2 = Just "555-1234"

ex01 = Employee <\$> m_name1 <*> m_phone1
ex02 = Employee <\$> m_name1 <*> m_phone2
ex03 = Employee <\$> m_name2 <*> m_phone1
ex04 = Employee <\$> m_name2 <*> m_phone2``````
``````(.+) = liftA2 (+)
(.*) = liftA2 (*)``````
``n = ([10,5] .* [4,8]) .+ [3,4] .+ [4,3]``
``````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)``````

Now we can see a couple of different ways to go back and redefine `Applicative BinTree`. Should it expand into “tree product”, or should it try to match up trees (in which case we need something like `repeat` for trees)?