dph-seq-0.5.1.1: Data/Array/Parallel/PArray/Types.hs
{-# 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 }