th-utilities-0.2.5.2: Collection of useful functions for use with Template Haskell

Safe Haskell | None
Language | Haskell2010

TH.Derive

Description

This module implements a system for registering and using typeclass derivers and instantiators. This allows you to derive instances for typeclasses beyond GHC's ability to generate instances in `deriving` clauses.

For example, TH.Derive.Storable defines a `Deriver` for `Storable`. This allows us to use `derive` to generate an instance for Storable:

        data X = X Int Float

        $($(derive [d|
            instance Deriving (Storable X)
            |]))

In particular, note the use of double splicing, `$($(derive [d| ... |]))`. The inner `$(derive [d| ... |])` expression generates code which invokes the `runDeriver` method with appropriate arguments. The outer `$( ... $)` then runs that code in order to generate the resulting instances. This is how it does dispatch at compile time.

There are a number of advantages of re-using instance syntax in this way:

- It allows the user to specify constraints. Similarly to GHC's need for standalone deriving, it is sometimes very difficult for TH to figure out appropriate superclass constraints.
- The instance gets thoroughly checked by GHC (syntax, kind, and type checking). This means that you get reasonably nice error messages when you misuse these.
- It allows the user to specify methods. With `Instantiator`s, the user can provide values which can be used in the definition of the generated instance. This is a bit like having Instance Templates. We don't have pretty ways of writing these quite yet, but I have worked on something similar in the past.
- Using compile-time dispatch allows for concise specification of a multiple of instances you'd like derived.
- In the case of use of a `Deriver`s, the user doesn't need to know about anything but `derive` and the name of the class they want. (and the `Deriver` instance must be in scope one way or another)

Synopsis

- derive :: DecsQ -> ExpQ
- class Deriving cls
- class Deriver cls where
  - runDeriver :: Proxy cls -> Cxt -> Type -> Q [Dec]
- class Instantiator inst where
  - runInstantiator :: Proxy inst -> Cxt -> Type -> [Dec] -> Q [Dec]
- dequalifyMethods :: Data a => Name -> a -> Q a

# Documentation

derive :: DecsQ -> ExpQ Source #

This is the primary function for users of TH.Derive. See the module documentation for usage info.

class Deriving cls Source #

This class has no instances. Its only purpose is usage within the `[d| ... |]` quote provided to `derive`. Usage such as `instance Deriving (Foo X)` indicates that you would like to use the `Deriver` registered for `Foo a`.

Minimal complete definition

_noInstances

class Deriver cls where Source #

Instances of `Deriver` describe a default way of creating an instance for a particular typeclass. For example, if I wanted to write something that derives `Eq` instances, I would write a `instance Deriver (Eq a)`.

Methods

runDeriver :: Proxy cls -> Cxt -> Type -> Q [Dec] Source #

#### Instances

Instances details

Deriver (Storable a) Source # |
Instance details Defined in TH.Derive.Storable Methods runDeriver :: Proxy (Storable a) -> Cxt -> Type -> Q [Dec] Source #

class Instantiator inst where Source #

Methods

runInstantiator :: Proxy inst -> Cxt -> Type -> [Dec] -> Q [Dec] Source #

dequalifyMethods :: Data a => Name -> a -> Q a Source #

Useful function for defining `Instantiator` instances. It uses `Data` to generically replace references to the methods with plain `Name`s. This is handy when you are putting the definitions passed to the instantiator in a where clause. It is also useful so that you can reference the class methods from AST quotes involved in the definition of the instantiator.