# Applicative Functors Types: `Bool`, `Int`, `Char`, `[Char] = String` Type Constructors: `Maybe`, `[]` (type) classes: `Eq`, `Show`, `Functor` ```haskell newtype Parser a = P ( String -> [a, String]) parse :: Parser a -> String -> [(a, String)] parse (P p) s = p s -- s's can be cancelled from both sides instance Functor Parser where -- fmap :: (a -> b) -> Parser a -> Parser b fmap g pa = P (\s -> [(g x, s1) | (x,s1) <- parse pa s]) ``` Applicative - motivation ```haskell Functor f fmap0 :: a -> f a fmap1 :: (a -> b) -> f a -> f b -- cannot do this with functors ie cannot deal with multiple parameters fmap2 :: (a -> b -> c) -> f a -> f b -> f c fmap3 :: (a -> ... n) -> f a -> ... f n ``` `Functor f` can do `fmap1`; however, it cannot do `fmap0` or `fmap2` etc. **Remember**: `a -> b -> c == a -> (b -> c)` For `fmap2` we can use `fmap2 :: (a -> (b -> c)) -> f a -> f (a -> b)` would need: `f(b -> c) -> f b -> f c` ```haskell class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b -- <*> infix operator -- NOTE its f (a -> b) and not (a -> b) in fmap1 -- fmap1 not part of the applicative class ``` Writing `fmap3` in an applicative functor ```haskell fmap3 :: g x y z = (pure g) <*> x <*> y <*> z ``` ##### Example Maybe ```haskell instance Applicative Maybe where -- pure :: a -> Maybe a pure x = Just x -- (<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b Just g <*> (Just x) = Just (g x) _ <*> _ = Nothing ``` ##### Example Lists ```haskell instance Applicative [] where -- pure :: a -> [a] pure x = [x] -- (<*>) :: [a -> b] -> [a] -> [b] gs <*> xs = [g x | g <- gs, x <- xs] ``` ##### Example Parser ```haskell instance Applicative Parser where -- pure :: a -> Parser a -- newtype Parser a = P ( String -> [(a, String)] ) pure x = P (\s -> [(x,s)]) -- <*> :: Parser (a -> b) -> Parser a -> Parser b pf <*> pa = P (\s -> [ (f x, s2) | (f, s1) <- parse pf s, (x, s2) <- parse pa s1)]) ``` All parse does is apply a parser `parse :: Parser a -> String -> [(a, String)]` Where `P` is the constructor `parse ( P p ) = p`