Applicative functors, Part I
Posted on 2015-08-23 19:40:32 +0900 in Functional Programming
Lecture Contents
The induction from Functor to Applicative is quite beautiful.
Recalled that there exists fmap :: (a -> b) -> (f a -> f b) in Functor, it would be great if this mapping
function is still valid if the input consists of more than one variable, namely (a -> b -> c) -> (f a -> f b -> f c)
We have
h :: a -> b -> c
fa :: f a
fb :: f b
fc :: f cUse fmap to lift functions,
h :: a -> (b -> c)
fmap h :: f a -> f (b -> c)
fmap h fa :: f (b -> c)But there is no way to make
f (b -> c) -> fb -> fcApplicative has the (<*>) to implement it, namely
(<*>) :: f (a -> b) -> f a -> f bThe final induction is
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
liftA2 = h <$> fa <*> fbHome Work
Exercise 1
-- Ex. 1 - implement a Functor instance for Parser
--
-- You may find it useful to implement:
-- first :: (a -> b) -> (a,c) -> (b,c)
first :: (a -> b) -> (a, c) -> (b, c)
first f (x, y) = (f x, y)
instance Functor Parser where
fmap f parser = Parser $ \s -> first f <$> runParser parser sExercise 2
-- Ex. 2 - implement an Applicative instance for Parser
--
instance Applicative Parser where
pure a = Parser (\s -> Just (a, s))
p1 <*> p2 = Parser parse
where parse s = do
r1 <- runParser p1 s
r2 <- runParser p2 (snd r1)
return (fst r1 $ fst r2, snd r2)Exercise 3
-- Ex. 3a - Create a parser:
--
-- abParser :: Parser (Char, Char)
--
-- which expects to see the characters ’a’ and ’b’ and returns them as a pair
abParser :: Parser (Char, Char)
abParser = (,) <$> char 'a' <*> char 'b'
-- Ex. 3b - Create a parser:
--
-- abParser_ :: Parser ()
--
-- which acts in the same way as abParser but returns () instead of 'a' and 'b'
abParser_ :: Parser ()
abParser_ = const . const () <$> char 'a' <*> char 'b'
-- Ex. 3c - Create a parser:
--
-- intPair
--
-- which reads two integer values separated by a space and returns the integer
-- values in a list. You should use the provided posInt to parse the integer values.
intPair :: Parser [Integer]
intPair = (\x y -> [x, y]) <$> posInt <* char ' ' <*> posIntExercise 4
instance Alternative Parser where
empty = Parser $ const Nothing
Parser p1 <|> Parser p2 = Parser $ liftA2 (<|>) p1 p2Exercise 5
-- Ex. 5 - Implement a parser:
--
-- intOrUppercase :: Parser ()
--
-- which parses either an integer value or an uppercase character, and fails otherwise.
intOrUppercase :: Parser ()
intOrUppercase = const () <$> posInt <|> const () <$> satisfy isUpperHide Comments
comments powered by Disqus