derive: A program and library to derive instances for data types

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

Data.Derive is a library and a tool for deriving instances for Haskell programs. It is designed to work with custom derivations, SYB and Template Haskell mechanisms. The tool requires GHC, but the generated code is portable to all compilers. We see this tool as a competitor to DrIFT.


[Skip to Readme]

Properties

Versions 0.1, 0.1.1, 0.1.2, 0.1.3, 0.1.4, 2.0.0, 2.0.1, 2.1.0, 2.2.0, 2.3.0, 2.3.0.1, 2.3.0.2, 2.4, 2.4.1, 2.4.2, 2.5.1, 2.5.2, 2.5.3, 2.5.4, 2.5.5, 2.5.6, 2.5.7, 2.5.8, 2.5.9, 2.5.10, 2.5.11, 2.5.12, 2.5.13, 2.5.14, 2.5.15, 2.5.16, 2.5.17, 2.5.18, 2.5.19, 2.5.20, 2.5.21, 2.5.22, 2.5.23, 2.5.24, 2.5.25, 2.5.26, 2.6, 2.6.1, 2.6.2, 2.6.3, 2.6.4, 2.6.5, 2.6.5
Change log CHANGES.txt
Dependencies base (>=4 && <5), bytestring, containers, derive, directory, filepath, haskell-src-exts (>=1.20 && <1.21), pretty, process, syb, template-haskell, transformers (>=0.2), uniplate (>=1.5 && <1.7) [details]
License BSD-3-Clause
Copyright Neil Mitchell 2006-2017
Author Neil Mitchell <ndmitchell@gmail.com> and others
Maintainer none
Category Development
Home page https://github.com/ndmitchell/derive#readme
Bug tracker https://github.com/ndmitchell/derive/issues
Source repo head: git clone https://github.com/ndmitchell/derive.git
Uploaded by VladimirShabanov at 2019-01-22T13:50:56Z

Modules

[Index] [Quick Jump]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


Readme for derive-2.6.5

[back to package description]

Derive Hackage version Build Status

Warning: This package has no official maintainer anymore. Use at your own risk. You may wish to consider the built-in mechanism GHC.Generics or libraries such as generic-deriving.

Data.Derive is a library and a tool for deriving instances for Haskell programs. It is designed to work with custom derivations, SYB and Template Haskell mechanisms. The tool requires GHC, but the generated code is portable to all compilers. We see this tool as a competitor to DrIFT.

This document proceeds as follows:

Acknowledgements

Thanks to everyone who has submitted patches and given assistance, including: Twan van Laarhoven, Spencer Janssen, Andrea Vezzosi, Samuel Bronson, Joel Raymont, Benedikt Huber, Stefan O'Rear, Robin Green, Bertram Felgenhauer.

Obtaining and Installing Data.Derive

Installation follows the standard pattern of any Haskell library or program, type cabal update to update your local hackage database, then cabal install derive to install Derive.

Supported Derivations

Data.Derive is not limited to any prebuild set of derivations, see later for howto add your own. Out of the box, we provide instances for the following libraries.

Using the Derive program

Let's imagine we've defined a data type:

data Color = RGB Int Int Int
           | CMYK Int Int Int Int
           deriving (Eq, Show)

Now we wish to extend this to derive Binary and change to defining Eq using our library. To do this we simply add to the deriving clause.

data Color = RGB Int Int Int
           | CMYK Int Int Int Int
           deriving (Show {-! Eq, Binary !-})

Or alternatively write:

{-!
deriving instance Eq Color
deriving instance Binary Color
!-}

Now running derive on the program containing this code will generate appropriate instances. How do you combine these instances back into the code? There are various mechanisms supported.

Appending to the module

One way is to append the text to the bottom of the module, this can be done by passing the --append flag. If this is done, Derive will generate the required instances and place them at the bottom of the file, along with a checksum. Do not modify these instances.

As a GHC preprocessor

To use Derive as a GHC preprocessor, add the following line at the top of the source file:

{-# OPTIONS_GHC -F -pgmFderive -optF-F #-}

This instructs GHC to apply a preprocessor (-F), and to use the preprocessor derive -F.

Using CPP

One way is to use CPP. Ensure your compiler is set up for compiling with the C Pre Processor. For example:

{-# LANGUAGE CPP #-}
{-# OPTIONS_DERIVE --output=file.h #-}

module ModuleName where

#include "file.h"

Side-by-side Modules

If you had Colour.Type, and wished to place the Binary instance in Colour.Binary, this can be done with:

{-# OPTIONS_DERIVE --output=Binary.hs --module=Colour.Binary --import #-}

Here you ask for the output to go to a particular file, give a specific module name and import this module. This will only work if the data structure is exported non-abstractly.

Using Template Haskell Derivations

One of Derive's advantages over DrIFT is support for Template Haskell (abbreviated TH). Derive can be invoked automatically during the compilation process, and transparently supports deriving across module boundaries. The main disadvantage of TH-based deriving is that it is only portable to compilers that support TH; currently that is GHC only.

To use the TH deriving system, with the same example as before:

{-# LANGUAGE TemplateHaskell #-}
import Data.DeriveTH
import Data.Binary

data Color = RGB Int Int Int
           | CMYK Int Int Int Int
           deriving (Show)

$( derive makeEq ''Color )
$( derive makeBinary ''Color )

We need to tell the compiler to insert the instance using the TH splice construct, $( ... ) (the spaces are optional). The splice causes the compiler to run the function derive (exported from Data.DeriveTH), passing arguments makeFooBar and ''Color. The second argument deserves more explanation; it is a quoted symbol, somewhat like a quoted symbol in Lisp and with deliberately similar syntax. (Two apostrophes are used to specify that this name is to be resolved as a type constructor; just 'Color would look for a data constructor named Color.)

Writing a New Derivation

There are two methods for writing a new derivation, guessing or coding. The guessing method is substantially easier if it will work for you, but is limited to derivations with the following properties:

If however your instance does meet these properties, you can use derivation by guess. Many instances do meet these conditions, for examples see: Eq, Ord, Data, Serial etc. If however you need to code the derivation manually see examples such as Update and Functor.

Modifying Derive

The standard sequence for testing Derive is:

$ ghci Main.hs
:main --generate
:reload
:main --test

The --generate option will automatically generate DSL's for derivations derived by example. The --test option runs all test comparisons and then loads the file with Template Haskell.

Coding a new derivation

My best suggestion, start with a similar instance, i.e. to make Eq2 from Eq do:

Now fix up Eq2.hs appropriately.