I used a type context in doing an instance declaration for a data type I made up.
data Set a = Insert a (Set a) | EmptySet
instance (Show a) => Show (Set a) where
show x = "{" ++ show' x ++ "}" where
show' (Insert x EmptySet) = show x
show' (Insert x xs) = show x ++ ", " ++ show' xs
instance Eq a => Eq (Set a) where
(Insert x xs) == (Insert y ys) = (x == y) && (xs == ys)
So now, I have to add the Eq type context to all of the functions I define that use my Set type, like so, or I get a type error:
memberSet::Eq a =>a->Set a->Bool
memberSet _ EmptySet = False
memberSet x (Insert y ys)
| x == y = True
| otherwise = memberSet x ys
subSet::Eq a=>Set a->Set a->Bool
subSet EmptySet _ = True
subSet (Insert a as) bs
| memberSet a bs = subSet as bs
| otherwise = False
The error I get looks like:
No instance for (Eq a)
arising from a use of `=='
In the expression: (x == y)
In a stmt of a pattern guard for
an equation for `memberSet':
(x == y)
In an equation for `memberSet':
memberSet x (Insert y ys)
| (x == y) = True
| otherwise = memberSet x ys
Failed, modules loaded: none.
What does this even mean? Why do I get this error? I figured that once I did the instance declaration, Haskell would be able to automatically verify that the things being compared by “==” in my functions “memberSet” and “subSet” would automatically be checked to be instances of “Eq?”
Edit for clarity:
My issue is that I don’t understand why the type contexts are necessary on “memberSet” and “subSet.” If I remove them like so, it doesn’t compile.
memberSet::a->Set a->Bool
memberSet _ EmptySet = False
memberSet x (Insert y ys)
| x == y = True
| otherwise = memberSet x ys
subSet::Set a->Set a->Bool
subSet EmptySet _ = True
subSet (Insert a as) bs
| memberSet a bs = subSet as bs
| otherwise = False
What your instance declaration says is that
Set ais an instance ofEqwheneverais. Whether or notais, in fact, an instance ofEqis another matter entirely; this merely allows you to compare twoSets with==, while inmemberSetyou’re only comparing elements.Consider the type
Integer -> Integer. This is not an instance ofEqfor reasons that should be obvious. How would you expectmemberSetto work if theSetcontains elements of that type?I wonder if what you were hoping to accomplish here is ensuring that only
Sets with an element type that’s an instance ofEqcan be created. If so, that’s a very different problem, but also mostly unnecessary–leaving theEqconstraint on the functions usingSets serves the same purpose in the end.Why not take a look at the standard
Data.Setmodule? Note that most of its functions operating on sets have anOrdconstraint, reflecting the fact that the internal representation used is a binary search tree.