Note [Newtype-deriving instances]
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
- GND and ambiguity GHC.Tc.Deriv.Generate
- GND and QuantifiedConstraints GHC.Tc.Deriv.Generate
- Inferred invisible patterns GHC.Tc.Deriv.Generate
- Newtype-deriving trickiness GHC.Tc.Deriv.Generate
- Bindings for Generalised Newtype Deriving GHC.Tc.Deriv
- Determining whether newtype-deriving is appropriate GHC.Tc.Deriv
- GND and associated type families GHC.Tc.Deriv
- Newtype deriving GHC.Tc.Deriv
- Newtype representation GHC.Tc.Deriv
- Recursive newtypes GHC.Tc.Deriv
Referenced by 7
- GHC.Tc.Deriv.Generate call site ×3
- GHC.Tc.Deriv call site ×2
- GND and QuantifiedConstraints GHC.Tc.Deriv.Generate
- GND and ambiguity GHC.Tc.Deriv.Generate