我正在尝试使用parsec库在haskell中实现语法,但是我遇到了预期的Vs问题。语法中定义的实际类型,我知道我的问题的答案无疑是简单/明显的,但是有一些我不理解的东西......
接下来是数据声明的摘录(应该足以诊断):
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非常相似 - &gt; expr3它们之间的区别在于它们是如何分隔的,例如: Expr3由“||”分隔,Expr4由“&amp;&amp;”分隔。等
我遇到的一个问题(如果解决这个问题应该让我想到解决剩下的问题):
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作为值声明,但我不确定如何纠正语法来解决这个问题。
提前感谢您的帮助!
肖恩
答案 0 :(得分: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
。
所以你可能需要将expr2
包裹在list
,
list = ...
<|> fmap Foo expr2
如果您更改Expr1
的定义以包含Foo
构造函数来包装Expr2
。