Topics in Advanced Computing Lesson 10: Applicatives and Monads

  1. Applicative Functors
    1. Maybe
    2. <$>
    3. Lists
    4. IO
    5. Laws
  2. Monoids
    1. Foldables

Applicative Functors

infixl 4 <*> 
class Functor f => Applicative f where 
  pure :: a -> f a -- put something into a box
  (<*>) ::f (a -> b) -> f a -> f b -- take a function in a box, apply to a box.

Reminder: currying / partial functions.

Maybe

instance Applicative Maybe where  
  pure = Just  
  Nothing <*> _ = Nothing  
  (Just f) <*> something = fmap f something  

Examples:

<$>

Basically: infix version of fmap. So f <$> x <*> y <*> z is like f x y z, on applicative functors.

Ex:(+) <$> Just 1 <*> Just 2

How do we understand this? fmap (+) Just 1 would become Just (+1), and then Just (+1) <*> Just 2 is Just 3.

Lists

instance Applicative [] where  
  pure x = [x]  
  fs <*> xs = [f x | f <- fs, x <- xs]  

All products of numbers from [-2..2] with [1..3]?

IO

instance Applicative IO where  
  pure = return   
  a <*> b = do  
    f <- a  
    x <- b  
    return (f x)  

Laws

Monoids

class Monoid m where  
  mempty :: m  
  mappend :: m -> m -> m  
  mconcat :: [m] -> m  
  mconcat = foldr mappend mempty  

A monoid is a set of objects $M$ that comes with two distinguished pieces of data: (1) a binary operation $*$ (meaning that $*$ is a function which takes two parameters from $M$ and returns a value in $M$) that is associative (ie, if $a, b, c \in M$, then $a * (b * c) = (a * b) * c$), and (2) an identity element $e \in M$; that is, for all $a \in M$, $e * a = a * e = a$.

This is a generalization of a few patterns we see in mathematical objects all the time:

How does this make sense in Haskell?

The other function, mconcat, is defined so that it takes a list of objects in that monoid, and repeatedly applies the operator over all of them. (ie, it folds over the list).

Foldables

class Foldable t where
  Data.Foldable.fold :: Monoid m => t m -> m
  foldMap :: Monoid m => (a -> m) -> t a -> m
  Data.Foldable.foldMap' :: Monoid m => (a -> m) -> t a -> m
  foldr :: (a -> b -> b) -> b -> t a -> b
  Data.Foldable.foldr' :: (a -> b -> b) -> b -> t a -> b
  foldl :: (b -> a -> b) -> b -> t a -> b
  Data.Foldable.foldl' :: (b -> a -> b) -> b -> t a -> b
  foldr1 :: (a -> a -> a) -> t a -> a
  foldl1 :: (a -> a -> a) -> t a -> a
  Data.Foldable.toList :: t a -> [a]
  null :: t a -> Bool
  length :: t a -> Int
  elem :: Eq a => a -> t a -> Bool
  maximum :: Ord a => t a -> a
  minimum :: Ord a => t a -> a
  sum :: Num a => t a -> a
  product :: Num a => t a -> a
  {-# MINIMAL foldMap | foldr #-}

We need to implement foldMap or foldr. Given our Tree data type, how would we implement foldMap?