Skip to content

Instantiation doesn't look through dictionaries

The bug is simple to state in terms of GHC's implementation: topInstantiate does not look past dictionaries. Thus a type like forall a. C a => forall b. ... only gets its a instantiated, not its b. This can be witnessed is some ugly-looking code:

data Rec a b = MkRec { x :: Bool }

class C a where
  r :: Rec a b

instance C Int where
  r = MkRec { x = True }

foo :: Rec Int Bool
foo = r { x = False }

This fails with

/Users/rae/temp/Bug.hs:10:7: error:
    • Ambiguous type variable ‘a0’ arising from a use of ‘r’
      prevents the constraint ‘(C a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instance exist:
        instance C Int -- Defined at /Users/rae/temp/Bug.hs:6:10
    • In the expression: r
      In the expression: r {x = False}
      In an equation for ‘foo’: foo = r {x = False}

I have no idea why it's an ambiguous-variable error, but let's not get distracted by that. The problem is that GHC does not instantiate r vigorously enough to notice that it's a record. The solution is straightforward: have topInstantiate be recursive, looking past dictionaries. topInstantiate is used in other places, too, and perhaps there are other similar bugs to find.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information