[[PageOutline]]
= Overlapping Instances =
== Brief Explanation ==
Instances are allowed to overlap, as long as there is a most specific one in any case.
Contexts of instances play no part in testing for overlapping.
== References ==
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#instance-overlap Overlapping instances] in the GHC User's Guide.
* [http://cvs.haskell.org/Hugs/pages/users_guide/class-extensions.html#OVERLAPPING-INSTANCES Overlapping instances] in the Hugs User's Guide.
* IncoherentInstances
== Tickets ==
[[TicketQuery(description~=OverlappingInstances)]]
== Pros ==
* useful on occasion.
== Cons ==
* Makes it very easy for incorrect programs to still typecheck.
* Can cause confusing error messages.
* A program that type checks can have its meaning changed by adding an instance declaration.
* Similarly adding "import M()" can silently change the meaning of a program (by changing which instances are visible.
* When exactly is overlap permitted? Is this ok?
{{{
instance C a Int
instance C Bool b
}}}
* The language description would need to be a lot more specific about exactly where context reduction takes place.
* Can sometimes be simulated with the extra-method trick used in the Show class of the Prelude for showing lists of characters differently than lists of other things.
== Variations ==
Hugs compares instance declarations, while GHC delays tests until the instances are used.
* Hugs considers instances to be overlapping if they are unifiable, e.g.
{{{
instance C Int b
instance C a Bool
}}}
Similarly the "most specific" test is applied to instances (though not as cleverly as it could be).
* GHC only requires `-fallow-overlapping-instances` if it needs to resolve a constraint that overlaps with both, e.g. `C Int Char` is fine, but `C a Bool` overlaps.
Similarly a most specific instance is needed only for constraints encountered in type checking.
An alternative to what GHC implements would be to declare whether a class may be overlapping on a class by class basis, perhaps with something like
{{{
class overlapping Foo a where
...
}}}