instance overlap

Simon Peyton-Jones simonpj at microsoft.com
Mon Jan 21 06:24:53 EST 2008


Serge, and others

| 1. Can you check what ghc-5.02.3 will report on the below small program
|    with DShow

I don't have ghc 5.02 to hand, but here's what 5.04.3 says about the code you give.

ghc-5.04.3 -fglasgow-exts -fallow-overlapping-instances -fallow-undecidable-instances Serge.hs

Serge.hs:14:
    Could not unambiguously deduce (DShow [a])
        from the context (DShow a)
    The choice of (overlapping) instance declaration
        depends on the instantiation of `a'
    Probable fix:
        Add (DShow [a]) to the type signature(s) for `f'
        Or add an instance declaration for (DShow [a])
    arising from use of `dShows' at Serge.hs:14
    In the definition of `f': dShows xs ""

| 2. When GHC fails to select an instance among overlapping ones, it is
|    often useful to report advice to the user: "consider adding such and
|    such instance class assertion to a type context".

In general it's quite hard to make suggestions that are never misleading.   In this case GHC does suggest something, but it's wrong!

GHC 6.08's message is this:

Serge.hs:14:23:
    Overlapping instances for DShow [a]
      arising from a use of `dShows' at Serge.hs:14:23-34
    Matching instances:
      instance [overlap ok] (DShow a) => DShow [a]
        -- Defined at Serge.hs:(7,0)-(9,45)
      instance [overlap ok] DShow String -- Defined at Serge.hs:11:0-42
    (The choice depends on the instantiation of `a'
     To pick the first instance above, use -fallow-incoherent-instances
     when compiling the other instance declarations)
    In the expression: dShows xs ""
    In the definition of `f': f xs = dShows xs ""

This is better, although it does not suggest adding (DShow [a]) to the context of f.  Adding that could perhaps be possible.

| 3. In my example with DShow, instance overlaps are really redundant.
|    I looked into  Prelude.Show, showList, and their usage in List and
|    [Char]. I added an analogue of showList, and now DShow does not need
|    overlapping instances.
|
| 4. But there are other situations, when it is much simpler for a
|    programmer to declare overlapping instances than to apply tricks with
|    additional class methods.

I don't know what you are actually suggesting here

| 5. What the GHC developers think on my suggestion below with the user
|    defined preference for overlapping instances?

I believe your suggestion is: where instances overlap, choose the most specific.

Yes, that's possible, and GHC does exactly that *unless* the answer to the match can be changed by instantiating a type variable.  Consider
        f :: DShow a => a -> String
If I need (DShow [a]) inside f, then you say, I guess, choose the DShow [a] instance even though there is a (DShow [Char]) instance.

But if I changed 'f' to give it a more specific type:
        f :: Char -> String
then we would choose the DShow [Char] instance instead.  So making the type signature more specific has changed the semantics of the program.


This is precisely what the flag -fallow-incoherent-instances does.  So you can get the behaviour you ask for by giving an extra flag.

Simon



More information about the Glasgow-haskell-users mailing list