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
Could not unambiguously deduce (DShow [a])
from the context (DShow a)
The choice of (overlapping) instance declaration
depends on the instantiation of `a'
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:
Overlapping instances for DShow [a]
arising from a use of `dShows' at Serge.hs:14:23-34
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.
More information about the Glasgow-haskell-users