1

我正在尝试使用 parsec 库在 haskell 中实现语法,但我遇到了预期的问题。语法中定义的实际类型,我知道我的问题的答案无疑是简单/显而易见的,但可惜有些东西我不明白......

以下是数据声明的摘录(应该足以诊断):

data Expr1 = SeqOfExpr1 [Expr1]
            | Lambda Expr8 Expr1
            | List Expr2 Expr1
            | If Expr2 Expr1 Expr1
            | Expr2
              deriving (Show)

data Expr2 =  SeqOfExpr3 [Expr3]
              deriving (Show)

data Expr3 =  SeqOfExpr4 [Expr4]
              deriving (Show)
 ----------------------------Redundant Code Omitted------------------------------
expr1 :: Parser Expr1   
expr1 = declaration
      <|> list
      <|> ifStmt
      <|> expr2

declaration :: Parser Expr1
declaration =
    do  reservedOp "\\"
        var <- name
        reservedOp "->"
        expr <- expr1
        return $ Lambda var expr

list :: Parser Expr1    
list =
    do exprA <- expr2
       reservedOp ":"
       exprB <- expr1
       return $ List exprA exprB

现在还有更多表达式的数据声明,直到 Expr8,但它们与 expr2 -> expr3 大致相同,它们之间的不同之处在于它们的分隔方式,例如 Expr3 由“||”分隔,Expr4 由“&&”等分隔。

我遇到的问题之一(如果解决了应该为我提供解决其余问题的想法):

List 值构造函数返回一个导致冲突的 Expr1:

Couldn't match expected type `Expr2' with actual type `Expr1'
In the first argument of `List', namely `exprA'
In the second argument of `($)', namely `List exprA exprB'
In a stmt of a 'do' block: return $ List exprA exprB

我认为这是因为我在 Expr1 中使用 Expr2 作为值声明,但我不确定如何更正语法以解决此问题。

提前感谢您的帮助!

肖恩

4

1 回答 1

5

data Expr1中,您有一个空构造函数Expr2。我怀疑你的意思是这样的

data Expr1 =
           ...
           | Foo Expr2

包装一个Expr2.

无论如何,按照

expr1 :: Parser Expr1   
expr1 = declaration
      <|> list
      <|> ifStmt
      <|> expr2

编译器推断expr2 :: Parser Expr1,但是当你尝试

list :: Parser Expr1    
list =
    do exprA <- expr2
       reservedOp ":"
       exprB <- expr1
       return $ List exprA exprB

List方法的类型exprA必须是Expr2,但expr2编译器知道 的类型exprA :: Expr1

所以你可能需要换expr2list

list = ...
     <|> fmap Foo expr2

如果您更改 的定义Expr1以包含Foo构造函数来包装Expr2.

于 2013-03-15T16:00:17.620 回答