如何实例化Eq而无需派生 [英] how to instance Eq without deriving

查看:116
本文介绍了如何实例化Eq而无需派生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起我的英文不好。标题可能无法解释我的意思。

在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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆