attoparsec 如何可以 return 不同类型的值?
How attoparsec can return values of different types?
我被 attoparsec 困住了,我无法 return 一个关于它的值 "embedded type"。
我尝试解析一种文件:
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
我明白为什么但不知道如何解决这个问题!
目前,我使用 ExistantialQuantification
pragma 和 Data.Typeable
,但我不确定解决方案是否需要 "so complex" 有那个问题吗?
创建求和类型并让您的解析器return,例如:
data SumType = Str String | Int Int | Double Double
keyvalue :: Parser SumType
keyvalue = ...
现在keyvalue
可以以return (Str "foo")
结束表示一个字符串已经被解析或者以return (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)
...
我被 attoparsec 困住了,我无法 return 一个关于它的值 "embedded type"。
我尝试解析一种文件:
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
我明白为什么但不知道如何解决这个问题!
目前,我使用 ExistantialQuantification
pragma 和 Data.Typeable
,但我不确定解决方案是否需要 "so complex" 有那个问题吗?
创建求和类型并让您的解析器return,例如:
data SumType = Str String | Int Int | Double Double
keyvalue :: Parser SumType
keyvalue = ...
现在keyvalue
可以以return (Str "foo")
结束表示一个字符串已经被解析或者以return (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)
...