diff --git a/Data/Array/Parallel/PArr.hs b/Data/Array/Parallel/PArr.hs
new file mode 100644
--- /dev/null
+++ b/Data/Array/Parallel/PArr.hs
@@ -0,0 +1,91 @@
+{-# OPTIONS_GHC -funbox-strict-fields #-}
+{-# OPTIONS_HADDOCK hide #-}
+
+--   NOTE NOTE NOTE
+--   This file is IDENTICAL to the one in dph-lifted-boxed.
+--   If you update one then update the other as well.
+
+-- | Unvectorised functions that work directly on parallel arrays of [::] type.
+--   These are used internally in the DPH library, but the user never sees them.
+--   Only vectorised functions are visible in the DPH client programs.
+--
+module Data.Array.Parallel.PArr 
+        ( PArr
+        , emptyPArr
+        , replicatePArr
+        , singletonPArr
+        , indexPArr
+        , headPArr
+        , lengthPArr)
+where
+import GHC.ST
+import GHC.Base
+import GHC.PArr
+
+-- | Construct an empty array, with no elements.
+emptyPArr :: PArr a
+emptyPArr = replicatePArr 0 undefined
+{-# NOINLINE emptyPArr #-}
+
+
+-- | Construct an array with a single element.
+singletonPArr :: a -> PArr a
+singletonPArr e = replicatePArr 1 e
+{-# NOINLINE singletonPArr #-}
+
+
+-- | Construct an array by replicating the given element some number of times.
+replicatePArr :: Int -> a -> PArr a
+replicatePArr n e  
+ = runST (do
+         marr# <- newArray n e
+         mkPArr n marr#)
+{-# NOINLINE replicatePArr #-}
+
+
+-- | Take the length of an array.
+lengthPArr :: PArr a -> Int
+lengthPArr (PArr n _) = n
+{-# NOINLINE lengthPArr #-}
+
+
+-- | Lookup a single element from the source array.
+indexPArr :: PArr e -> Int -> e
+indexPArr (PArr n arr#) i@(I# i#)
+  | i >= 0 && i < n 
+  = case indexArray# arr# i# of (# e #) -> e
+
+  | otherwise
+  = error $  "indexPArr: out of bounds parallel array index; " 
+          ++ "idx = " ++ show i ++ ", arr len = "
+          ++ show n
+{-# NOINLINE indexPArr #-}
+
+
+-- | Take the first element of the source array, 
+--   or `error` if there isn't one.
+headPArr :: PArr a -> a
+headPArr arr = indexPArr arr 0
+{-# NOINLINE headPArr #-}
+
+
+-------------------------------------------------------------------------------
+-- | Internally used mutable boxed arrays
+data MPArr s e = MPArr !Int (MutableArray# s e)
+
+
+-- | Allocate a new mutable array that is pre-initialised with a given value
+newArray :: Int -> e -> ST s (MPArr s e)
+newArray n@(I# n#) e  = ST $ \s1# ->
+  case newArray# n# e s1# of { (# s2#, marr# #) ->
+  (# s2#, MPArr n marr# #)}
+{-# INLINE newArray #-}
+
+
+-- | Convert a mutable array into the external parallel array representation
+mkPArr :: Int -> MPArr s e -> ST s (PArr e)
+mkPArr n (MPArr _ marr#)  = ST $ \s1# ->
+  case unsafeFreezeArray# marr# s1#   of { (# s2#, arr# #) ->
+  (# s2#, PArr n arr# #) }
+{-# INLINE mkPArr #-}
+
diff --git a/Data/Array/Parallel/PArray.hs b/Data/Array/Parallel/PArray.hs
new file mode 100644
--- /dev/null
+++ b/Data/Array/Parallel/PArray.hs
@@ -0,0 +1,400 @@
+
+-- | Reference implementation of operators on unvectorised parallel arrays.
+--
+--   * In this module we just used boxed vectors as the array representation. 
+--     This won't be fast, but it means we can write the operators without
+--     needing type class dictionaries such as PA. This makes them
+--     much easier to use as reference code.
+--
+--   * The operators should also all do bounds checks, sanity checks, and 
+--     give nice error messages if something is wrong. The ideas is that
+--     this code can be run side-by-side production code during debugging.
+---
+--   TODO: check lengths properly in functions like zip, extracts
+--
+module Data.Array.Parallel.PArray
+        ( PArray
+        , valid
+        , nf
+        
+        -- * Constructors
+        , empty
+        , singleton,    singletonl
+        , replicate,    replicatel,     replicates,     replicates'
+        , append,       appendl
+        , concat,       concatl
+        , unconcat
+        , nestUSegd
+        
+        -- * Projections
+        , length,       lengthl
+        , index,        indexl
+        , extract,      extracts,       extracts'
+        , slice,        slicel
+        , takeUSegd
+        
+        -- * Pack and Combine
+        , pack,         packl
+        , packByTag
+        , combine2
+        
+        -- * Enumerations
+        , enumFromTo,   enumFromTol
+        
+        -- * Tuples
+        , zip,          zipl
+        , unzip,        unzipl
+        
+        -- * Conversions
+        , fromVector,   toVector
+        , fromList,     toList
+        , fromUArray,   toUArray
+        , fromUArray2)
+where
+import Data.Array.Parallel.Base                 (Tag)
+import Data.Vector                              (Vector)
+import qualified Data.Array.Parallel.Unlifted   as U
+import qualified Data.Vector                    as V
+import qualified Prelude                        as P
+import Control.Monad
+import GHC.Exts
+import Prelude hiding
+        ( replicate, length, concat
+        , enumFromTo
+        , zip, unzip)
+
+-------------------------------------------------------------------------------
+here :: String -> String
+here str   = "Data.Array.Parallel.PArray." ++ str
+
+die :: String -> String -> a
+die fn str = error (here $ fn ++ " " ++ str)
+
+-- Array Type -----------------------------------------------------------------
+type PArray a
+        = Vector a
+        
+-- | Lift a unary array operator.
+lift1   :: (a -> b) -> PArray a -> PArray b
+lift1 f vec
+        = V.map f vec
+
+
+-- | Lift a binary array operator.
+lift2   :: (a -> b -> c) -> PArray a -> PArray b -> PArray c
+lift2 f vec1 vec2
+        | V.length vec1 /= V.length vec2
+        = die "lift2" "length mismatch"
+ 
+        | otherwise
+        = V.zipWith f vec1 vec2
+
+
+-- | Lift a trinary array operator
+lift3   :: (a -> b -> c -> d) -> PArray a -> PArray b -> PArray c -> PArray d
+lift3 f vec1 vec2 vec3
+        |   V.length vec1 /= V.length vec2
+         || V.length vec1 /= V.length vec3
+        = die "lift3" "length mismatch"
+ 
+        | otherwise
+        = V.zipWith3 f vec1 vec2 vec3
+
+
+-- Basics ---------------------------------------------------------------------
+-- | Check that an array has a valid internal representation.
+valid :: PArray a -> Bool
+valid _ = True
+
+-- | Force an array to normal form.
+nf :: PArray a -> ()
+nf _    = ()
+
+
+-- Constructors ----------------------------------------------------------------
+-- | O(1). An empty array.
+empty :: PArray a
+empty           = V.empty
+
+
+-- | O(1). Produce an array containing a single element.
+singleton :: a -> PArray a
+singleton       = V.singleton
+
+
+-- | O(n). Produce an array of singleton arrays.
+singletonl :: PArray a -> PArray (PArray a)
+singletonl      = lift1 singleton
+
+
+-- | O(n). Define an array of the given size, that maps all elements to the same value.
+replicate :: Int -> a -> PArray a
+replicate       = V.replicate
+
+
+-- | O(sum lengths). Lifted replicate.
+replicatel :: PArray Int -> PArray a -> PArray (PArray a)
+replicatel      = lift2 replicate
+
+
+-- | O(sum lengths). Segmented replicate.
+replicates :: U.Segd -> PArray a -> PArray a
+replicates segd vec
+        | V.length vec /= U.lengthSegd segd
+        = die "replicates" $ unlines
+                [ "segd length mismatch"
+                , "  segd length  = " ++ (show $ U.lengthSegd segd)
+                , "  array length = " ++ (show $ V.length vec)]
+
+        | otherwise
+        = join 
+        $ V.zipWith V.replicate
+                (V.convert $ U.lengthsSegd segd)
+                vec
+
+
+-- | O(sum lengths). Wrapper for segmented replicate that takes replication counts
+--  and uses them to build the `U.Segd`.
+replicates' :: PArray Int -> PArray a -> PArray a
+replicates' reps arr
+        = replicates (U.lengthsToSegd $ V.convert $ reps) arr
+
+
+-- | Append two arrays.
+append :: PArray a -> PArray a -> PArray a
+append          = (V.++)
+
+
+-- | Lifted append.
+appendl :: PArray (PArray a) -> PArray (PArray a) -> PArray (PArray a)
+appendl         = lift2 append
+
+
+-- | Concatenation
+concat :: PArray (PArray a) -> PArray a
+concat          = join
+
+
+-- | Lifted concatenation.
+concatl :: PArray (PArray (PArray a)) -> PArray (PArray a)
+concatl         = lift1 concat
+
+
+-- | Impose a nesting structure on a flat array
+unconcat :: PArray (PArray a) -> PArray b -> PArray (PArray b)
+unconcat arr1 arr2
+        = nestUSegd (takeUSegd arr1) arr2
+
+
+-- | Create a nested array from a segment descriptor and some flat data.
+--   The segment descriptor must represent as many elements as present
+--   in the flat data array, else `error`
+nestUSegd :: U.Segd -> PArray a -> PArray (PArray a)
+nestUSegd segd vec
+        | U.elementsSegd segd     == V.length vec 
+        = V.zipWith
+                (\start len -> V.slice start len vec)
+                (V.convert $ U.indicesSegd segd)
+                (V.convert $ U.lengthsSegd segd)
+
+        | otherwise
+        = error $ unlines
+                [ "Data.Array.Parallel.PArray.nestSegd: number of elements defined by "
+                        ++ "segment descriptor and data array do not match"
+                , " length of segment desciptor = " ++ (show $ U.elementsSegd segd)
+                , " length of data array        = " ++ (show $ V.length vec)]
+{-# NOINLINE nestUSegd #-}
+
+
+-- Projections ----------------------------------------------------------------
+-- | Take the length of an array
+length :: PArray a -> Int
+length          = V.length
+
+
+-- | Take the length of some arrays.
+lengthl :: PArray (PArray a) -> PArray Int
+lengthl         = lift1 length
+
+
+-- | Lookup a single element from the source array.
+index :: PArray a -> Int -> a
+index           = (V.!)
+
+
+-- | Lookup a several elements from several source arrays.
+indexl :: PArray (PArray a) -> PArray Int -> PArray a
+indexl          = lift2 index
+
+
+-- | Extract a range of elements from an array.
+extract :: PArray a -> Int -> Int -> PArray a
+extract vec start len
+        = V.slice start len vec
+
+
+-- | Segmented extract.
+extracts :: Vector (PArray a) -> U.SSegd -> PArray a
+extracts arrs ssegd
+        = join
+        $ V.zipWith3
+                (\src start len -> extract (arrs V.! src) start len)
+                (V.convert $ U.sourcesOfSSegd ssegd)
+                (V.convert $ U.startsOfSSegd  ssegd)
+                (V.convert $ U.lengthsOfSSegd ssegd)
+
+
+-- | Wrapper for `extracts` that takes arrays of sources, starts and lengths of
+--   the segments, and uses these to build the `U.SSegd`.
+extracts' 
+        :: Vector (PArray a) 
+        -> PArray Int           -- ^ id of source array for each segment.
+        -> PArray Int           -- ^ starting index of each segment in its source array.
+        -> PArray Int           -- ^ length of each segment.
+        -> PArray a
+extracts' arrs sources starts lengths
+ = let  segd    = U.lengthsToSegd $ V.convert lengths
+        ssegd   = U.mkSSegd 
+                        (V.convert $ starts)
+                        (V.convert $ sources)
+                        segd
+   in   extracts arrs ssegd
+
+
+-- | Extract a range of elements from an arrary.
+--   Like `extract` but with the parameters in a different order.
+slice :: Int -> Int -> PArray a -> PArray a
+slice start len arr
+        = extract arr start len
+
+
+-- | Extract some slices from some arrays.
+--   The arrays of starting indices and lengths must themselves
+--   have the same length.
+slicel :: PArray Int -> PArray Int -> PArray (PArray a) -> PArray (PArray a)
+slicel  = lift3 slice
+
+
+-- | Take the segment descriptor from a nested array. This can cause index space
+--   overflow if the number of elements in the result does not can not be
+--   represented by a single machine word.
+takeUSegd :: PArray (PArray a) -> U.Segd
+takeUSegd vec
+        = U.lengthsToSegd 
+        $ V.convert
+        $ V.map length vec
+        
+
+-- Pack and Combine -----------------------------------------------------------
+-- | Select the elements of an array that have their tag set to True.
+pack    :: PArray a -> PArray Bool -> PArray a
+pack xs bs
+        | V.length xs /= V.length bs
+        = die "pack" $ unlines
+                [ "array length mismatch"
+                , "  data  length = " ++ (show $ V.length xs)
+                , "  flags length = " ++ (show $ V.length bs) ]
+
+        | otherwise
+        = V.ifilter (\i _ -> bs V.! i) xs
+
+
+-- | Lifted pack.
+packl :: PArray (PArray a) -> PArray (PArray Bool) -> PArray (PArray a)
+packl   = lift2 pack
+
+
+-- | Filter an array based on some tags.
+packByTag :: PArray a -> U.Array Tag -> Tag -> PArray a
+packByTag xs tags tag
+        | V.length xs /= U.length tags
+        = die "packByTag" $ unlines
+                [ "array length mismatch"
+                , "  data  length = " ++ (show $ V.length xs)
+                , "  flags length = " ++ (show $ U.length tags) ]
+
+        | otherwise
+        = V.ifilter (\i _ -> U.index (here "packByTag") tags i == tag) xs
+
+
+-- | Combine two arrays based on a selector.
+combine2 :: U.Sel2 -> PArray a -> PArray a -> PArray a
+combine2 tags vec1 vec2
+ = let  go [] [] []                     = []
+        go (0 : bs) (x : xs) ys         = x : go bs xs ys
+        go (1 : bs) xs       (y : ys)   = y : go bs xs ys
+        go _ _ _ = error "Data.Array.Parallel.PArray.combine: length mismatch"
+ 
+   in   V.fromList
+                $ go    (V.toList $ V.convert $ U.tagsSel2 tags)
+                        (V.toList vec1)
+                        (V.toList vec2)
+
+
+-- Enumerations ---------------------------------------------------------------
+-- | Construct a range of integers
+enumFromTo :: Int -> Int -> PArray Int
+enumFromTo      = V.enumFromTo
+
+
+-- | Lifted enumeration
+enumFromTol :: PArray Int -> PArray Int -> PArray (PArray Int)
+enumFromTol     = lift2 enumFromTo
+
+
+-- Tuples ---------------------------------------------------------------------
+-- | O(n). Zip a pair of arrays into an array of pairs.
+zip     :: PArray a -> PArray b -> PArray (a, b)
+zip     = V.zip
+
+
+-- | Lifted zip
+zipl    :: PArray (PArray a) -> PArray (PArray b) -> PArray (PArray (a, b))
+zipl    = lift2 zip
+
+
+-- | O(n). Unzip an array of pairs into a pair of arrays.
+unzip   :: PArray (a, b) -> (PArray a, PArray b)
+unzip   = V.unzip
+
+
+-- | Lifted unzip
+unzipl  :: PArray (PArray (a, b)) -> PArray (PArray a, PArray b)
+unzipl  = lift1 unzip
+
+
+-- Conversions ----------------------------------------------------------------
+-- | Convert a `Vector` to a `PArray`
+fromVector :: Vector a -> PArray a
+fromVector = id
+
+
+-- | Convert a `PArray` to a `Vector`        
+toVector   :: PArray a -> Vector a
+toVector   = id
+
+-- | Convert a list to a `PArray`.
+fromList   :: [a] -> PArray a
+fromList   = V.fromList
+
+-- | Convert a `PArray` to a list.
+toList     :: PArray a -> [a]
+toList     = V.toList
+
+
+-- | Convert a `U.Array` to a `PArray`
+fromUArray :: U.Elt a => U.Array a -> PArray a
+fromUArray  = V.convert
+
+
+-- | Convert a `PArray` to a `U.Array`
+toUArray   :: U.Elt a => PArray a -> U.Array a
+toUArray    = V.convert
+
+
+-- | Convert a `U.Array` of tuples to a `PArray`
+fromUArray2
+        :: (U.Elt a, U.Elt b)
+        => U.Array (a, b) -> PArray (a, b)
+        
+fromUArray2  = V.convert
diff --git a/Data/Array/Parallel/PArray/Reference.hs b/Data/Array/Parallel/PArray/Reference.hs
new file mode 100644
--- /dev/null
+++ b/Data/Array/Parallel/PArray/Reference.hs
@@ -0,0 +1,170 @@
+{-# LANGUAGE UndecidableInstances #-}
+{-# OPTIONS -fno-warn-missing-signatures #-}
+-- | During testing, we compare the output of each invocation of the lifted
+--   combinators in "Data.Array.Parallel.PArray" with the reference implementations. 
+--
+--   This module helps convert the to and from the array representation
+--   used by the reference implementation.
+
+--   TODO: we could use this to trace the lengths of the vectors being used, 
+--         as well as the types that each opeartor is being called at.
+--
+module Data.Array.Parallel.PArray.Reference
+        ( Similar(..), PprPhysical1 (..)
+        , withRef1, withRef2
+        , toRef1,   toRef2,   toRef3)
+where
+import Data.Array.Parallel.Pretty
+import qualified Data.Array.Parallel.Array      as A
+import qualified Data.Vector                    as V
+import Data.Vector                              (Vector)
+import Prelude hiding (length)
+import System.IO
+import System.IO.Unsafe
+import Control.Monad
+
+-- Config ---------------------------------------------------------------------
+debugLiftedTrace        :: Bool
+debugLiftedTrace        = False
+
+debugLiftedCompare      :: Bool
+debugLiftedCompare      = False
+
+class Similar a where
+ similar :: a -> a -> Bool
+
+class PprPhysical1 a where
+ pprp1  :: a -> Doc
+
+ pprp1v :: Vector a -> Doc
+ pprp1v vec
+        = brackets 
+        $ hcat
+        $ punctuate (text ", ") 
+        $ V.toList $ V.map pprp1 vec
+        
+
+-- withRef --------------------------------------------------------------------
+-- | Compare the result of some array operator against a reference.
+
+--  Careful:
+--   * We don't want to inline the whole body of this function into
+--     every use site, or we'll get code explosion. When debugging is off we
+--     want this wrapper to be inlined and eliminated as cheaply as possible.
+--   * We also do this with 'unsafePerformIO' instead of trace, because
+--     with trace, if the computation contructing the string throws an exception
+--     then we get no output. For debugging we want to see what function was
+--     entered before we try to print the result (which might be badly formed),
+--
+withRef1 :: ( A.Array r a
+            , A.Array c a, PprPhysical1 (c a)
+            , Similar a,   PprPhysical1 a)
+         => String              -- name of operator
+         -> r a                 -- result using reference implementation
+         -> c a                 -- result using vseg implementation
+         -> c a
+
+{-# INLINE withRef1 #-}
+withRef1 name arrRef arrImpl
+ = if debugLiftedCompare || debugLiftedTrace
+        then withRef1' name arrRef arrImpl
+        else arrImpl
+        
+{-# NOINLINE withRef1' #-}
+withRef1' name arrRef arrImpl
+ = unsafePerformIO
+ $ do   when debugLiftedTrace
+         $ do putStrLn  $ "* " ++ name
+              putStrLn  $ render (nest 4 $ pprp1 arrImpl)
+              hFlush stdout
+        
+        when ( debugLiftedCompare 
+             && or [ not $ A.valid arrImpl
+                   , not $ A.length arrRef == A.length arrImpl
+                   , not $ V.and $ V.zipWith similar
+                                (A.toVectors1 arrRef)
+                                (A.toVectors1 arrImpl)])
+         $ error $ render $ vcat
+                [ text "withRef1: failure " <> text name
+                , nest 4 $ pprp1v $ A.toVectors1 arrRef
+                , nest 4 $ pprp1  $ arrImpl ]
+
+        return arrImpl
+
+
+-- | Compare the nested result of some array operator against a reference.
+withRef2 :: ( A.Array r (r a)
+            , A.Array r a
+            , A.Array c (c a), PprPhysical1 (c (c a))
+            , A.Array c a,     PprPhysical1 (c a)
+            , Similar a,       PprPhysical1 a)
+         => String      -- name of operator.
+         -> r (r a)     -- result using reference implementaiton.
+         -> c (c a)     -- result using vseg implementation.
+         -> c (c a)
+
+{-# INLINE withRef2 #-}
+withRef2 name arrRef arrImpl
+ = if debugLiftedCompare || debugLiftedTrace
+         then withRef2' name arrRef arrImpl
+         else arrImpl
+
+{-# NOINLINE withRef2' #-}
+withRef2' name arrRef arrImpl
+ = unsafePerformIO
+ $ do   when debugLiftedTrace
+         $ do putStrLn  $ "* " ++ name
+              putStrLn  $ render (nest 4 $ pprp1 arrImpl)
+              hFlush stdout
+
+        when ( debugLiftedCompare
+             && or [ not $ A.valid arrImpl
+                   , not $ A.length arrRef == A.length arrImpl
+                   , not $ V.and $ V.zipWith 
+                                (\xs ys -> V.and $ V.zipWith similar xs ys)
+                                (A.toVectors2 arrRef)
+                                (A.toVectors2 arrImpl) ])
+         $ error $ render $ vcat
+                [ text "withRef2: failure " <> text name
+                , nest 4 $ pprp1 arrImpl ]
+
+        return arrImpl
+
+
+-- toRef ----------------------------------------------------------------------
+-- | Convert an array to the reference version.
+toRef1  :: ( A.Array c a
+           , A.Array r a)
+        => c a -> r a
+
+toRef1  = A.fromVectors1 . A.toVectors1
+{-# NOINLINE toRef1 #-}
+--  NOINLINE because it's only for debugging.
+
+
+-- | Convert a nested array to the reference version.
+toRef2 :: ( A.Array c (c a)
+          , A.Array c a
+          , A.Array r (r a)
+          , A.Array r a)
+       => c (c a)
+       -> r (r a)
+
+toRef2  = A.fromVectors2 . A.toVectors2
+{-# NOINLINE toRef2 #-}
+--  NOINLINE because it's only for debugging.
+
+
+-- | Convert a doubly nested array to the reference version.
+toRef3 :: ( A.Array c (c (c a))
+          , A.Array c (c a)
+          , A.Array c a
+          , A.Array r (r (r a))
+          , A.Array r (r a)
+          , A.Array r a)
+       => c (c (c a))
+       -> r (r (r a))
+
+toRef3  = A.fromVectors3 . A.toVectors3
+{-# NOINLINE toRef3 #-}
+--  NOINLINE because it's only for debugging.
diff --git a/Data/Array/Parallel/PArray/Types.hs b/Data/Array/Parallel/PArray/Types.hs
new file mode 100644
--- /dev/null
+++ b/Data/Array/Parallel/PArray/Types.hs
@@ -0,0 +1,116 @@
+{-# LANGUAGE CPP #-}
+#include "fusion-phases.h"
+
+-- | 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(..), tagOfSum2
+        , Sum3(..), tagOfSum3
+        
+          -- * The Wrap type
+        , Wrap (..))
+where
+import Data.Array.Parallel.Base (Tag)
+import Data.Array.Parallel.Pretty
+
+
+-- 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." ]
+
+
+-- Sum2 -----------------------------------------------------------------------
+-- | Sum types used for the generic representation of algebraic data.
+data Sum2 a b
+        = Alt2_1 a | Alt2_2 b
+
+tagOfSum2 :: Sum2 a b -> Tag
+tagOfSum2 ss
+ = case ss of
+        Alt2_1 _        -> 0
+        Alt2_2 _        -> 1
+{-# INLINE tagOfSum2 #-}
+
+
+instance (PprPhysical a, PprPhysical b)
+        => PprPhysical (Sum2 a b) where
+ pprp ss
+  = case ss of
+        Alt2_1 x        -> text "Alt2_1" <+> pprp x
+        Alt2_2 y        -> text "Alt2_2" <+> pprp y
+
+
+-- Sum3 -----------------------------------------------------------------------
+data Sum3 a b c
+        = Alt3_1 a | Alt3_2 b | Alt3_3 c
+
+tagOfSum3 :: Sum3 a b c -> Tag
+tagOfSum3 ss
+ = case ss of
+        Alt3_1 _        -> 0
+        Alt3_2 _        -> 1
+        Alt3_3 _        -> 2
+{-# INLINE tagOfSum3 #-}
+
+
+-- 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 }
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,36 @@
+Copyright (c) 2001-2012, The DPH Team
+
+The DPH Team is:
+  Manuel M T Chakravarty
+  Gabriele Keller
+  Roman Leshchinskiy
+  Ben Lippmeier
+  George Roldugin
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+ 
+- Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+ 
+- Neither name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF
+GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+import Distribution.Simple
+main = defaultMain
+
diff --git a/dph-lifted-base.cabal b/dph-lifted-base.cabal
new file mode 100644
--- /dev/null
+++ b/dph-lifted-base.cabal
@@ -0,0 +1,65 @@
+Name:           dph-lifted-base
+Version:        0.6.0.1
+License:        BSD3
+License-File:   LICENSE
+Author:         The DPH Team
+Maintainer:     Ben Lippmeier <benl@cse.unsw.edu.au>
+Homepage:       http://www.haskell.org/haskellwiki/GHC/Data_Parallel_Haskell
+Category:       Data Structures
+Synopsis:       Data Parallel Haskell common definitions used by other dph-lifted packages.
+
+Cabal-Version:  >= 1.6
+Build-Type:     Simple
+
+Library
+  Exposed-Modules:
+        Data.Array.Parallel.PArray.Types
+        Data.Array.Parallel.PArray.Reference
+        Data.Array.Parallel.PArray
+        Data.Array.Parallel.PArr
+        
+  Exposed:
+        False
+
+  Extensions:
+        BangPatterns,
+        PatternGuards
+        TypeFamilies,
+        TypeOperators,
+        RankNTypes,
+        BangPatterns,
+        MagicHash,
+        UnboxedTuples,
+        TypeOperators,
+        FlexibleContexts,
+        FlexibleInstances,
+        EmptyDataDecls,
+        NoMonomorphismRestriction,
+        MultiParamTypeClasses,
+        EmptyDataDecls,
+        StandaloneDeriving,
+        ExplicitForAll,
+        ParallelListComp,
+        ExistentialQuantification,
+        ScopedTypeVariables,
+        PatternGuards,
+        PackageImports
+
+  GHC-Options:
+        -Odph 
+        -fcpr-off -fno-liberate-case -fno-spec-constr
+        -Wall
+        -fno-warn-missing-methods
+        -fno-warn-orphans
+
+  Build-Depends:  
+        base                    == 4.5.*,
+        ghc                     == 7.*,
+        array                   == 0.4.*,
+        random                  == 1.0.*,
+        template-haskell        == 2.7.*,
+        dph-base                == 0.6.*,
+        dph-prim-par            == 0.6.*,
+        vector                  == 0.9.*,
+        pretty                  == 1.1.*,
+        containers              == 0.4.*
