{-# LANGUAGE EmptyDataDecls #-} -- | Defines the extra types we use when representing algebraic data in parallel arrays. -- We don't store values of user defined algebraic type directly in PArrays. Instead, -- we convert these to a generic representation and store that representation. -- -- Conversion to and from the generic representation is handled by the methods -- of the PA class defined in "Data.Array.Parallel.PArray.PRepr". -- --- For further information see: -- "Instant Generics: Fast and Easy", Chakravarty, Ditu and Keller, 2009 -- module Data.Array.Parallel.PArray.Types ( -- * The Void type Void, void, fromVoid, -- * Generic sums Sum2(..), Sum3(..), -- * The Wrap type Wrap (..) ) where -- Void ----------------------------------------------------------------------- -- | The `Void` type is used when representing enumerations. -- A type like Bool is represented as @Sum2 Void Void@, meaning that we only -- only care about the tag of the data constructor and not its argumnent. data Void -- | A 'value' with the void type. Used as a placholder like `undefined`. -- Forcing this yields `error`. void :: Void void = error $ unlines [ "Data.Array.Parallel.PArray.Types.void" , " With the DPH generic array representation, values of type void" , " should never be forced. Something has gone badly wrong." ] -- | Coerce a `Void` to a different type. Used as a placeholder like `undefined`. -- Forcing the result yields `error`. fromVoid :: a fromVoid = error $unlines [ "Data.Array.Parallel.PArray.Types.fromVoid" , " With the DPH generic array representation, values of type void" , " should never be forced. Something has gone badly wrong." ] -- Sums ----------------------------------------------------------------------- -- | Sum types used for the generic representation of algebraic data. data Sum2 a b = Alt2_1 a | Alt2_2 b data Sum3 a b c = Alt3_1 a | Alt3_2 b | Alt3_3 c -- Wrap ----------------------------------------------------------------------- -- | When converting a data type to its generic representation, we use -- `Wrap` to help us convert only one layer at a time. For example: -- -- @ -- data Foo a = Foo Int a -- -- instance PA a => PA (Foo a) where -- type PRepr (Foo a) = (Int, Wrap a) -- define how (Foo a) is represented -- @ -- -- Here we've converted the @Foo@ data constructor to a pair, and Int -- is its own representation type. We have PData/PR instances for pairs and -- Ints, so we can work with arrays of these types. However, we can't just -- use (Int, a) as the representation of (Foo a) because 'a' might -- be user defined and we won't have PData/PR instances for it. -- -- Instead, we wrap the second element with the Wrap constructor, which tells -- us that if we want to process this element we still need to convert it -- to the generic representation (and back). This last part is done by -- the PR instance of Wrap, who's methods are defined by calls to the *PD -- functions from "Data.Array.Parallel.PArray.PRepr". -- newtype Wrap a = Wrap { unWrap :: a }