Parsing 如何在haskell中使用parsec解析带基前缀的整数?

Parsing 如何在haskell中使用parsec解析带基前缀的整数?,parsing,haskell,parsec,Parsing,Haskell,Parsec,我正在尝试使用parsec解析haskell中的输入整数字符串。字符串可以是十进制、八进制或十六进制。基数由前缀#d、#o或#x分别为十进制、八进制和十六进制指定,然后后跟整数。如果未指定前缀,则假定基数为10。以下是我迄今为止所做的工作: parseNumber = do x <- noPrefix <|> withPrefix return x where noPrefix = many1 digit

我正在尝试使用parsec解析haskell中的输入整数字符串。字符串可以是十进制、八进制或十六进制。基数由前缀
#d
#o
#x
分别为十进制、八进制和十六进制指定,然后后跟整数。如果未指定前缀,则假定基数为10。以下是我迄今为止所做的工作:

parseNumber = do x <- noPrefix <|> withPrefix
             return x
          where noPrefix = many1 digit
                withPrefix = do char '#'
                                prefix <- oneOf "dox"
                                return $ case prefix of
                                    'd' -> many1 digit
                                    'o' -> fmap (show . fst . head . readOct) (many1 octDigit)
                                    'x' -> fmap (show . fst . head . readHex) (many1 hexDigit)
parseNumber=do x fmap(show.fst.head.readOct)(多个八位数)
'x'->fmap(show.fst.head.readHex)(多个十六进制数字)
但是,这不是编译,并且由于类型错误而失败。我真的不太理解类型错误,只是想在这个问题上得到一般性的帮助。任何其他解决方法也将受到赞赏

感谢您的时间和帮助。:)


编辑:我收到的错误。

您有两个轻微错误:

一个缩进错误(
return x
必须与
do
相比缩进),并且withPrefix中的解析器不能
return
ed,因为它们无论如何都将
返回其结果

parseNumber = do x <- noPrefix <|> withPrefix
                 return x
      where noPrefix = many1 digit
            withPrefix = do char '#'
                            prefix <- oneOf "dox"
                            case prefix of
                                'd' -> many1 digit
                                'o' -> fmap (show . fst . head . readOct) (many1 octDigit)
                                'x' -> fmap (show . fst . head . readHex) (many1 hexDigit)
parseNumber=do x fmap(show.fst.head.readOct)(多个八位数)
'x'->fmap(show.fst.head.readHex)(多个十六进制数字)
这应该在现代社会中起作用 Parsec的fork,此问题不存在(从 ):

解析十六进制表示的整数。代表 十六进制数字应符合Haskell报告,但 因为这个解析器不解析“0x”或“0x”前缀。它是 程序员在解析前解析正确前缀的责任 数字本身

例如,您可以使其符合Haskell报告,如下所示:

hexadecimal = char '0' >> char' 'x' >> L.hexadecimal
因此,在您的情况下,您可以定义(注意它的可读性):

导入数据。无效
导入文本.Megaparsec
导入Text.Megaparsec.Char
将限定的Text.Megaparsec.Char.Lexer作为L导入
类型Parser=Parsec空字符串
parseNumber::解析器整数
parseNumber=选择
[L.十进制
,(字符串“o#”*>L.octal)“八进制整数”
,(字符串“d#”*>L.decimal)“十进制整数”
,(字符串“h#”*>L.hexadecimal)“十六进制整数”]
让我们试试解析器(注意错误消息的质量):


λ>parseTest'(parseNumber parseTest'(parseNumber parseTest'(parseNumber parseTest')parseNumber parseTest'(parseNumber您可以发布您收到的错误吗?Text.Megaparsec.Lexer不再存在于Megaparsec中,此时,可以在中找到
十六进制
。另外请注意,在版本6.0.0之前,函数返回的是
整数
,即它的返回类型不是多态的。
import Data.Void
import Text.Megaparsec
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L

type Parser = Parsec Void String

parseNumber :: Parser Integer
parseNumber = choice
  [ L.decimal
  , (string  "o#" *> L.octal)       <?> "octal integer"
  , (string  "d#" *> L.decimal)     <?> "decimal integer"
  , (string  "h#" *> L.hexadecimal) <?> "hexadecimal integer" ]
λ> parseTest' (parseNumber <* eof) ""
1:1:
  |
1 | <empty line>
  | ^
unexpected end of input
expecting decimal integer, hexadecimal integer, integer, or octal integer
λ> parseTest' (parseNumber <* eof) "d#3"
3
λ> parseTest' (parseNumber <* eof) "h#ff"
255
λ> parseTest' (parseNumber <* eof) "o#8"
1:3:
  |
1 | o#8
  |   ^
unexpected '8'
expecting octal integer
λ> parseTest' (parseNumber <* eof) "o#77"
63
λ> parseTest' (parseNumber <* eof) "190"
190