如何实例化Eq而无需派生 [英] how to instance Eq without deriving
问题描述
在Data.Tree中, Tree
定义如下:
- |多路树,也被称为/玫瑰树/。
数据树a =节点{
rootLabel :: a, - ^标签值
subForest :: Forest a - ^零个或多个子树
}
#ifdef __GLASGOW_HASKELL__
导出(Eq,Read,Show,Data)
#else
派生(Eq,Read,Show)
#endif
它使用派生
来实例 ==
和 / =
用于树
(日期)。
我可以在不派生的情况下做同样的事情吗?
我尝试这样的事情:
data测试a =测试
实例Eq测试其中
(Test a)==(Test b)= a == b
但它抛出例外。我认为原因是关于a和b的类型。
我可以做什么,无论我是否想用 ==
。
我知道我可以用 Functor
和 fmap
来做到这一点。但是我想用 ==
,比如 a == b
其中 a = Test 1
和 b =测试a
。您可以定义一个实例
是否有可能?
Eq
上的树或测试
,但是你的定义存在一些问题。 instance Eq Test其中
(Test a)==(Test b)= a == b
第一个是<$ c在 Eq Test
中,$ c> Test
仍然是参数化的。事实上,你写了数据Test a = ...
,这意味着有一个类型参数。所以你可以指定它: 实例公式(测试 a)其中
(Test y)==(Test x)= x == y
Eq
定义在 Test a
之上。我还将 a
和 b
更名为 x
和ý
。这是没有必要的,因为类型世界和变量世界是分开的,但它使事情变得更加混乱。但是仍然存在一个问题: code> x == y 。但不存在 a
本身就是 Eq
的实例。因此,您需要使用类型约束:
instance 等式a => Eq(Test a)其中
(Test y)==(Test x)= x == y
现在您指定 Test a
是 Eq
的一个实例if a
也是 Eq
的一个实例。
您的 Tree
数据结构, Eq
的实例
应该看起来像:
instance(Eq a,Eq(Forest a))=>公式(树a)其中
(树x1 y1)==(树x2 y2)= x1 == x2&& y1 == y2
(当然,我在这里定义了 等同的,你可能希望以(语义)不同的方式定义两棵树上的平等,所以你不应该本身复制粘贴这段代码。)
请注意 - 像 @ luqui 说 - 如果键入Forest a = [Tree a]
,那么您可以省略 Eq Forest a)类型约束,因为
instance Eq a =>>公式[a]
成立。所以在这种情况下,它是:
instance Eq a =>公式(树a)其中
(树x1 y1)==(树x2 y2)= x1 == x2&& y1 == y2
Sorry about my poor English. The title may not explain what I mean.
In Data.Tree, Tree
is defined as following:
-- | 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
It uses deriving
to instance ==
and /=
for Tree
(date).
Could I do the same thing without deriving? I try things like this:
data Test a = Test a
instance Eq Test where
(Test a) == (Test b) = a == b
But It throws an exception. I think the reason is about the types of a and b.
And what can I do whether I want to define a custom action for my data with ==
.
I know I can use Functor
with fmap
to do it. But I want to use ==
like a == b
where a = Test 1
and b = Test "a"
. Is it possible?
You can define an instance
of Eq
on Tree
or Test
, but there are some problems with your definition.
instance Eq Test where
(Test a) == (Test b) = a == b
A first one is that Test
in Eq Test
is still parametrized. Indeed, you wrote data Test a = ...
so that means that there is a type parameter. So you can specify it with:
instance Eq (Test a) where
(Test y) == (Test x) = x == y
Now you thus specified that Eq
is defined over Test a
. I also renamed a
and b
to x
and y
. This is not necessary since the "type world" and "variable world" are separated, but it makes things less confusing.
But there is still a problem: you call x == y
. But there is no guantee that a
itself is an instance of Eq
. You thus need to work with a type constraint:
instance Eq a => Eq (Test a) where
(Test y) == (Test x) = x == y
Now you specify that Test a
is an instance of Eq
if a
is an instance of Eq
as well.
For your Tree
data structure, the instance
of Eq
should thus look like:
instance (Eq a, Eq (Forest a)) => Eq (Tree a) where
(Tree x1 y1) == (Tree x2 y2) = x1 == x2 && y1 == y2
(of course I here define how two trees are equal, it is possible that you want to define the equality over two trees in a (semantically) different way, so you should not per se copy paste this code).
Note that - like @luqui says - if type Forest a = [Tree a]
, then you can omit the Eq (Forest a)
type constraint since instance Eq a => Eq [a]
holds. So in that case it is:
instance Eq a => Eq (Tree a) where
(Tree x1 y1) == (Tree x2 y2) = x1 == x2 && y1 == y2
这篇关于如何实例化Eq而无需派生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!