parserChar :: Char -> Parser Char
parserChar c = Parser ch where
ch d = case dvChar d of
Parsed c dp -> Parsed c dp
_ -> NoParse
The above function is supposed to take a Char c
and return a Parser which will only match c
. The function dvChar d
is going 开发者_开发百科to return either Parsed char dp
or NoParse
(where char
is the next character in the string). Thus, I had hoped that Parsed c dp
would only match a result in which char==c
, but what's actually happening is that the Parser returned by this function matches any character (even though c
seems to be bound to some particular Char, as a function argument).
The following function works correctly:
parserChar :: Char -> Parser Char
parserChar c = Parser ch where
ch d = case dvChar d of
Parsed char dp -> if char == c then Parsed char dp else NoParse
_ -> NoParse
Manually coding the parser to parse the letter 'a'
also works correctly, in that
case dvChar d of
Parsed 'a' dp -> Parsed 'a' dp
_ -> NoParse
will only return success if the character was 'a'
.
So what gives? Can you only match literals in a pattern like that (e.g. despite the fact that Char is in class Eq, the if char==c (..)
still needs to be coded manually), or am I doing something wrong?
Yes, you can only match literals. In fact, a better way to think about it is that you can only match constructors, and it so happens that Int, Char, String & co. all have literal constructors.
Note that you can also mix case and guards and write it as (from memory):
parserChar :: Char -> Parser Char
parserChar c = Parser ch where
ch d = case dvChar d of
Parsed char dp | char == c -> Parsed char dp
_ -> NoParse
精彩评论