2

我被 attoparsec 困住了,我无法返回关于它的“嵌入式类型”的值。

我尝试解析一种文件:

type
value
type
value
...

例如:

0 -- code for a string value
hello
70 -- code for an int value
10
0
world
20 -- code for a double value
5.20

我当前的数据类型是:

data KeyValue = forall a. (Typeable a, Show a, Eq a) => KeyValue (Int, a)
instance Eq KeyValue where -- as I need to test equality
    KeyValue (code1, value1) == KeyValue (code2, value2) =
      code1 == code2 && case cast value2 of
                               Just value2' -> value1 == value2
                               Nohing -> False

我的解析器看起来像:

parser :: Parser [KeyValue]
parser = many' (keyValue <* endOfLine)

keyValue :: Parser KeyValue
keyValue = do
    key <- decimal <* endOfLine
    value <- case key of
               0  -> takeLine
               20 -> double
               70 -> decimal
               _ -> takeLine
    return $ KeyValue (key, value)

takeLine :: Parser Text
takeLine = takeTill isEndOfLine

但 GHC 抱怨说:

Couldn't match type Double with Text
Expected type: Parser Text Text
  Actual type: Parser Double
In the expression: double
In a case alternative: 20 -> double

我明白为什么,但不知道如何解决这个问题!

目前,我使用ExistantialQuantificationpragma with Data.Typeable,但我不确定解决方案是否需要“如此复杂”来解决这个问题?

4

1 回答 1

8

创建一个 sum 类型并让您的解析器返回它,例如:

data SumType = Str String | Int Int | Double Double

keyvalue :: Parser SumType
keyvalue = ...

现在keyvalue可以以 with 结尾return (Str "foo")来表示一个字符串已经被解析,或者 withreturn (Int 23)等等来表示一个 int 已经被解析。

例如:

keyValue = do
    key <- decimal <* endOfLine
    case key of
      20 -> do d <- parseDouble; return (Double d)
      70 -> do i <- parseInt; return (Int i)
      ...
于 2015-07-28T19:50:23.967 回答