问题描述
对不起我的英文不好。标题可能无法解释我的意思。在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
(当然,我在这里定义了 等同的,你可能希望以(语义)不同的方式定义两棵树上的平等,所以你不应该本身复制粘贴这段代码。)
请注意 - 像说 - 如果键入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而无需派生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!