Parsec返回[Char]而不是Text

时间:2014-05-06 19:51:35

标签: haskell type-inference parsec

我正在尝试为自定义文件格式创建解析器。在我正在使用的格式中,某些字段具有如下的结束标记:

<SOL>
<DATE>0517
<YEAR>86
</SOL>

我试图获取</>之间的值,并将其用作更大解析器的一部分。

我已经提出了以下代码。问题是,解析器返回[Char]而不是Text。我可以通过执行Char打包每个fmap pack $ return r以获取文本值,但我希望类型推断可以使我不必这样做。有人可以提示我为什么要回来[Char]而不是Text,以及如何在不必手动打包价值的情况下取回Text

{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverloadedStrings #-}

import           Data.Text
import           Text.Parsec
import           Text.Parsec.Text

-- |A closing tag is on its own line and is a "</" followed by some uppercase characters
-- followed by some '>'
closingTag = do
    _ <- char '\n'
    r <- between (string "</") (char '>') (many upper)
    return r

2 个答案:

答案 0 :(得分:4)

string的类型为

string :: Stream s m Char => String -> ParsecT s u m String

(有关文档,请参阅here

所以让String回来正是应该发生的事情。

类型推断不会更改类型,它只会推断它们。 String是具体类型,因此无法推断出Text

如果你需要在几个地方做的话,你可以做的是编写一个函数

text :: Stream s m Char => String -> ParsecT s u m Text 
text = fmap pack . string

甚至

string' :: (IsString a, Stream s m Char) => String -> ParsecT s u m a
string' = fmap fromString . string

此外,在此示例中无关紧要,但您可能想要导入Text限定条件,pack等名称会在许多不同的模块中使用。


正如ØrjanJohansen正确指出的那样,string实际上不是问题,many upper是。同样的原则适用。

答案 1 :(得分:3)

此处获得[Char]的原因是upper解析Charmany将其转换为[Char]。我会按照以下方式编写自己的组合器:

manyPacked = fmap pack . many

您可以使用类型级别的类型级编程来自动选择manymanyPack,具体取决于期望的返回类型,但我认为这不值得。 (它可能看起来有点像Scala的CanBuiltFrom)。