incoherent instance selection when it should be still coherent

Simon Peyton-Jones simonpj at microsoft.com
Tue Jul 25 08:44:42 EDT 2006


It's clear that the type checker cannot do better, because in 
	uuh (Wrap x) (Wrap y) = bar x y
the call to 'bar' can use *only* evidence stored in the Wrap
constructor.   Previously GHC gave an error message at this point, but
some collection of users persuaded me that the behaviour below is the
"right" one.  As you say, it's not altogether clear!

Simon

| -----Original Message-----
| From: glasgow-haskell-bugs-bounces at haskell.org
[mailto:glasgow-haskell-bugs-bounces at haskell.org]
| On Behalf Of Ralf Lammel
| Sent: 24 July 2006 09:53
| To: glasgow-haskell-bugs at haskell.org
| Subject: FW: incoherent instance selection when it should be still
coherent
| 
| Repro contained in forwarded email.
| 
| Here is a bit more reasoning. I guess *always* selecting the generic
| instance is really incoherent, and then best called a bug. Since more
| specific instance selection does not make sense w/o violating the
| contract of existential types, I also feel like concluding that the
| program must not typecheck in the first place. I do agree that
| "-fallow-incoherent-instances" could admit this program, if the option
| was chosen (even though I generally fail to understand the use of this
| option anyway :-).
| 
| Thanks,
| Ralf
| 
| -----Original Message-----
| From: Ralf Lammel
| Sent: Friday, July 21, 2006 5:37 PM
| To: 'haskell-cafe at haskell.org'
| Subject: incoherent instance selection when it should be still
coherent
| 
| The following pain is sort of ghc (6.4.2) specific.
| (The same behavior is achievable with hugs -98 +O which is Ok in so
far
| that +O (as opposed to +o) is not strongly supposed to be coherent.)
| 
| Note the following GHC options preceding the code.
| They do not contain -fallow-incoherent-instances.
| 
| ---------------------------------------------------------
| 
| {-# OPTIONS -fglasgow-exts #-}
| 
| {-# OPTIONS -fallow-undecidable-instances #-}
| 
| {-# OPTIONS -fallow-overlapping-instances #-}
| 
| 
| -- A single parameter class with two silly instances
| 
| class Foo x where foo :: x -> (); foo = const ()
| 
| instance Foo ()
| 
| instance Foo Bool
| 
| 
| -- A two-parameter class with a generic and a non-generic instance
| 
| class (Foo x, Foo y) => Bar x y where bar :: x -> y -> String
| 
| instance (Foo x, Foo y) => Bar x y where bar _ _ = "generic instance"
| 
| instance Foo z => Bar () z where bar _ _ = "non-generic instance"
| 
| 
| -- An existential wrapper around foos
| 
| data Wrap = forall x. Foo x => Wrap x
| 
| 
| -- A wrapper-based variation on the type-class member bar
| 
| uuh :: Wrap -> Wrap -> String
| 
| uuh (Wrap x) (Wrap y) = bar x y
| 
| 
| -- Let's try all unwrapped and wrapped combinations of bar and uuh
| 
| t1 = ()
| 
| t2 = True
| 
| w1 = Wrap t1
| 
| w2 = Wrap t2
| 
| main = do
|           print $ bar t1 t1
|           print $ uuh w1 w1 -- uuh!
|           print $ bar t1 t2
|           print $ uuh w1 w2 -- uuh!
|           print $ bar t2 t1
|           print $ uuh w2 w1
|           print $ bar t2 t2
|           print $ uuh w2 w2
| 
| --------------------------------------------------------
| 
| We get:
| 
| {-
| 
| "non-generic instance"
| "generic instance"
| "non-generic instance"
| "generic instance"
| "generic instance"
| "generic instance"
| "generic instance"
| "generic instance"
| 
| -}
| 
| This means that the generic instance is consistently chosen by uuh.
| This is clearly incoherent.
| I would also complain that uuh type-checks in the first place.
| Opinions?
| 
| Regards,
| Ralf
| 
| _______________________________________________
| Glasgow-haskell-bugs mailing list
| Glasgow-haskell-bugs at haskell.org
| http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs



More information about the Glasgow-haskell-bugs mailing list