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

Safe HaskellNone
LanguageHaskell2010

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 Instantiators, 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 Derivers, 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

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 :: Constraint) 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 :: Constraint) 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
Deriver (Storable a) Source # 
Instance details

Defined in TH.Derive.Storable

Methods

runDeriver :: Proxy (Storable a) -> Cxt -> Type -> Q [Dec] Source #

class Instantiator (inst :: Constraint) 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 Names. 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.