6.6.7. Deriving strategies
- DerivingStrategies
- Since:
8.2.1
Allow multiple
deriving, each optionally qualified with a strategy.
In most scenarios, every deriving statement generates a typeclass instance
in an unambiguous fashion. There is a corner case, however, where
simultaneously enabling both the GeneralizedNewtypeDeriving and
DeriveAnyClass extensions can make deriving become ambiguous.
Consider the following example
{-# LANGUAGE DeriveAnyClass, GeneralizedNewtypeDeriving #-}
newtype Foo = MkFoo Bar deriving C
One could either pick the DeriveAnyClass approach to deriving C or the
GeneralizedNewtypeDeriving approach to deriving C, both of which would
be equally as valid. GHC defaults to favoring DeriveAnyClass in such a
dispute, but this is not a satisfying solution, since that leaves users unable
to use both language extensions in a single module.
To make this more robust, GHC has a notion of deriving strategies, which allow
the user to explicitly request which approach to use when deriving an instance.
To enable this feature, one must enable the DerivingStrategies
language extension. A deriving strategy can be specified in a deriving
clause
newtype Foo = MkFoo Bar
deriving newtype C
Or in a standalone deriving declaration
deriving anyclass instance C Foo
DerivingStrategies also allows the use of multiple deriving
clauses per data declaration so that a user can derive some instance with
one deriving strategy and other instances with another deriving strategy.
For example
newtype Baz = Baz Quux
deriving (Eq, Ord)
deriving stock (Read, Show)
deriving newtype (Num, Floating)
deriving anyclass C
Currently, the deriving strategies are:
stock: Have GHC implement a “standard” instance for a data type, if possible (e.g.,Eq,Ord,Generic,Data,Functor, etc.)anyclass: UseDeriveAnyClass(see Deriving any other class)newtype: UseGeneralizedNewtypeDeriving
via: UseDerivingVia(see Deriving via)
6.6.7.1. Default deriving strategy
If an explicit deriving strategy is not given, multiple strategies may apply. In that case, GHC chooses the strategy as follows:
Stock type classes, i.e. those specified in the report and those enabled by language extensions, are derived using the
stockstrategy, with the following exception:For newtypes,
Eq,Ord,IxandBoundedare always derived using thenewtypestrategy, even withoutGeneralizedNewtypeDerivingenabled. (There should be no observable difference to instances derived using the stock strategy.)Also for newtypes,
Functor,FoldableandEnumare derived using thenewtypestrategy ifGeneralizedNewtypeDerivingis enabled and the derivation succeeds.
For other any type class:
When
DeriveAnyClassis enabled, useanyclass.When
GeneralizedNewtypeDerivingis enabled and we are deriving for a newtype, then usenewtype.
If both rules apply to a deriving clause, then
anyclassis used and the user is warned about the ambiguity. The warning can be avoided by explicitly stating the desired deriving strategy.