Overlapping instance declarations
Simon Peyton-Jones
simonpj at microsoft.com
Fri Sep 19 05:26:01 EDT 2008
| 2. But in several places DoCon has parasitic additions
| (similar to the below MulSemigroup (Fraction a))
| to the context for overlapping instances.
| These places are marked in the docon-2.12-pre source with
| 'overlaps in ghc'.
| I would like to cancel them, similar as we now cancel the above
| MulSemigroup (Fraction a) in the context.
| But ghc-6.9.20080910 does not allow this.
| So, I wonder: what is the difference?
No you can't cancel them! Consider
class Foo a where
fop :: a->a
instance Foo [a] where ...
instance Foo [Int] where ..
class Bar a where
bop :: a -> a
instance Bar [a] where
bop = fop
In the Bar [a] instance, we get a constraint (Foo [a]). It's wrong to commit to the Foo [a] instance, because if you are ultimately building a Bar [Int] instance you want the Foo [Int] instance of fop!
The Right Thing is to add (Foo [a]) to the context of the Bar instance thus
instance Foo [a] => Bar [a] where
bop = fop
I'll expand the user manual (in the section about overlapping instances) to cover this point.
The other situation that DoCon contains is more like this:
class C a where { op1,op2 :: a -> a }
instance C [Int] where...
instance C a => C [a] where
op1 x = op2 x ++ op2 x
op2 x = ...
In the C [a] instance you'll see that op1 calls op2, thereby giving rise to a C [a] constraint. I *originally thought* that the same reasoning applied as above, so we should reject the program. But applying the solution I describe above would give
instance C [a], C a => C [a] where ..
which is silly. Here the Right Thing is to satisfy the C [a] constraint "locally", without worrying about the overlap. This is justified because we'll only be *in* the code for op1 in the C [a] instance if we know that 'a' does not match Int.
Thanks for bringing this up.
Simon
More information about the Glasgow-haskell-users
mailing list