[Haskell] A problem with overlapping instances and super-classes
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.
*B> :t f
f :: (Name [t]) => t -> String
*B> :t f
f :: (Name t) => t -> String
More information about the Haskell