Liberalising IncoherentInstances

AntC anthony_clayden at clear.net.nz
Mon Jul 29 03:33:08 CEST 2013


> Simon Peyton-Jones <simonpj <at> microsoft.com> writes:
> 
> I've realised that GHC's -XIncoherentInstances flag is,
> I think, over-conservative. 

Hi Simon, by coincidence I've just come across a very similar issue with 
overlapping instances and FunDeps (following-up some discussion with Oleg, 
MartinS, EdwardK).

Starting with:

    class C a b | a -> b where foo :: a -> b
    instance C [a] [a] where foo = id

    t1 = foo "a"     -- t1 :: [Char] -> [Char]

I then added:

    instance C [Char] [Char] where foo = id
                     -- more specific!
    t2 = foo "a"     -- t2 :: C [a] [a] => [a] -> [a]
                     -- more polymorphic!

My (probably subjective) experience is that somewhere around 2006 when 
Type Families started appearing, there were some subtle changes around 
overlaps. TF's seemed to be very pre-occupied with supporting 'coincident' 
(or confluent) _partial_ overlap.

(By partial overlap I mean: some substitutions match both instances, some 
only one, some only t'other. This seems to be the root of the issue with 
Joachim's post on ghc-devs.)

Partial overlaps are always going to be awkward for IncoherentInstances. 
With Type Families, you can always check that the result is confluent. But 
for class instances there's no such algebraic/semantic check possible.

It's easy to avoid partial overlaps: just define an instance for the mgu 
of the overlap; then both of the less-specific instances totally overlap 
it.

With the benefit of hindsight, I would have banned partial overlaps. IMO 
we could then validate class instance 'eagerly' at point of declaration 
(as Hugs does), rather than paying the penalty later with hazy/lazy 
instance selection woes.

I strenuously try to avoid needing IncoherentInstances. I've no objection 
to your proposed "liberalise a bit".


> 
> Incidentally, I think it'd be an improvement to localise the 
Overlapping/Incoherent flags to particular
> instance declarations, via pragmas, something like
> 	instance C [a] where
> 	  {-# ALLOW_OVERLAP #-}
> 	  op x = ....
> 
> Similarly {-# ALLOW_INCOHERENT #-}.   Having -XOverlappingInstances for 
the whole module is a bit crude.,
> and might be missed when looking at an instance.   How valuable would 
this be?
> 

+1
I strongly support localising these flags. Very seldom do I want 
Overlapping for every class in a module, and I'd rather the compiler told 
me if I inadvertently did overlap an instance.

Better still, can we do {-# DISALLOW_PARTIAL #-} ?






More information about the Glasgow-haskell-users mailing list