简体   繁体   中英

how to instance Eq without deriving

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 = ... so that means that there is a type parameter. = ...所以这意味着有一个类型参数。 So you can specify it with:

instance Eq Test  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 (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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM