Generics.Deriving.Default

generic-deriving-1.14.6: Generic programming library for generalised deriving.

License | BSD-3-Clause
Maintainer | generics@haskell.org
Stability | experimental
Portability | non-portable
Safe Haskell | Safe
Language | Haskell2010

Generics.Deriving.Default

Contents

- Kind `*` (aka `Type`)
- Kind `* -> *` (aka `Type -> Type`)
- Other kinds

Description

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.

Synopsis

- newtype Default a = Default {
  - unDefault :: a
  }
- newtype Default1 (f :: Type -> Type) a = Default1 {
  - unDefault1 :: f a
  }

# 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) instance GShow MyType

Instances may be parameterized by type variables.

    data MyType1 a = …
     deriving (Generic)
     deriving (GShow) via (Default (MyType1 a))

    deriving via Default (MyType1 a) instance GEq a => GEq (MyType1 a)

These types both require instances for `Generic`. This is because the implementations of `geq` and `gshowsPrec` for ``Default` b` have a ``Generic` b` constraint, i.e. the type corresponding to `b` require a `Generic` instance. For these two types, that means instances for ``Generic` MyType` and ``Generic` (MyType1 a)` respectively.

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.

newtype Default a #

This newtype wrapper can be used to derive default instances for classes taking an argument of kind `Type`.

Constructors

Default |
Fields unDefault :: a

#### Instances

Instances details

(Generic a, GEq a, Enum' (Rep a)) => GEnum (Default a) # | The `Enum` class in `base` is slightly different; it comprises `toEnum` and `fromEnum`. Generics.Deriving.Enum provides functions `toEnumDefault` and `fromEnumDefault`.
Instance details Defined in Generics.Deriving.Default Methods genum :: [Default a] #
(Generic a, GEq' (Rep a)) => GEq (Default a) # |
Instance details Defined in Generics.Deriving.Default Methods geq :: Default a -> Default a -> Bool #
(Generic a, GMonoid' (Rep a)) => GMonoid (Default a) # |
Instance details Defined in Generics.Deriving.Default Methods gmempty :: Default a # gmappend :: Default a -> Default a -> Default a # gmconcat :: [Default a] -> Default a #
(Generic a, GSemigroup' (Rep a)) => GSemigroup (Default a) # | Semigroups often have many sensible implementations of `<>` / `gsappend`, and therefore no sensible default. Indeed, there is no `GSemigroup'` instance for representations of sum types. In other cases, one may wish to use the existing wrapper newtypes in `base`, such as the following (using `First`):
    newtype FirstSemigroup = FirstSemigroup Bool
      deriving stock (Eq, Show)
      deriving (GSemigroup) via (First Bool)
Instance details Defined in Generics.Deriving.Default Methods gsappend :: Default a -> Default a -> Default a # gstimes :: Integral b => b -> Default a -> Default a # gsconcat :: NonEmpty (Default a) -> Default a #
(Generic a, GShow' (Rep a)) => GShow (Default a) # | For example, with this type:
    newtype TestShow = TestShow Bool
      deriving (GShow) via (Default Bool)
`gshow` for `TestShow` would produce the same string as `gshow` for `Bool`. In this example, `TestShow` requires no `Generic` instance, as the constraint on `gshowsPrec` from ``Default` `Bool`` is ``Generic` `Bool``. In general, when using a newtype wrapper, the instance can be derived via the wrapped type, as here (via ``Default` `Bool`` rather than ``Default` TestShow`).
Instance details Defined in Generics.Deriving.Default Methods gshowsPrec :: Int -> Default a -> ShowS # gshows :: Default a -> ShowS # gshow :: Default a -> String # gshowList :: [Default a] -> ShowS #
(Generic a, Uniplate' (Rep a) a, Context' (Rep a) a) => Uniplate (Default a) # |
Instance details Defined in Generics.Deriving.Default Methods children :: Default a -> [Default a] # context :: Default a -> [Default a] -> Default a # descend :: (Default a -> Default a) -> Default a -> Default a # descendM :: Monad m => (Default a -> m (Default a)) -> Default a -> m (Default a) # transform :: (Default a -> Default a) -> Default a -> Default a # transformM :: Monad m => (Default a -> m (Default a)) -> Default a -> m (Default a) #

# Kind `* -> *` (aka `Type -> Type`)

For classes which take an argument of kind ``Type` -> `Type``, use `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) instance GFoldable MyType1

Note that these instances require a ``Generic1` MyType1` constraint as `gmap` and `gfoldMap` have ``Generic1` a` constraints on the implementations for ``Default1` a`.

newtype Default1 (f :: Type -> Type) a #

This newtype wrapper can be used to derive default instances for classes taking an argument of kind ``Type` -> `Type``.

Constructors

Default1 |
Fields unDefault1 :: f a

#### Instances

Instances details

(Generic1 f, GCopoint' (Rep1 f)) => GCopoint (Default1 f) # |
Instance details Defined in Generics.Deriving.Default Methods gcopoint :: Default1 f a -> a #
(Generic1 t, GFoldable' (Rep1 t)) => GFoldable (Default1 t) # |
Instance details Defined in Generics.Deriving.Default Methods gfoldMap :: Monoid m => (a -> m) -> Default1 t a -> m # gfold :: Monoid m => Default1 t m -> m # gfoldr :: (a -> b -> b) -> b -> Default1 t a -> b # gfoldr' :: (a -> b -> b) -> b -> Default1 t a -> b # gfoldl :: (a -> b -> a) -> a -> Default1 t b -> a # gfoldl' :: (a -> b -> a) -> a -> Default1 t b -> a # gfoldr1 :: (a -> a -> a) -> Default1 t a -> a # gfoldl1 :: (a -> a -> a) -> Default1 t a -> a #
(Generic1 f, GFunctor' (Rep1 f)) => GFunctor (Default1 f) # |
Instance details Defined in Generics.Deriving.Default Methods gmap :: (a -> b) -> Default1 f a -> Default1 f b #
(Generic1 t, GFunctor' (Rep1 t), GFoldable' (Rep1 t), GTraversable' (Rep1 t)) => GTraversable (Default1 t) # |
Instance details Defined in Generics.Deriving.Default Methods gtraverse :: Applicative f => (a -> f b) -> Default1 t a -> f (Default1 t b) # gsequenceA :: Applicative f => Default1 t (f a) -> f (Default1 t a) # gmapM :: Monad m => (a -> m b) -> Default1 t a -> m (Default1 t b) # gsequence :: Monad m => Default1 t (m a) -> m (Default1 t a) #

# Other kinds

These principles extend to classes taking arguments of other kinds.