类型树应为类型类Eq的实例

时间:2019-11-19 07:56:02

标签: haskell

我具有以下数据结构,并希望它成为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”的(可见)方法

2 个答案:

答案 0 :(得分:9)

这里有两个问题:

  1. 您没有指定Tree n l成为实例的类型类型;和
  2. 为了检查是否具有给定的定义,nl都必须是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,因为它们确实有所不同。