I don't understand how to use the lexeme function

主宰稳场 提交于 2019-12-11 04:34:04

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!