... | ... | @@ -107,10 +107,10 @@ With `-XDerivingStrategies` in the picture, we can now state how GHC figures out |
|
|
The phrase "bespoke typeclass" refers to the classes listed [ here](http://git.haskell.org/ghc.git/blob/8fe1672a9c4229b884b8dcebb9be57efa4c1fdb8:/compiler/typecheck/TcGenDeriv.hs#l123), plus `Generic` and `Generic1`.
|
|
|
|
|
|
|
|
|
Step 2 is fairly intricate since GHC tries to use `GeneralizedNewtypeDeriving` in certain special cases whenever it can to optimize the generated instances. In addition, the phrase "can be successfully used with `GeneralizedNewtypeDeriving`" must be invoked since it is possible for `GeneralizedNewtypeDeriving` to fail for certain datatypes. For example, you cannot have a newtype-derived `Functor` instance for `newtype Compose f g a = Compose (f (g a))`, since the last type variable `a` cannot be eta-reduced.
|
|
|
The relationship between bespoke instances and `DeriveAnyClass` can be be summarized as follows: In the absence of an explicit `anyclass` keyword, GHC will never attempt to derive a class using the `DeriveAnyClass` strategy when it would otherwise derive a `bespoke` instance, since it is guaranteed that doing so would not produce the instance you'd want.
|
|
|
|
|
|
|
|
|
Step 2.(b) deserves some explanation. As a rule, in the absence of an explicit `anyclass` keyword, GHC will never attempt to derive a class using the `DeriveAnyClass` strategy when it would otherwise derive a `bespoke` instance, since it is guaranteed that doing so would not produce the instance you'd want. This also applies when deriving a bespoke instance for a newtype when both `-XGeneralizedNewtypeDeriving` and `-XDeriveAnyClass` are enabled, which is why we need step 2 to come before step 3 so that `-XDeriveAnyClass` doesn't kick in when it shouldn't. This fixes the problem originally reported in Trac [\#10598](https://gitlab.haskell.org//ghc/ghc/issues/10598).
|
|
|
Step 2 is fairly intricate since GHC tries to use `GeneralizedNewtypeDeriving` in certain special cases whenever it can to optimize the generated instances. In addition, the phrase "can be successfully used with `GeneralizedNewtypeDeriving`" must be invoked since it is possible for `GeneralizedNewtypeDeriving` to fail for certain datatypes. For example, you cannot have a newtype-derived `Functor` instance for `newtype Compose f g a = Compose (f (g a))`, since the last type variable `a` cannot be eta-reduced.
|
|
|
|
|
|
|
|
|
To help visualize things, here's a table summarizing which typeclasses GHC decides it can use the `newtype` strategy for (thanks to Ørjan Johansen):
|
... | ... | |