抽象数据类型的平等性

Let*_*thi 1 haskell

如果我有:

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)的实例"

huo*_*uon 6

告知这样的情况下的编译器最简单的方法是使用一个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)