"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

Reply via email to