vector-th-unbox- Deriver for Data.Vector.Unboxed using Template Haskell

Safe HaskellTrustworthy



Writing Unbox instances for new data types is tedious and formulaic. More often than not, there is a straightforward mapping of the new type onto some existing one already imbued with an Unbox instance. The example from the vector package represents Complex a as pairs (a, a). Using derivingUnbox, we can define the same instances much more succinctly:

derivingUnbox "Complex"
    [t| (Unbox a) ⇒ Complex a → (a, a) |]    [| \ (r :+ i) → (r, i) |]    [| \ (r, i) → r :+ i |]

Requires the MultiParamTypeClasses, TemplateHaskell, TypeFamilies and probably the FlexibleInstances LANGUAGE extensions. Note that GHC 7.4 (but not earlier nor later) needs the Vector and MVector class method names to be in scope in order to define the appropriate instances:

#if 706 == 704
import qualified Data.Vector.Generic
import qualified Data.Vector.Generic.Mutable

Consult the sanity test for a working example.





:: String

Unique constructor suffix for the MVector and Vector data families

-> TypeQ

Quotation of the form [t| ctxt ⇒ src → rep ]

-> ExpQ

Quotation of an expression of type src → re

-> ExpQ

Quotation of an expression of type rep → sr

-> DecsQ

Declarations to be spliced for the derived Unbox instance

Let's consider a more complex example: suppose we want an Unbox instance for Maybe a. We could encode this using the pair (Bool, a), with the boolean indicating whether we have Nothing or Just something. This encoding requires a dummy value in the Nothing case, necessitating an additional Default constraint. Thus:

derivingUnbox "Maybe"
    [t| (Default a, Unbox a) ⇒ Maybe a → (Bool, a) |]    [| maybe (False, def) (\ x → (True, x)) |]    [| \ (b, x) → if b then Just x else Nothing |]