如何在不派生的情况下实例化 Eq



对不起,我的英语很差。标题可能无法解释我的意思。

在数据树中,Tree定义如下:

-- | Multi-way trees, also known as /rose trees/.
data Tree a = Node {
rootLabel :: a,         -- ^ label value
subForest :: Forest a   -- ^ zero or more child trees
}
#ifdef __GLASGOW_HASKELL__
deriving (Eq, Read, Show, Data)
#else
deriving (Eq, Read, Show)
#endif

它使用deriving实例==/=Tree(日期)。

我可以在不派生的情况下做同样的事情吗? 我尝试这样的事情:

data Test a = Test a
instance Eq Test where
(Test a) == (Test b) = a == b

但它抛出了一个例外。我认为原因是关于 a 和 b 的类型。

如果我想使用==为我的数据定义自定义操作,我该怎么办。

我知道我可以将Functorfmap一起使用。但我想在a = Test 1b = Test "a"的地方使用像a == b这样的==。可能吗?

您可以在TreeTest定义Eqinstance,但您的定义存在一些问题。

instance Eq Test where
(Test a) == (Test b) = a == b

第一个是Eq Test中的Test仍然是参数化的。实际上,您编写了data Testa= ...,因此这意味着存在一个类型参数。因此,您可以使用以下命令指定它:

instance Eq(Testa)where
(Test y) == (Test x) = x == y

现在,您指定Eq是在Test a上定义的。我还将ab重命名为xy。这不是必需的,因为"类型世界"和"可变世界"是分开的,但它使事情变得不那么混乱。

但是仍然存在一个问题:您称x == y.但是没有关a本身就是Eq的实例。因此,您需要使用类型约束

instanceEq a =>Eq (Test a) where
(Test y) == (Test x) = x == y

现在,如果Test a也是Eq的实例,则指定是Eq的实例a

因此,对于Tree数据结构,Eqinstance应如下所示:

instance (Eq a, Eq (Forest a)) => Eq (Tree a) where
(Tree x1 y1) == (Tree x2 y2) = x1 == x2 && y1 == y2

(当然,我在这里定义了两棵树是如何相等的,您可能希望以(语义上)不同的方式定义两棵树的相等性,因此您本身不应该复制粘贴此代码)。

请注意,就像@luqui所说的那样,如果type Forest a = [Tree a],那么您可以省略Eq (Forest a)类型约束,因为instance Eq a => Eq [a]成立。所以在这种情况下是:

instance Eq a => Eq (Tree a) where
(Tree x1 y1) == (Tree x2 y2) = x1 == x2 && y1 == y2

最新更新