Copyright | © 2012−2015 Liyang HU |
---|---|
License | BSD3 |
Maintainer | vector-th-unbox@liyang.hu |
Stability | experimental |
Portability | non-portable |
Safe Haskell | Trustworthy |
Language | Haskell2010 |
Documentation
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| ∀ a. (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 __GLASGOW_HASKELL__ == 704 import qualified Data.Vector.Generic import qualified Data.Vector.Generic.Mutable #endif
Consult the sanity test for a working example.
:: String | Unique constructor suffix for the MVector and Vector data families |
-> TypeQ | Quotation of the form |
-> ExpQ | Quotation of an expression of type |
-> ExpQ | Quotation of an expression of type |
-> 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| ∀ a. (Default a, Unbox a) ⇒ Maybe a → (Bool, a) |] [| maybe (False, def) (\ x → (True, x)) |] [| \ (b, x) → if b then Just x else Nothing |]