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