Note [Newtype-deriving instances]

GHC/Tc/Deriv/Generate.hs:1683 compiler 1 ticket

We take every method in the original instance and `coerce` it to fit
into the derived instance. We need type applications on the argument
to `coerce` to make it obvious what instantiation of the method we're
coercing from.  So from, say,

  class C a b where
    op :: forall c. a -> [b] -> c -> Int

  newtype T x = MkT <rep-ty>

  instance C a <rep-ty> => C a (T x) where
    op @c = coerce @(a -> [<rep-ty>] -> c -> Int)
                   @(a -> [T x]      -> c -> Int)
                   (op @c)

In addition to the type applications, we also use a type abstraction to bring
the method-bound variable `c` into scope. We do this for two reasons:

* We need to bring `c` into scope over the two type applications to `coerce`.
  See Note [GND and QuantifiedConstraints] for more information on why this
  is important.
* We need to bring `c` into scope over the type application to `op`. See
  Note [GND and ambiguity] for more information on why this is important.

(In the surface syntax, only specified type variables can be used in type
abstractions. Since a method signature could contain both specified and
inferred type variables, we need an internal-only way to represent the inferred
case. We handle this by smuggling a Specificity field in XInvisPat. See
Note [Inferred invisible patterns].)

Giving 'coerce' two explicitly-visible type arguments grants us finer control
over how it should be instantiated. Recall

  coerce :: Coercible a b => a -> b

By giving it explicit type arguments we deal with the case where
'op' has a higher rank type, and so we must instantiate 'coerce' with
a polytype.  E.g.

   class C a where op :: a -> forall b. b -> b
   newtype T x = MkT <rep-ty>
   instance C <rep-ty> => C (T x) where
     op = coerce @(<rep-ty> -> forall b. b -> b)
                 @(T x      -> forall b. b -> b)
                op

The use of type applications is crucial here. We have to instantiate
both type args of (coerce :: Coercible a b => a -> b) to polytypes,
and we can only do that with VTA or Quick Look. Here VTA seems more
appropriate for machine generated code: it's simple and robust.

However, to allow VTA with polytypes we must switch on
-XImpredicativeTypes locally in GHC.Tc.Deriv.genInst.
See #8503 for more discussion.

The following Notes describe further nuances of GeneralizedNewtypeDeriving:


In GHC.Tc.Deriv


* Note [Newtype deriving]
* Note [Newtype representation]
* Note [Recursive newtypes]
* Note [Determining whether newtype-deriving is appropriate]
* Note [GND and associated type families]
* Note [Bindings for Generalised Newtype Deriving]


In GHC.Tc.Deriv.Generate


* Note [Newtype-deriving trickiness]
* Note [GND and QuantifiedConstraints]
* Note [GND and ambiguity]

References 10

Referenced by 7