Reputation:
I'm reading this paper regarding a monadic parser in Haskell and as a newbie I cannot understand the following construct:
newtype Parser a = Parser (String -> [(a, String)])
instance Monad Parser where
return a = Parser (\cs -> [(a,cs)])
p >>= f = Parser (\cs -> concat [parse (f a) cs’ |
(a,cs’) <- parse p cs])
parse :: Parser a -> String -> [(a,String)]
parse (Parser p) = p
It says in the text that:
Using a deconstructor function for parsers defined by parse (Parser p) = p, the parser p >>= f first applies the parser p to the argument string cs to give a list of results of the form (a,cs’), where a is a value and cs’ is a string. For each such pair, f a is a parser which is applied to the string cs’.
Why is (f a) and not f a parser? And why is passing the 'a' necessary?
Upvotes: 0
Views: 307
Reputation: 129119
The type of (>>=)
, instantiated with the monad Parser
, has this type signature:
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
Hence, when defining p >>= f
, p
has type Parser a
and f
has type a -> Parser b
. That’s why f a
is a parser and not f
: f
is a function from a
to Parser b
s.
The reason it’s that way is that without it, we could combine parsers… but we would never be able to use the result of the previous parser in the next parse! By passing the result of the previous parser forward, we can build up data out of the results of multiple parsers, e.g.:
parseTwoOf :: Parser a -> Parser (a, a)
parseTwoOf p = p >>= \first -> p >>= \second -> return (first, second)
Upvotes: 2