如何让Parsec让我调用`read` :: Int?

Noa*_*els 2 haskell parsec

我有以下类型检查:

p_int = liftA read (many (char ' ') *> many1 digit <* many (char ' '))
Run Code Online (Sandbox Code Playgroud)

现在,正如函数名称所暗示的那样,我希望它能给我一个Int.但如果我这样做:

p_int = liftA read (many (char ' ') *> many1 digit <* many (char ' ')) :: Int
Run Code Online (Sandbox Code Playgroud)

我收到这种类型的错误:

Couldn't match expected type `Int' with actual type `f0 b0'
In the return type of a call of `liftA'
In the expression:
    liftA read (many (char ' ') *> many1 digit <* many (char ' ')) ::
      Int
In an equation for `p_int':
    p_int
      = liftA read (many (char ' ') *> many1 digit <* many (char ' ')) ::
          Int
Run Code Online (Sandbox Code Playgroud)

是否有更简单,更清晰的方法来解析可能有空格的整数?或者解决这个问题的方法?

最终,我希望这成为以下内容的一部分:

betaLine = string "BETA " *> p_int <*> p_int  <*> p_int <*>
           p_int <*> p_parallel <*> p_exposure <* eol
Run Code Online (Sandbox Code Playgroud)

这是解析看起来像这样的行:

BETA  6 11 5 24 -1 oiiio
Run Code Online (Sandbox Code Playgroud)

所以我最终可以调用一个需要这些值的BetaPair构造函数(一些作为Int,一些像其他类型,如[Exposure]和Parallel)

(如果你很好奇,这是一个文件格式的解析器,它代表蛋白质中氢键合的β-链对.我无法控制文件格式!)

ste*_*ley 7

我怎么让Parsec让我打电话read :: Int

第二个答案是"不要使用阅读".

使用read等同于重新解析已经解析的数据 - 因此在Parsec解析器中使用它是代码气味.解析自然数是无害的,但是read对Parsec有不同的失败语义,并且它适合于Haskell的词法语法,因此将它用于更复杂的数字格式是有问题的.

如果你不想去定义LanguageDef和使用Parsec Token模块的麻烦,这里是一个不使用read的自然数字解析器:

-- | Needs @foldl'@ from Data.List and 
-- @digitToInt@ from Data.Char.
--
positiveNatural :: Stream s m Char => ParsecT s u m Int
positiveNatural = 
    foldl' (\a i -> a * 10 + digitToInt i) 0 <$> many1 digit
Run Code Online (Sandbox Code Playgroud)


Dan*_*her 5

p_int是一个产生一个的解析器Int,所以类型是Parser Int或类似的¹.

p_int = liftA read (many (char ' ') *> many1 digit <* many (char ' ')) :: Parser Int
Run Code Online (Sandbox Code Playgroud)

或者,您可以键入read函数,(read :: String -> Int)以告诉编译器表达式具有哪种类型.

p_int = liftA (read :: String -> Int) (many (char ' ') *> many1 digit <* many (char ' ')) :: Int
Run Code Online (Sandbox Code Playgroud)

而对于更清洁的方式,考虑更换many (char ' ')spaces.

¹ ParsecT x y z Int,例如.