Note [GND and ambiguity]
We make an effort to make the code generated through GND be robust w.r.t. ambiguous type variables. Here are a couple of examples to illustrate this: * In this example (from #15637), the class-bound type variable `a` is ambiguous in the type of `f`: class C a where f :: String -- f :: forall a. C a => String instance C () where f = "foo" newtype T = T () deriving C A naïve attempt and generating a C T instance would be: instance C T where f = coerce @String @String f This isn't going to typecheck, however, since GHC doesn't know what to instantiate the type variable `a` with in the call to `f` in the method body. (Note that `f :: forall a. String`!) To compensate for the possibility of ambiguity here, we explicitly instantiate `a` like so: instance C T where f = coerce @String @String (f @()) All better now. * In this example (adapted from #25148), the ambiguity arises from the `n` type variable bound by the type signature for `fact1`: class Facts a where fact1 :: forall n. Proxy a -> Dict (0 <= n) newtype T a = MkT a deriving newtype Facts When generating code for the derived `Facts` instance, we must use a type abstraction to bring `n` into scope over the type applications to `coerce` (see Note [Newtype-deriving instances] for more why this is needed). A first attempt at generating the instance would be: instance Facts a => Facts (T a) where fact1 @n = coerce @(Proxy a -> Dict (0 <= n)) @(Proxy (T a) -> Dict (0 <= n)) (fact1 @a) This still won't typecheck, however, as GHC doesn't know how to instantiate `n` in the call to `fact1 @a`. To compensate for the possibility of ambiguity here, we also visibly apply `n` in the call to `fact1` on the RHS: instance Facts a => Facts (T a) where fact1 @n = coerce @(Proxy a -> Dict (0 <= n)) @(Proxy (T a) -> Dict (0 <= n)) (fact1 @a @n) -- Note the @n here! This takes advantage of the fact that we *already* need to bring `n` into scope using a type abstraction, and so we are able to use it both for instantiating the call to `coerce` and instantiating the call to `fact1`. Note that we use this same type abstractions-based approach for resolving ambiguity in default methods, as described in Note [Default methods in instances] (Wrinkle: Ambiguous types from vanilla method type signatures) in GHC.Tc.TyCl.Instance.
References 1
- Newtype-deriving instances GHC.Tc.Deriv.Generate
Referenced by 4
- Newtype-deriving instances GHC.Tc.Deriv.Generate ×2
- GHC.Tc.Deriv.Generate call site
- Default methods in instances GHC.Tc.TyCl.Instance