Need help understanding the Coverage Condition

Bertram Felgenhauer bertram.felgenhauer at
Wed Jul 4 11:23:04 EDT 2007

Philip K.F. H??lzenspies wrote:
> {- begin -}
> {-# OPTIONS -fglasgow-exts #-}
> data Z    -- Zero
> data S x  -- Successor of x
> class Add a b c | a b -> c
> instance Add Z q q
> instance Add p q r => (S p) q (S r)
> {- end -}


> The coverage condition. For each functional dependency, tvc_left ->
> tvs_right, of the class, every type variable in S(tvs_right) must
> appear in S(tvs_left), where S is the substitution mapping each type
> variable in the class declaration to the corresponding type in the
> instance declaration.
> In my mind, in this case:
> tvs_left     = {a,b}
> tvs_right    = {c}
> S(tvs_left)  = {p,q}
> S(tvs_right) = {r}

> What "occur in" means (mappings of type variables occurring in
> mappings of other type variables), I really don't quite understand.
> The example in the manual under, viz:

It's subset check. S(tvs_right) must be a subset of S(tvs_left) which
is clearly not the case. The condition is sufficient (but not necessary)
to let type checking terminate.

> The suggested flag to "allow undecidable instances" is throwing me
> off, since it seems very unambiguously decidable to me.

Ambiguity is not the issue here, ensuring termination is.

The consequence of using -fundecidable-instances is that there is no
a priori guarantee that type checking will terminate. [*] If it does
terminate, the final result will be correct.



[*] In your particular example termination will probably be guaranteed
    by a structural property: In deriving

       Add (S x) y (S z)

    the compiler will look for an instance Add x y z where all three
    type terms are smaller. The nice thing about the coverage condition
    is save and can be checked easily per instance.

More information about the Glasgow-haskell-users mailing list