我具有以下数据结构,并希望它成为Eq类型类的实例。
data Tree n l
= Node n (Tree n l) (Tree n l)
| Leaf l
我试图通过以下方式做到
instance Eq => (Tree n l) where
(Node a b c) == (Node d e f) = a == d
(Leaf a) == (Leaf b) = a == b
但是有一条错误消息
“ ==”不是类“ Tree”的(可见)方法
答案 0 :(得分:9)
这里有两个问题:
Tree n l
成为实例的类型类型;和n
和l
都必须是Eq
类型类实例的类型。因此,您可以通过以下方式实现此目标:
instance (Eq n, Eq l) => Eq (Tree n l) where
(Node a b c) == (Node d e f) = a == d
(Leaf a) == (Leaf b) = a == b
请注意,它现在可以编译,但是仍然存在问题:如果您检查Node … … …
是否等于Leaf …
,它将引发错误,反之亦然。您可以为此添加一条附加规则:
instance (Eq n, Eq l) => Eq (Tree n l) where
(Node a b c) == (Node d e f) = a == d
(Leaf a) == (Leaf b) = a == b
_ == _ = False
但是,从它们包装相同的值开始,您将在这里将两个Node … … …
视为相同。因此,您不必关注子树。为了解决此问题,您需要执行递归。我把它留作练习。
答案 1 :(得分:4)
我不确定您是否确实希望对树进行平等检查。
让我们
a = Node 2 (Leaf 1) (Leaf 2)
b = Node 2 (Leaf 100) (Leaf 200)
对于这样的两棵树,您将得到a == b
作为True
,因为对Node
的比较仅比较该节点中的值,但是子树被忽略。您甚至可以像这样定义支票的那一部分
(Node a _ _) == (Node d _ _) = a == d
表明您忽略了子树。
也许这是理想的行为,但我认为,更正确的相等性检查应如下所示:
(Node x lx rx) == (Node y ly ry) = x == y && lx == ly && rx == ry
这不仅会检查节点的值,而且还会递归地检查子树,因此a == b
现在会给您False
,因为它们确实有所不同。