抱歉我的英语不好。标题可能无法解释我的意思。
在Data.Tree中,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的类型。
如果我想使用==
为我的数据定义自定义操作,我该怎么办。
我知道我可以Functor
使用fmap
来执行此操作。但我希望==
使用a == b
a = Test 1
和b = Test "a"
。有可能吗?
答案 0 :(得分:9)
您可以在instance
或Eq
上定义Tree
Test
,但有一些问题用你的定义。
instance Eq Test where
(Test a) == (Test b) = a == b
第一个问题是Test
中的Eq Test
仍然是参数化的。实际上,您编写了data Test a = ...
,这意味着存在类型参数。所以你可以用:
instance Eq (Test a) where
(Test y) == (Test x) = x == y
现在您指定Eq
定义为Test a
。我还将a
和b
重命名为x
和y
。这不是必要的,因为“类型世界”和“变量世界”是分开的,但它使事情变得不那么混乱。
但仍有问题:你致电x == y
。但没有保证a
本身就是Eq
的实例。因此,您需要使用类型约束:
instance Eq a => Eq (Test a) where
(Test y) == (Test x) = x == y
现在您指定Test a
是Eq
的实例,如果 a
也是Eq
的实例。
对于您的Tree
数据结构,instance
的{{1}}应该如下所示:
Eq
(当然我在这里定义两个树是如何相同的,你可能希望以(语义)不同的方式定义两棵树的相等性,所以你不应该本身复制粘贴此代码。)
请注意 - 与@luqui一样 - 如果instance (Eq a, Eq (Forest a)) => Eq (Tree a) where
(Tree x1 y1) == (Tree x2 y2) = x1 == x2 && y1 == y2
,那么您可以省略 type Forest a = [Tree a]
类型约束,因为Eq (Forest a)
成立。所以在这种情况下它是:
instance Eq a => Eq [a]