Weird Undecidable Instances Bug

Martin Sulzmann sulzmann at comp.nus.edu.sg
Tue Sep 9 22:08:48 EDT 2003


 > original, "g" is actually a method in a class, and its definition is in 
 > an instance declaration. Its type is actually given, not annotated. For 
 > instance:
 > 

Ah, g is meant to be a method. Well, ...

 > -- ghc -fglasgow-exts -fallow-undecidable-instances -c WeirdInsts.hs
 > module WeirdInsts where
 > 	{
 > 	data T r = MkT;
 > 
 > 	class C t;
 > 
 > 	class D b t;
 > 
 > 	instance (C (T r)) => D b (T r); -- (1)
 > 
 > 	class F a b | a -> b;
 > 
 > 	f :: (F a b,D b t) => (a,t);
 > 	f = undefined;
 > 
 > 	class G t where
 > 		{
 > 		g :: forall a b. (F a b,D b t) => (a,t);
 > 		};
 > 
 > 	instance G (T r) where
 > 		{
 > 		g = f;
 > 		};
 > 	}
 > 
 > This exhibits the same behaviour.

... not quite. Cause we never can improve class declarations.

The short answer is, the above code won't type check in
a compilation-based evidence translation scheme. 
(There are no issues with decidable inference etc.)

Reason:

g's method declaration (i.e. annotation) is too general.
When type checking the instance, we need to check for

(F a' b',D b' t') => (a',t')

 "subsumes"

(F a b,D b (T r)) => (a,t)

(foralls are implicit)

In a compilation-based evidence translation scheme this check fails.
(BTW, there were similar problems mentioned when trying to define Monad2
instances some time ago on Haskell mail).

There are two solutions:

(1)
In an interpreter-based evidence translation scheme this
check would succeed. (i.e. we only
construct evidence at run-time, though this requires to pass around
run-time type information, see "A Theory of Overloading", journal
version, for details
http://www.comp.nus.edu.sg/~sulzmann/chr/publications.html)

(2) 
We need to find a different encoding. In essence, we need to give
up the class declaration. 

That is, we first generate

class G a where g :: a

instance (F a b, D b (T r)) => G (a, T r) where
   g = f

however, this won't work either, same problem as before.
Additionally, we need to improve
the instance (an instance is nothing else than a type annotation).
Finally, the following works

class G a where g :: a
instance (F a b, C (T r)) => G (a, T r) where
    g = f

Martin




More information about the Glasgow-haskell-bugs mailing list