"S.D.Mechveliani" wrote:
> Dear GHC,
>
> I fear, there is some hard bug in ghc-4.06.
> On the program
>
> main = let p = 5 :: Integer
> iI = eucIdeal "be" p [] [] [(p,1)]
> r1 = Rse 1 iI dZ
> dK = upGCDRing r1 eFM
> --upRing
> setK = snd $ baseSet r1 dK
> in putStr $ shows (osetCard setK) "\n"
>
> ghc-4.04 behaves correct,
> while ghc-4.06 prints "UnknownV" instead of "Fin 5".
>
> upGCDRing r1 eFM applies upRing r1 eFM and then adds to the
> result certain things.
> Replacing upGCDRing with upRing in the above `main' has to
> preserve the result. And ghc-4.06 does not preserve it.
>
> If you want to debug this, tell me to what address to send this bug
> project - 100-300 Kbyte.
I'll pass, but I suspect I know what the bug is.
Consider this little program:
class C a where c :: a
class C a => D a where d :: a
instance C Int where c = 17
instance D Int where d = 13
instance C a => C [a] where c = [c]
instance ({- C [a], -} D a) => D [a] where d = c
instance C [Int] where c = [37]
main = print (d :: [Int])
What do you think `main' prints (assuming we have overlapping instances, and
all that turned on)? Well, the instance for `D' at type `[a]' is defined to
be `c' at the same type, and we've got an instance of `C' at `[Int]', so the
answer is `[37]', right? (the generic `C [a]' instance shouldn't apply because
the `C [Int]' instance is more specific).
Ghc-4.04 gives `[37]', while ghc-4.06 gives `[17]', so 4.06 is wrong. That
was easy ;-) Let's just consult hugs for good measure. Wait - if I use old
hugs (pre-September99), I get `[17]', and stranger yet, if I use hugs98, it
doesn't even compile! What's going on!?
What hugs complains about is the `D [a]' instance decl.
ERROR "mj.hs" (line 10): Cannot build superclass instance
*** Instance : D [a]
*** Context supplied : D a
*** Required superclass : C [a]
You might wonder what hugs is complaining about. It's saying that you need to
add `C [a]' to the context of the `D [a]' instance (as appears in comments).
But there's that `C [a]' instance decl one line above that says that I can
reduce the need for a `C [a]' instance to the need for a `C a' instance, and
in this case, I already have the necessary `C a' instance (since we have `D a'
explicitly in the context, and `C' is a superclass of `D').
Unfortunately, the above reasoning indicates a premature commitment to the
generic `C [a]' instance. I.e., it prematurely rules out the more specific
instance `C [Int]'. This is the mistake that ghc-4.06 makes. The fix is to
add the context that hugs suggests (uncomment the `C [a]'), effectively
deferring the decision about which instance to use.
Now, interestingly enough, 4.04 has this same bug, but it's covered up in this
case by a little known `optimization' that was disabled in 4.06. Ghc-4.04
silently inserts any missing superclass context into an instance declaration.
In this case, it silently inserts the `C [a]', and everything happens to work
out.
So, what's the fix? I think hugs has it right (of course I do ;-). Here's
why. Let's try something else out with ghc-4.04. Let's add the following
line:
d' :: D a => [a]
d' = c
Everyone raise their hand who thinks that `d :: [Int]' should give a different
answer from `d' :: [Int]'. Well, in ghc-4.04, it does. The `optimization'
only applies to instance decls, not to regular bindings, giving inconsistent
behavior.
What hugs does is this: like GHC, the list of instances for a given class is
ordered, so that more specific instances come before more generic ones. For
example, the list might contain:
..., C Int, ..., C a, ...
When we go to look for a `C Int' instance we'll get that one first. But what
if we go looking for a `C b' (`b' is unconstrained)? We'll pass the `C Int'
instance, and keep going. But if `b' is unconstrained, then we don't know yet
if the more specific instance will eventually apply. GHC keeps going, and
matches on the generic `C a'. Hugs, on the other hand, at each step, checks
to see if there's a reverse match, and if so, aborts the search. This
prevents hugs from prematurely chosing a generic instance when a more specific
one may apply at some later point.
If y'all agree that GHC should match hugs on this, it's only about a 4 line
fix - I've tried it out already. On the other hand, I don't think that this
will make Sergey a happy camper. Many instance declarations need to be
tweaked. It's a tedious job, but straightforward.
--Jeff