问题
From Text.Parsec.Token
:
lexeme p = do { x <- p; whiteSpace; return x }
It appears that lexeme takes a parser p and delivers a parser that has the same behavior as p, except that it also skips all the trailing whitespace. Correct?
Then how come the following does not work:
constant :: Parser Int
constant = do
digits <- many1 digit
return (read digits)
lexConst :: Parser Int
lexConst = lexeme constant
The last line results in the following error message:
Couldn't match expected type `ParsecT
String () Data.Functor.Identity.Identity Int'
with actual type `ParsecT s0 u0 m0 a0 -> ParsecT s0 u0 m0 a0'
Expected type: Parser Int
Actual type: ParsecT s0 u0 m0 a0 -> ParsecT s0 u0 m0 a0
In the return type of a call of `lexeme'
In the expression: lexeme constant
What am I doing wrong?
回答1:
You misunderstood the documentation, the lexeme exported from Text.Parsec.Token
is a field of a GenTokenParser s u m, so the type is
lexeme :: GenTokenParser s u m -> ParsecT s u m a -> ParsecT s u m a
and you haven't supplied the GenTokenParser
argument in lexeme constant
.
You need to create a GenTokenParser
from a GenLanguageDef (typically with makeTokenParser) first to use its lexeme
field.
回答2:
The lexeme
function is an accessor into a GenTokenParser
record of parsers generated by makeTokenParser
, so you need to apply it to such a record to get at it. One common way of doing this is to use record wildcards, e.g.
{-# LANGUAGE RecordWildCards #-}
import qualified Text.Parsec.Token as Tok
Tok.TokenParser { .. } = Tok.makeTokenParser {- language definition -}
This will bring lexeme
and all the other parsers into scope already applied to the record, so you can use it like you were trying to do.
来源:https://stackoverflow.com/questions/16402571/i-dont-understand-how-to-use-the-lexeme-function