Files
notes/docs/lectures/compilers/06_applicative_functors.md
T

2.1 KiB

Applicative Functors

Types: Bool, Int, Char, [Char] = String

Type Constructors: Maybe, []

(type) classes: Eq, Show, Functor

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

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

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

fmap3 :: g x y z = (pure g) <*> x <*> y <*> z
Example Maybe
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
instance Applicative [] where
-- pure :: a -> [a]
pure x = [x]
-- (<*>) :: [a -> b] -> [a] -> [b]
gs <*> xs = [g x | g <- gs, x <- xs]
Example Parser
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