License | BSD-3-Clause |
---|---|
Maintainer | generics@haskell.org |
Stability | experimental |
Portability | non-portable |
Safe Haskell | Safe |
Language | Haskell2010 |
GHC 8.6 introduced the
DerivingVia
language extension, which means a typeclass instance can be derived from
an existing instance for an isomorphic type. Any newtype is isomorphic
to the underlying type. By implementing a typeclass once for the newtype,
it is possible to derive any typeclass for any type with a Generic
instance.
For a number of classes, there are sensible default instantiations. In
older GHCs, these can be supplied in the class definition, using the
DefaultSignatures
extension. However, only one default can be provided! With
DerivingVia
it is now possible to choose from many
default instantiations.
This package contains a number of such classes. This module demonstrates
how one might create a family of newtypes (Default
, Default1
) for
which such instances are defined.
One might then use
DerivingVia
as follows. The implementations of the data types are elided here (they
are irrelevant). For most cases, either the deriving clause with the
data type definition or the standalone clause will work (for some types
it is necessary to supply the context explicitly using the latter form).
See the source of this module for the implementations of instances for
the Default
family of newtypes and the source of the test suite for
some types which derive instances via these wrappers.
Kind *
(aka Type
)
For classes which take an argument of kind Type
, use
Default
. An example of this class from base
would be Eq
, or
Generic
.
These examples use GShow
and GEq
; they are interchangeable.
data MyType = … deriving (Generic
) deriving (GEq
) via (Default
MyType) deriving via (Default
MyType) instanceGShow
MyType
Instances may be parameterized by type variables.
data MyType1 a = … deriving (Generic
) deriving (GShow
) via (Default
(MyType1 a)) deriving viaDefault
(MyType1 a) instanceGEq
a =>GEq
(MyType1 a)
These types both require instances for Generic
. This is because the
implementations of geq
and gshowsPrec
for
have a Default
b
constraint, i.e. the type corresponding to Generic
bb
require a Generic
instance. For these two types, that means instances for
and Generic
MyType
respectively.Generic
(MyType1 a)
It also means the Generic
instance is not needed when there is already
a generic instance for the type used to derive the relevant instances.
For an example, see the documentation of the GShow
instance for
Default
, below.
This newtype wrapper can be used to derive default instances for
classes taking an argument of kind Type
.
Instances
(Generic a, GEq' (Rep a)) => GEq (Default a) Source # | |
(Generic a, GEq a, Enum' (Rep a)) => GEnum (Default a) Source # | The |
Defined in Generics.Deriving.Default | |
(Generic a, GSemigroup' (Rep a)) => GSemigroup (Default a) Source # | Semigroups often have many sensible implementations of
In other cases, one may wish to use the existing wrapper newtypes in
newtype FirstSemigroup = FirstSemigroup |
(Generic a, GMonoid' (Rep a)) => GMonoid (Default a) Source # | |
(Generic a, GShow' (Rep a)) => GShow (Default a) Source # | For example, with this type: newtype TestShow = TestShow
In this example, In general, when using a newtype wrapper, the instance can be derived
via the wrapped type, as here (via |
(Generic a, Uniplate' (Rep a) a, Context' (Rep a) a) => Uniplate (Default a) Source # | |
Defined in Generics.Deriving.Default children :: Default a -> [Default a] Source # context :: Default a -> [Default a] -> Default a Source # descend :: (Default a -> Default a) -> Default a -> Default a Source # descendM :: Monad m => (Default a -> m (Default a)) -> Default a -> m (Default a) Source # transform :: (Default a -> Default a) -> Default a -> Default a Source # transformM :: Monad m => (Default a -> m (Default a)) -> Default a -> m (Default a) Source # |
Kind * -> *
(aka Type -> Type
)
For classes which take an argument of kind
, use Type
->
Type
Default1
. An example of this class from base
would be Eq1
, or Generic1
.
Unlike for MyType1
, there can be no implementation of these classes for MyType ::
.Type
data MyType1 a = … deriving (Generic1
) deriving (GFunctor
) via (Default1
MyType1) deriving via (Default1
MyType1) instanceGFoldable
MyType1
Note that these instances require a
constraint as
Generic1
MyType1gmap
and gfoldMap
have
constraints on the
implementations for Generic1
a
.Default1
a
This newtype wrapper can be used to derive default instances for
classes taking an argument of kind
.Type
-> Type
Default1 | |
|
Instances
Other kinds
These principles extend to classes taking arguments of other kinds.