I have trouble in understanding the following Applicative instance. Can someone explain me what Applicative do(in this case) and how it can be used? Or write it less obfuscated? Thanks!
newtype Parser a = P { getParser :: String -> Maybe (a, String) }
instance Applicative Parser where
pure = success
P p <*> P p' = P $ \s -> case p s of
Just (f, s') -> fmap (applyToFirst f) $ p' s'
Nothing -> Nothing
{-|
Applies a function to the first component of a pair.
-}
applyToFirst :: (a -> b) -> (a, c) -> (b, c)
applyToFirst f (x, y) = (f x, y)
Maybe the following equivalent code makes it more clear what's going on?
instance Applicative Parser where
pure v = P (\s -> Just (v, s))
P p <*> P p' = P $ \s -> case p s of
Just (f, s') -> case p' s' of
Just (v, s'') -> Just (f v, s'')
Nothing -> Nothing
Nothing -> Nothing
Combining two parsers with <*> gives you new parser. Given an input string, the new parser runs the first parser returning a result and the unparsed remainder of the string. The remainder of the string is given to the second parser returning a result and unparsed remainder. Then the two results are combined. If either parser fails the result is failure.
Related
I am trying to get a hold over understanding Applicative functors currently. And my understanding is falling short somewhere but I cannot pinpoint where.
Source from where I am trying to build an understanding CIS 194 UPenn - Homework 10
I am working with a custom data type and its Applicative instance which are as follows :
-- A parser for a value of type a is a function which takes a String
-- represnting the input to be parsed, and succeeds or fails; if it
-- succeeds, it returns the parsed value along with the remainder of
-- the input.
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }
instance Functor Parser where
fmap :: (a -> b) -> Parser a -> Parser b
fmap fn parserA = Parser (fmap (first fn) . parseAFunc)
where parseAFunc = runParser parserA
appliedFunc p1 p2 str = case runParser p1 str of
Nothing -> Nothing
Just (f, str2) -> case runParser p2 str2 of
Nothing -> Nothing
Just (x, str3) -> Just (f x, str3)
instance Applicative Parser where
pure a = Parser (\s -> Just (a, s))
p1 <*> p2 = Parser (appliedFunc p1 p2)
-- For example, 'satisfy' takes a predicate on Char, and constructs a
-- parser which succeeds only if it sees a Char that satisfies the
-- predicate (which it then returns). If it encounters a Char that
-- does not satisfy the predicate (or an empty input), it fails.
satisfy :: (Char -> Bool) -> Parser Char
satisfy p = Parser f
where
f [] = Nothing -- fail on the empty input
f (x:xs) -- check if x satisfies the predicate
-- if so, return x along with the remainder
-- of the input (that is, xs)
| p x = Just (x, xs)
| otherwise = Nothing -- otherwise, fail
-- Using satisfy, we can define the parser 'char c' which expects to
-- see exactly the character c, and fails otherwise.
char :: Char -> Parser Char
char c = satisfy (== c)
-- Below is a parser for positive Ints which parses
-- the prefix of contiguous digits in a given String
-- as an Int
posUse :: Parser Int
posUse = Parser f
where
f xs
| null ns = Nothing
| otherwise = Just (read ns, rest)
where (ns, rest) = span isDigit xs
-- Below function takes a function and a pair and returns a pair
-- with the function applied to the first element of pair
first :: (a -> b) -> (a, c) -> (b, c)
first fn (x, y) = (fn x, y)
Using all the above setup, I am trying to construct some more complicated Parsers using simple Parsers defined above. So fmap has type fmap :: Functor f => (a -> b) -> f a -> f b. And as per my understanding currently, Applicative allows us to extend fmap to functions that take n-ary functions and n Functor parameters and return the resultant functor.
fmap can be defined in terms of pure and <*> as :
fmap1 :: Applicative f => (a -> b) -> f a -> f b
fmap1 f x = pure f <*> x
I understand why the above will work given that the implementations of pure and <*> are appropriate since the types nicely line up.
Extending this to fmap2 aka liftA2 :
fmap2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
fmap2 f x y = pure f <*> x <*> y
My understanding of why the above works is as follows :
pure g will have type f (a -> b -> c) And so therefore pure g <*> x will have type f (b -> c) since functions are curried. Then this type combined with the type type of y (f b) using <*> will finally give us the type of the result which is f c which is what we needed the type fmap2 to be.
This understanding did not break down when I tried to construct a Parser out of 2 simple Parsers as follows :
-- This Parser expects to see the characters ’a’ and ’b’ and returns them
-- as a pair.
abParser = liftA2 (\c1 c2 -> (c2 c1)) (char 'a') (char 'b')
The above works as expected.
But when I try to make the parser intPair which reads two integer values separated by a space and returns the integer values in a list using liftA3 my understanding of lift is not working since I expect the following to work but the linter complains :
intPair :: Parser [Int]
intPair = liftA3 (\x y z -> [z x]) posUse (char ' ') posUse
The above does not compile as the last argument needs to have the type Parser (Int -> a) (according to type inference) but I have passed posUse which has the type Parser Int.
TL;DR :
Sorry for the long description. If anyone does not want to go through it all (expecially the custom data type and its Applicative and Functor instance) -- please let me know if my understanding of why fmap2 aka liftA2 works is correct and how does that understanding extend to liftA3 ?
The definition of liftA3 seems to be something different than just an extension of the definition of liftA2 using <*> and pure.
Edit 1 :
As stated above, the below line was being complained about by the linter
intPair :: Parser [Int]
intPair = liftA3 (\x y z -> [z x]) posUse (char ' ') posUse
The linter expected the type for the last argument to be Parser (Int -> a).
But after I defined an explicit function instead of passing a lambda, it worked as I expected to work.
fnn :: Int -> Char -> Int -> [Int]
fnn arg1 arg2 arg3 = [arg1, arg3]
intPair = liftA3 fnn posUse (char ' ') posUse
It works as I expected.
Yes, your understanding of liftA2 is correct, and liftA3 is just more of the same. I can't guess why it looks different to you, but inlining the definition of liftA2 into the definition of liftA3 may help.
liftA2 :: Applicative f => (a -> b -> c)
-> f a -> f b -> f c
liftA2 f x y = pure f <*> x <*> y
liftA3 :: Applicative f => (a -> b -> c -> d)
-> f a -> f b -> f c -> f d
liftA3 f a b c = liftA2 f a b <*> c
I took these definitions from https://hackage.haskell.org/package/base-4.17.0.0/docs/src/GHC.Base.html, and rearranged the definition of liftA2 a little to make it more explicit - it matches your fmap2 exactly.
Now, note that liftA3 includes a call to liftA2 f a b. We know how liftA2 f a b is defined, and because of purity, we can always inline definitions to yield semantically identical terms. So let's do that:
liftA3 f a b c = (pure f <*> a <*> b) <*> c
The parentheses are redundant, but I put them in while substituting just in case. Now if we remove them, we see there is no new idea here:
liftA3 f a b c = pure f <*> a <*> b <*> c
We lift the function, yielding f (a -> b -> c -> d), then apply that to a with <*> to get an f (b -> c -> d), and so on, all the way to an f d at the end.
You've just made a silly mistake when converting from a named function to an anonymous one. Contrast:
fnn arg1 arg2 arg3 = [arg1, arg3] -- your working code
fnn = \x y z -> [z x] -- your broken code
fnn = \x y z -> [z, x] -- type-correct code
fnn = \x y z -> [x, z] -- more correct translation of your working code
I have the following type:
newtype Rep f a = Rep { runRep :: String -> f (String, a) }
The type Rep f a is a stateful computation that takes a String as the initial state and produces a (String, a) as the result of the computation. The result of the computation is wrapped in the functor f.
The monad instance for Rep is the following:
instance Monad f => Monad (Rep f) where
return x = pure x
Rep a >>= f = Rep $ \s -> do
(s', xa) <- a s
let (Rep f') = f xa
(s'', xf) <- f' s'
pure (s'', xf)
The alternative instance for Rep is the following:
instance (Monad f, Alternative f) => Alternative (Rep f) where
empty = Rep (const empty)
Rep a <|> Rep b = Rep $ \s -> a s <|> b s
I also have the following function:
readCharacter :: (Alternative f, Monad f) => Rep f Char
readCharacter = Rep $ \s -> case s of
[] -> empty
(x:xs) -> pure (xs,x)
The above function takes a state and returns empty if the state is an empty list. If the state is not an empty list, it returns a tuple with the first element the modified state and the second a Char, wrapped in the functor f.
And I also have the following function and data type:
data Res = Nil | Character Char | Cop Res Res | Special [Res]
findmatch :: (Monad f, Alternative f) => String -> Rep f Res
findmatch (cs) = do
x <- readCharacter
guard (x `elem` cs)
pure (Character x)
I am having trouble understanding how the above function works. It seems to me that for each character in the string cs, the readCharacter function is called. If the character returned by readCharacter is an element of the string cs, then the expression will evaluate to true. Suppose that the functor f is Maybe - then guard (True) will return a Just (), and then pure (Character x) is returned.
However, I am not sure what happens when the guard expression evaluates to False. For example, assuming that the functor is Maybe, guard False will return Nothing. If Nothing is returned by guard False, is it the case that the overall do block will return Nothing? Any insights are appreciated.
I found a Parser example in haskell that use monadic error handling and state.
It's written like this.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Monad.Except
import Control.Monad.State
newtype Parser a
= Parser { runParser :: ExceptT String (State String) a }
deriving ( Functor
, Applicative
, Monad
, MonadError String
, MonadState String
)
I understand what it does and how to use it. But, what I want to know is how
it's implemented without GeneralizedNewtypeDeriving extension.
So, how to make Parser an instance of Functor, Applicative, Monad,
MonadError, MonadState if there is no GeneralizedNewtypeDeriving
extension?
GeneralizedNewtypeDeriving wraps the instances of the underlying type (in your case, ExceptT String (State String)) with the newtype boilerplate. The Functor one, for example, amounts to:
-- p :: ExceptT String (State String) a
instance Functor Parser where
fmap f (Parser p) = Parser (fmap f p)
-- Or, equivalently:
-- fmap f = Parser . fmap f . runParser
As for what the underlying instances do, you can check their sources by following the "Source" links for the instances in the docs. Functor for ExceptT, for example, is:
instance (Functor m) => Functor (ExceptT e m) where
fmap f = ExceptT . fmap (fmap f) . runExceptT
(The nested fmaps are there because the underlying type of ExceptT e m a is m (Either e a), and so there are two Functor layers to get through: m and Either.)
It took me almost the whole day to figure out how implement this. But, after I
figure it out, the concept is actually pretty simple. The whole point is to dig
through the monad stack to apply a function that is to be implemented and then
bury the result in the monad stack again. Those jobs can be done with these
functions:
unwrap :: Parser a -> String -> (Either String a, String)
unwrap p s = runState (runExceptT (runParser p)) s
wrap :: (String -> (Either String a, String)) -> Parser a
wrap f = Parser (ExceptT (state (\s -> (f s))))
So, to make the Parser an instance of Functor, Applicative, Monad,
MonadError and MonadStateI can just define a lambda or a function inside
where binding and then wrap it with wrap.
Here is the instances implementation:
instance Functor Parser where
fmap f p = wrap fn
where fn s = let (ea, s') = unwrap p s
in case ea of
Right a -> (Right (f a), s')
Left e -> (Left e, s)
instance Applicative Parser where
pure x = wrap fn
where fn s = (Right x, s)
p1 <*> p2 = wrap fn
where fn s = let (ef, s') = unwrap p1 s
(ea, s'') = unwrap p2 s'
in run ef ea s'' s
run (Right f) (Right a) s' s = (Right (f a), s')
run (Left e) _ s' s = (Left e, s)
run _ (Left e) s' s = (Left e, s)
instance Monad Parser where
return = pure
p >>= f = wrap fn
where fn s = let (ea, s') = unwrap p s
in case ea of
Right a -> unwrap (f a) s'
Left e -> (Left e, s)
instance MonadError String Parser where
throwError err = wrap fn
where fn s = (Left err, s)
catchError p h = wrap fn
where fn s = let (ea, s') = unwrap p s
in case ea of
Right a -> (Right a, s')
Left e -> unwrap (h e) s
instance MonadState String Parser where
get = wrap fn
where fn s = (Right s, s)
put s = wrap fn
where fn s = (Right (), s)
With that, the parser now can be used like this:
item :: Parser Char
item = do
s <- get
case s of
[] -> throwError "unexpected end of input"
(c:cs) -> do put cs
return c
satisfy :: (Char -> Bool) -> Parser Char
satisfy p = item >>= \c -> if p c then return c else throwError $ "unexpected: " ++ show c
char :: Char -> Parser Char
char c = satisfy (c ==)
main :: IO ()
main = do
print $ unwrap item "c"
print $ unwrap (char 'c') "c"
print $ unwrap (satisfy isDigit) "c"
When learning the Reader Monad, I find that it is defined as:
newtype Reader r a = Reader { runReader :: r -> a }
instance Monad (Reader r) where
return a = Reader $ \_ -> a
m >>= k = Reader $ \r -> runReader (k (runReader m r)) r
I want to known why using function as constructor parameter instead of something else such as a tuple:
newtype Reader r a = Reader { runReader :: (r, a) }
instance Monad (Reader r) where
-- Here I cannot get r when defining return function,
-- so does that's the reason that must using a function whose input is an "r"?
return a = Reader (r_unknown, a)
m >>= k = Reader (fst $ runReader m) (f (snd $ runReader m))
According to the Reader definition, we need a "environment" which we can use to generate a "value". I think a Reader type should contain the information of "environment" and "value", so the tuple seems perfect.
You didn't mention it in the question, but I guess you thought specifically of using a pair for defining Reader because it also makes sense to think of that as a way of providing a fixed environment. Let's say we have an earlier result in the Reader monad:
return 2 :: Reader Integer Integer
We can use this result to do further calculations with the fixed environment (and the Monad methods guarantee it remains fixed throughout the chain of (>>=)):
GHCi> runReader (return 2 >>= \x -> Reader (\r -> x + r)) 3
5
(If you substitute the definitions of return, (>>=) and runReader in the expression above and simplify it, you will see exactly how it reduces to 2 + 3.)
Now, let's follow your suggestion and define:
newtype Env r a = Env { runEnv :: (r, a) }
If we have an environment of type r and a previous result of type a, we can make an Env r a out of them...
Env (3, 2) :: Env Integer Integer
... and we can also get a new result from that:
GHCi> (\(r, x) -> x + r) . runEnv $ Env (3, 2)
5
The question, then, is whether we can capture this pattern through the Monad interface. The answer is no. While there is a Monad instance for pairs, it does something quite different:
newtype Writer r a = Writer { Writer :: (r, a) }
instance Monoid r => Monad (Writer r) where
return x = (mempty, x)
m >>= f = Writer
. (\(r, x) -> (\(s, y) -> (mappend r s, y)) $ f x)
$ runWriter m
The Monoid constraint is needed so that we can use mempty (which solves the problem that you noticed of having to create a r_unknown out of nowhere) and mappend (which makes it possible to combine the first elements of the pair in a way that doesn't violate the monad laws). This Monad instance, however, does something very different than what the Reader one does. The first element of the pair isn't fixed (it is subject to change, as we mappend other generated values to it) and we don't use it to compute the second element of the pair (in the definition above, y does not depend neither on r nor on s). Writer is a logger; the r values here are output, not input.
There is one way, however, in which your intuition is justified: we can't make a reader-like monad using a pair, but we can make a reader-like comonad. To put it very loosely, Comonad is what you get when you turn the Monad interface upside down:
-- This is slightly different than what you'll find in Control.Comonad,
-- but it boils down to the same thing.
class Comonad w where
extract :: w a -> a -- compare with return
(=>>) :: w a -> (w a -> b) -> w b -- compare with (>>=)
We can give the Env we had abandoned a Comonad instance:
newtype Env r a = Env { runEnv :: (r, a) }
instance Comonad (Env r) where
extract (Env (_, x)) = x
w#(Env (r, _)) =>> f = Env (r, f w)
That allows us to write the 2 + 3 example from the beginning in terms of (=>>):
GHCi> runEnv $ Env (3, 2) =>> ((\(r, x) -> x + r) . runEnv)
(3,5)
One way to see why this works is noting that an a -> Reader r b function (i.e. what you give to Reader's (>>=)) is essentially the same thing that an Env r a -> b one (i.e. what you give to Env's (=>>)):
a -> Reader r b
a -> (r -> b) -- Unwrap the Reader result
r -> (a -> b) -- Flip the function
(r, a) -> b -- Uncurry the function
Env r a -> b -- Wrap the argument pair
As further evidence of that, here is a function that changes one into the other:
GHCi> :t \f -> \w -> (\(r, x) -> runReader (f x) r) $ runEnv w
\f -> \w -> (\(r, x) -> runReader (f x) r) $ runEnv w
:: (t -> Reader r a) -> Env r t -> a
GHCi> -- Or, equivalently:
GHCi> :t \f -> uncurry (flip (runReader . f)) . runEnv
\f -> uncurry (flip (runReader . f)) . runEnv
:: (a -> Reader r c) -> Env r a -> c
To wrap things up, here is a slightly longer example, with Reader and Env versions side-by-side:
GHCi> :{
GHCi| flip runReader 3 $
GHCi| return 2 >>= \x ->
GHCi| Reader (\r -> x ^ r) >>= \y ->
GHCi| Reader (\r -> y - r)
GHCi| :}
5
GHCi> :{
GHCi| extract $
GHCi| Env (3, 2) =>> (\w ->
GHCi| (\(r, x) -> x ^ r) $ runEnv w) =>> (\z ->
GHCi| (\(r, x) -> x - r) $ runEnv z)
GHCi| :}
5
First of all note that your bind function is wrong and would not compile.
If the Reader were defined as you describe with a tuple, there would be problems:
The monad laws would be violated, e.g. left identity, which states that:
return a >>= f == f a
or the right identity:
m >>= return == m
would be broken, depending on the implmentation of >>= because >>= would forget either the first tuple element of the first argument or the second, i.e. if the implmentation would be:
(Reader (mr, mv)) >>= f =
let (Reader (fr, fv)) = f mv
in Reader (mr, fv)
then we would always lose the reader value that comes out of f (aka fr) and otherwise if >>= would be
(Reader (mr, mv)) >>= f =
let (Reader (fr, fv)) = f mv
in Reader (fr, fv)
-- ^^^ tiny difference here ;)
we would always lose mr.
A Reader is some action, that may ask for a constant value, which cannot be changed by another monadic action, which is read-only.
But when defined with a tuple, we could super-easy overwrite the reader value, e.g. whith this function:
tell :: x -> BadReader x ()
tell x = BadReader (x, ())
If a reader is instead defined with a function, this is impossible (try it)
Also, that enviroment is actually not required before converting a Reader to a pure value (aka running the Reader), so from this alone it makes sense to use a function instead of a tuple.
When using a tuple, we would have to provide the Reader value even before we actually run an action.
You can see that in your return definition, you even point out the problem, where the r_unknown comes from ...
To get a btter intuition, let's assume a Reader action that returns the Persons with a certain age from the Addressbook:
data Person = MkPerson {name :: String, age :: Int}
type Addressbook = [Person]
personsWithThisAge :: Int -> Reader Addressbook [Person]
personsWithThisAge a = do
addressbook <- ask
return (filter (\p -> age p == a) addressbook)
This personsWithAge function returns a Reader action and since it only asks for the Addressbook, it is like a function that accepts an addressbook and gives back a [Person] list,
so it is natural to define a reader as just that, a function from some input to a result.
We could rewrite this Reader action to be a function of the Addressbook like this:
personsWithThisAgeFun :: Int -> Addressbook -> [Person]
personsWithThisAgeFun a addressbook =
filter (\p -> age p == a) addressbook
But why invent Reader??
The real value of Reader shows when combining several functions like e.g. personsWithThisAge, that all depend on (the same) one constant Addressbook.
Using a Reader we don't have to explicitly pass some Addressbook around, individual Reader actions don't even have any way at all to modify the Addressbook - Reader guarantees us, that every action uses the same, unmodified Addressbook, and all a Reader action can ever to with the environment is ask for it.
The only way to implement this, with these guarantees is with a function.
Also if you look at the monad instances that are included in the standard library, you will see that (r ->) is a monad; actually it is identical to the Reader monad apart from some technical differences.
Now the structure you describe with the tuple is actually pretty close to a Writer monad, what is write-only , but that's out of scope.
This is something of a combination of State and Writer. I have checked the monad laws.
newtype M s a = M { runM :: s -> (s,a) }
instance (Monoid s) => Monad (M s) where
return = M . const . (mempty,)
m >>= f = M $ \s ->
let (s' ,x) = runM m s
(s'',y) = runM (f x) (s `mappend` s')
in (s' `mappend` s'', y)
StateWriter seems kinda lame.
"Introspective Writer"? It seems that the interesting you can do with it (that you can't do with Writer) is to write an introspect function that examines the state/output and changes it:
introspect :: (s -> s) -> M s ()
introspect f = M $ \s -> (f s, ())
I can't see that you can do this for writer, I think you'd have to make do with a post-transformer instead:
postW :: Writer w a -> (w -> w) -> Writer w a
postW ma f = Writer $ let (w,a) = getWriter ma in (f w,a)
Monoidal State. MonoState.MState. AccumState.
Maybe call SW (Statefull Writer), I think short names are rather intuitive and save some typing.