haskell中的语法问题与数据定义有关

Sea*_*ean 1 grammar haskell parsec

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

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

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
Run Code Online (Sandbox Code Playgroud)

现在还有针对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
Run Code Online (Sandbox Code Playgroud)

我认为这是因为我在Expr1中使用Expr2作为值声明,但我不确定如何纠正语法来解决这个问题.

在此先感谢您的帮助!

肖恩

Dan*_*her 5

data Expr1,你有一个无效的构造函数Expr2.我怀疑你的意思是这样的

data Expr1 =
           ...
           | Foo Expr2
Run Code Online (Sandbox Code Playgroud)

包裹一个Expr2.

无论如何,按照

expr1 :: Parser Expr1   
expr1 = declaration
      <|> list
      <|> ifStmt
      <|> expr2
Run Code Online (Sandbox Code Playgroud)

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

list :: Parser Expr1    
list =
    do exprA <- expr2
       reservedOp ":"
       exprB <- expr1
       return $ List exprA exprB
Run Code Online (Sandbox Code Playgroud)

List均值的类型exprA必须是a Expr2,但是从expr2类型来看,编译器知道exprA :: Expr1.

所以,你可能需要包装expr2list,

list = ...
     <|> fmap Foo expr2
Run Code Online (Sandbox Code Playgroud)

如果你改变了Expr1包含一个Foo构造函数来包装的定义Expr2.