Haskell的Parsec <|>运算符的问题

Gra*_*ore 4 parsing haskell parsec

我是Haskell和Parsec的新手.为了更多地了解语言和特定库,我正在尝试创建一个可以解析Lua保存的变量文件的解析器.在这些文件中,变量可以采用以下形式:

varname = value

varname = {value,value,...}

varname = {{value,value},{value,value,...}}

我已经为每种类型创建了解析器,但是当我将它们与选择<|>运算符串在一起时,我得到了一个类型错误.

Couldn't match expected type `[Char]' against inferred type `Char'
  Expected type: GenParser Char st [[[Char]]]
  Inferred type: GenParser Char st [[Char]]
In the first argument of `try', namely `lList'
In the first argument of `(<|>)', namely `try lList'
Run Code Online (Sandbox Code Playgroud)

我的假设是(虽然我在文档中找不到)传递给选择运算符的每个解析器必须返回相同的类型.这是有问题的代码:

data Variable = LuaString ([Char], [Char])
          | LuaList ([Char], [[Char]])
          | NestedLuaList ([Char], [[[Char]]])
          deriving (Show)

main:: IO()
main = do
       case (parse varName "" "variable = {{1234,\"Josh\"},{123,222}}") of
            Left err -> print err
            Right xs -> print xs 

varName :: GenParser Char st Variable
varName = do{
        vName <- (many letter);
        eq <- string " = ";
        vCon <- try nestList
             <|> try lList 
             <|> varContent;
        return (vName, vCon)}

varContent :: GenParser Char st [Char]
varContent =  quotedString 
    <|> many1 letter
    <|> many1 digit

quotedString :: GenParser Char st [Char]
quotedString = do{
         s1 <- string "\""; 
         s2 <- varContent;
         s3 <- string "\"";
         return (s1++s2++s3)}

lList :: GenParser Char st [[Char]]
lList = between (string "{") (string "}") (sepBy varContent (string ","))

nestList :: GenParser Char st [[[Char]]]
nestList = between (string "{") (string "}") (sepBy lList (string ","))
Run Code Online (Sandbox Code Playgroud)

luq*_*qui 7

那是对的.

(<|>) :: (Alternative f) => f a -> f a -> f a
Run Code Online (Sandbox Code Playgroud)

注意两个参数是如何完全相同的类型.

我不完全了解您的Variable数据类型.这是我这样做的方式:

data LuaValue = LuaString String | LuaList [LuaValue]
data Binding = Binding String LuaValue
Run Code Online (Sandbox Code Playgroud)

这允许值被任意嵌套,而不仅仅是像你的那样嵌套两个级别.然后写:

luaValue :: GenParser Char st LuaValue
luaValue = (LuaString <$> identifier)
       <|> (LuaList <$> between (string "{") (string "}") (sepBy (string ",") luaValue))
Run Code Online (Sandbox Code Playgroud)

这是luaValue 解析器.那你只需要写:

binding :: GenParser Char st Binding
content :: GenParser Char st [Binding]
Run Code Online (Sandbox Code Playgroud)

你会拥有它.使用准确表示可能性的数据类型非常重要.