Reputation: 365
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?
Upvotes: 3
Views: 2142
Reputation: 476574
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
Upvotes: 9