The fundamental problem is that the type class instance resolution machinery doesn't backtrack. So if you write instance Shape a => Eq a
, then whenever the compiler wants to find an Eq
instance, the compiler will try to use this instance and for most types it won't work out because they aren't instances of Shape
.
If you still really want to do this, you can add
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
at the top of your source file.
You can also work round some of the problems described above by also adding OverlappingInstances
to the set of LANGUAGE pragmas, but you will still have a global instance for Eq
that will cause significant confusion elsewhere in your program.
It's much better to just enumerate the instances you really need, even if it seems ugly. You can keep the boilerplate to a minimum with a helper function, e.g.
x `areaEq` y = area x == area y
and then
instance Eq Circle where
(==) = areaEq
etc.