The problem in your case is not Int
but e
. The Coverage Condition is documented in GHC's manual Sect. 7.6.3.2. Relaxed rules for instance contexts and says:
The Coverage Condition. For each functional dependency, tvsleft -> tvsright, of the class, every type variable in S(tvsright) must appear in S(tvsleft), where S is the substitution mapping each type variable in the class declaration to the corresponding type in the instance declaration.
What does it mean in practise? In your case, your functional dependency says g -> n e
, which means that for each instance the types denoted by n
and e
are unique for the type denoted by g
. Now let's say you're defining an instance
instance Graph SomeTypeG SomeTypeN SomeTypeE where
...
The coverage condition says that any type variable appearing in SomeTypeE
or SomeTypeN
must appear in SomeTypeG
. What happens if it's not satisfied? Let's suppose a type variable a
appears in SomeTypeE
but not in SomeTypeG
. Then for fixed SomeTypeG
we would have an infinite number of possible instances by substituting different types for a
.
In your case
instance Graph g Int e where
...
e
is such a type variable, so by the Coverage Condition it must appear in g
, which is not true. Because it doesn't appear there, your definition would imply that Graph g Int Int
is an instances, Graph g Int (Maybe Char)
is another instance, etc., contradicting the functional dependency that requires that there is precisely one.
If you had defined something like
instance Graph g Int Char where
then it would be OK, as there are no type variables in Int
and Char
. Another valid instance could be
instance Graph (g2 e) Int e where
where g2
is now of kind * -> *
. In this case, e
appears in g2 e
, which satisfies the Coverage Condition, and indeed, e
is always uniquely determined from g2 e
.