[Haskell] A problem with overlapping instances and super-classes

Claus Reinke claus.reinke at talk21.com
Tue Jun 10 09:26:12 EDT 2008

>Yes indeed, this is one of those "well-known" (ie not at all well
>known, but folk lore) problems with overlapping instances, at least in
>programs where different instances can be in scope at different times.

I think these examples are subtly different (eg, some trip up Hugs as
well, some only GHC), and it would be nice to have a collection of such
folk lore. Currently, GHC's trac is probably the best approximation, but
it would be more useful to have a collection of examples interpreted
differently by different Haskell implementations.

1) Iavor's example exploits the special early treatment of superclass
  constraints to trigger an early commit (excluding later, more specific
  overlaps), and trips up both Hugs and GHC.

2) Simon's variation exploits explicit type signatures to trigger an
  early commit. As given, it trips up both Hugs and GHC, but if we
  remove the explicit type signature for f, Hugs recovers while GHC
  still misses the more specific instance (Simon: this seems to be a
  regression in 6.9 wrt to 6.6.1? [*]).

3) Simon's multiple instance example exploits GHC's late treatment 
  of overlap errors, only trips up GHC, and -in its Haskell 98, 
  no-overlapping-instances incarnation- is in direct violation of the
  language report (GHC trac ticket #2356)

Both 1 and 2 seem to be caused by a specific dictionary translation.
Haskell 98 requires an early superclass check, and does not need
to require that the superclass instance found for that check is the one
used at every point of use, because -in Haskell 98- there can be
only one such instance. 

For implementations supporting overlapping instances, it seems quite 
possible to use one superclass instance for the superclass constraint 
check, but another, more specific superclass instance for each actual 
use - just that the usual dictionary translation doesn't have that flexibility 
as it fixes the instance to use at the point of definition, where superclass 
constraint or explicit signature are checked.


    -- 6.6.1
    *B> :t f
    f :: (Name [t]) => t -> String

    -- 6.9.20080217
    *B> :t f
    f :: (Name t) => t -> String

More information about the Haskell mailing list