one-liner-0.3.1: Constraint-based generics

Portabilitynon-portable
Stabilityexperimental
Maintainersjoerd@w3future.com
Safe HaskellNone

Generics.OneLiner

Contents

Description

This module is for writing generic functions on algebraic data types of kind *. These data types must be an instance of the Generic type class, which can be derived.

Synopsis

Producing values

create :: (ADT t, Constraints t c) => for c -> (forall s. c s => s) -> [t]Source

Create a value (one for each constructor), given how to construct the components.

 minBound = head $ create (For :: For Bounded) minBound
 maxBound = last $ create (For :: For Bounded) maxBound

createA :: (ADT t, Constraints t c, Applicative f) => for c -> (forall s. c s => f s) -> [f t]Source

Create a value (one for each constructor), given how to construct the components, under an applicative effect.

Here's how to implement get from the binary package:

 get = getWord8 >>= \ix -> createA (For :: For Binary) get !! fromEnum ix

ctorIndex :: ADT t => t -> IntSource

Get the index in the lists returned by create and createA of the constructor of the given value.

For example, this is the implementation of put that generates the binary data that the above implentation of get expects:

 put t = putWord8 (toEnum (ctorIndex t)) <> gfoldMap (For :: For Binary) put t

Note that this assumes a straightforward `Monoid` instance of `Put` which `binary` unfortunately does not provide.

Traversing values

gmap :: (ADT t, Constraints t c) => for c -> (forall s. c s => s -> s) -> t -> tSource

Map over a structure, updating each component.

gfoldMap :: (ADT t, Constraints t c, Monoid m) => for c -> (forall s. c s => s -> m) -> t -> mSource

Map each component of a structure to a monoid, and combine the results.

If you have a class Size, which measures the size of a structure, then this could be the default implementation:

 size = succ . getSum . gfoldMap (For :: For Size) (Sum . size)

gtraverse :: (ADT t, Constraints t c, Applicative f) => for c -> (forall s. c s => s -> f s) -> t -> f tSource

Map each component of a structure to an action, evaluate these actions from left to right, and collect the results.

Combining values

gzipWith :: (ADT t, Constraints t c) => for c -> (forall s. c s => s -> s -> s) -> t -> t -> Maybe tSource

Combine two values by combining each component of the structures with the given function. Returns Nothing if the constructors don't match.

mzipWith :: (ADT t, Constraints t c, Monoid m) => for c -> (forall s. c s => s -> s -> m) -> t -> t -> mSource

Combine two values by combining each component of the structures to a monoid, and combine the results. Returns mempty if the constructors don't match.

 compare s t = compare (ctorIndex s) (ctorIndex t) <> mzipWith (For :: For Ord) compare s t

zipWithA :: (ADT t, Constraints t c, Applicative f) => for c -> (forall s. c s => s -> s -> f s) -> t -> t -> Maybe (f t)Source

Combine two values by combining each component of the structures with the given function, under an applicative effect. Returns Nothing if the constructors don't match.

Single constructor functions

op0 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s) -> tSource

Implement a nullary operator by calling the operator for each component.

 mempty = op0 (For :: For Monoid) mempty
 fromInteger i = op0 (For :: For Num) (fromInteger i)

op1 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s -> s) -> t -> tSource

Implement a unary operator by calling the operator on the components. This is here for consistency, it is the same as gmap.

 negate = op1 (For :: For Num) negate

op2 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s -> s -> s) -> t -> t -> tSource

Implement a binary operator by calling the operator on the components.

 mappend = op2 (For :: For Monoid) mappend
 (+) = op2 (For :: For Num) (+)

Types

type ADT t = (Generic t, ADT' (Rep t))Source

ADT is a constraint type synonym. The Generic instance can be derived, and any generic representation will be an instance of ADT'.

type ADTRecord t = (ADT t, ADTRecord' (Rep t))Source

ADTRecord is a constraint type synonym. An instance is an ADT with exactly one constructor.

type Constraints t c = Constraints' (Rep t) cSource

Constraints is a constraint type synonym, containing the constraint requirements for an instance for t of class c. It requires an instance of class c for each component of t.

data For c Source

Tell the compiler which class we want to use in the traversal. Should be used like this:

 (For :: For Show)

Where Show can be any class.

Constructors

For