抽象数据类型的平等性

时间:2012-09-08 13:15:04

标签: haskell

如果我有:

data Container a = Node a | End a | Container a

如果我想编写一个可以查看Container a元素列表并执行列表差异的函数,我该怎么做才能明确告诉编译器这个抽象数据类型允许相等?

我以为会:

compare::Eq (Container a) => Container a -> Container a -> Bool
compare a b
           | a == b = True
           | a /= b = False

但它抱怨Eq声明不正确,因为它无法推断(Eq(容器a))因使用'=='而引起

编辑它似乎在我的抽象数据类型中导出(Eq)是允许这种情况的唯一方法。有人可以确认一下吗?

包括导出(Eq)之后的EDIT2:

test:: [Container a] -> Container a -> Bool
test list element = elem element list
  

“没有(Eq a)的实例”

2 个答案:

答案 0 :(得分:6)

通知编译器这类实例的最简单方法是使用a deriving clause。在这种情况下,

data Container a = Node a | End a | Container a deriving (Eq)

也可以手动提供Eq个实例,例如以下说明如果Container包含可以测试相等性的元素,那么Container也可以进行相等性测试。

instance Eq a => Eq (Container a) where
    (Node a)      == (Node b)      = a == b
    (End a)       == (End b)       = a == b
    (Container a) == (Container b) = a == b
    _             == _             = False

这与deriving给出的定义相同,因此没有必要像以前那样输入定义,但如果想要更复杂的Eq定义,则必须做类似的东西。

一旦你有一个Eq容器实例,你就可以写:

compare :: Eq a => Container a -> Container a -> Bool
compare a b | a == b = True
            | a /= b = False

(关于这个功能的两件事:它实际上完全没有意义,因为它与(==)相同,并且应该使用otherwise作为守卫中的最后一个选择。)

这些基本上只是两个选项。虽然有第三种方法,基本上是两种方法的组合:使用GHC扩展StandaloneDeriving

deriving instance Eq a => Eq (Container a)

答案 1 :(得分:1)

至于“没有(Eq a)的实例” - 你的类型是错误的。

test:: [Container a] -> Container a -> Bool

该类型表示您可以比较任何错误的容器。您当前的实例仅适用于具有可比元素的容器。所以你应该写

test:: Eq a => [Container a] -> Container a -> Bool