如果我有:
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)的实例”
答案 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