问题
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?
回答1:
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
来源:https://stackoverflow.com/questions/43975200/how-to-instance-eq-without-deriving