
#10598: DeriveAnyClass and GND don't work well together -------------------------------------+------------------------------------- Reporter: osa1 | Owner: RyanGlScott Type: bug | Status: patch Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 7.11 Resolution: | Keywords: Generics Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2280 Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Replying to [comment:40 oerjan]:
Is it still the case that using any other deriving strategy than `bespoke` for a class that supports `bespoke` requires using this new extension?
The short answer is: yes. The longer, more nuanced answer is that GHC sometimes picks to derive certain "standard" classes using GND when they would produce the same instance (see "The deriving strategy resolution algorithm" section of [https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/DerivingStrategies this wiki page] for more info). For example, `newtype Foo = Foo Int deriving Eq` actually uses GND to derive the `Eq` instance, not the bespoke instance you'd normally get for `Eq`. Most of the time, though, if you derive a standard class without a keyword, it'll default to the `bespoke` strategy.
If not, then that could lead to confusing errors, like accidentally deriving `Functor` with anyclass because `DeriveAnyClass` is enabled but `DeriveFunctor` has been forgotten, and would probably warrant some more warnings.
This is a valid concern, but luckily that doesn't happen, even with the current GHC. Currently, GHC's outlook is that `DeriveAnyClass` should //never// kick in for standard classes. As a result, if you try compiling this program: {{{#!hs {-# LANGUAGE DeriveAnyClass #-} newtype T a = T (Maybe a) deriving Functor }}} it will error with: {{{ Can't make a derived instance of ‘Functor T’: You need DeriveFunctor to derive an instance for this class Try GeneralizedNewtypeDeriving for GHC's newtype-deriving extension In the newtype declaration for ‘T’ }}} whereas for nonstandard classes, `DeriveAnyClass` kicks in. Since none of the standard classes use `DefaultSignatures`, I think this special case is probably acceptable (and if you //really// want to derive your `Functor` instance using `DeriveAnyClass` for some bizarre reason, you'll be able to with `DerivingStrategies`).
On the other hand, I think GND would give equivalent result to `bespoke` for many classes, so it might be convenient ''not'' to warn in those cases. E.g. when someone wants to derive `Functor`, `Applicative` and `Monad` for their monad stack newtype, it seems almost reasonable that only GND needs to be enabled, and not `DeriveFunctor`.
It is indeed reasonable, and GHC does sometimes choose to pick `GeneralizedNewtypeDeriving` over the `DeriveFunctor` algorithm when the last type variable can be eta-reduced (again, see [https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/DerivingStrategies this wiki page] for the full story). Emphatically, Phab:D2280 will not change any of this existing behavior. The only things it does are (1) fix the bug reported in the original comment and (2) give you the ability to choose explicitly which strategy to use, and hence bypass the confusing algorithm GHC uses to choose a strategy implicitly in the absence of a strategy keyword. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10598#comment:41 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler