如果我有:
data Container a = Node a | End a | Container a
Run Code Online (Sandbox Code Playgroud)
如果我想编写一个可以查看Container的元素列表并执行列表差异的函数,我该怎么做才能明确告诉编译器这个抽象数据类型允许相等?
我以为会是:
compare::Eq (Container a) => Container a -> Container a -> Bool
compare a b
| a == b = True
| a /= b = False
Run Code Online (Sandbox Code Playgroud)
但它抱怨Eq声明不正确,因为它无法推断(Eq(容器a))因使用'=='而产生
编辑似乎在我的抽象数据类型中导出(Eq)是允许这种情况的唯一方法.有人可以确认一下吗?
包含导出(Eq)后的EDIT2:
test:: [Container a] -> Container a -> Bool
test list element = elem element list
Run Code Online (Sandbox Code Playgroud)
"没有(Eq a)的实例"
告知这样的情况下的编译器最简单的方法是使用一个deriving条款.在这种情况下,
data Container a = Node a | End a | Container a deriving (Eq)
Run Code Online (Sandbox Code Playgroud)
也可以Eq手工给出一个实例,例如下面说如果a 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
Run Code Online (Sandbox Code Playgroud)
这与给出的定义相同deriving,因此没有必要像以前那样输入定义,但如果想要更复杂的定义,Eq则必须做类似的定义.
一旦有了Eq容器实例,你就可以写:
compare :: Eq a => Container a -> Container a -> Bool
compare a b | a == b = True
| a /= b = False
Run Code Online (Sandbox Code Playgroud)
(关于这个功能的两件事:它实际上完全没有意义,因为它是相同的(==),并且应该使用它otherwise作为守卫中的最后一个选择.)
这些基本上只是两个选项.虽然有第三种方法,它基本上是两者的结合:使用GHC扩展StandaloneDeriving.
deriving instance Eq a => Eq (Container a)
Run Code Online (Sandbox Code Playgroud)