diff --git a/Data/Array/Parallel/Lifted/Closure.hs b/Data/Array/Parallel/Lifted/Closure.hs
--- a/Data/Array/Parallel/Lifted/Closure.hs
+++ b/Data/Array/Parallel/Lifted/Closure.hs
@@ -13,8 +13,8 @@
         , ($:^), liftedApply
 
         -- * Closure Construction.
-        , closure1,  closure2,  closure3,  closure4,  closure5
-        , closure1', closure2', closure3', closure4', closure5')
+        , closure1,  closure2,  closure3,  closure4,  closure5,  closure6,  closure7,  closure8
+        , closure1', closure2', closure3', closure4', closure5', closure6', closure7', closure8')
 where
 import Data.Array.Parallel.Pretty
 import Data.Array.Parallel.PArray.PData.Base
@@ -22,7 +22,12 @@
 import Data.Array.Parallel.PArray.PData.Tuple2
 import Data.Array.Parallel.PArray.PData.Tuple3
 import Data.Array.Parallel.PArray.PData.Tuple4
+import Data.Array.Parallel.PArray.PData.Tuple5
+import Data.Array.Parallel.PArray.PData.Tuple6
+import Data.Array.Parallel.PArray.PData.Tuple7
+
 import Data.Array.Parallel.PArray.PRepr
+import qualified Data.Typeable          as T
 import qualified Data.Vector            as V
 import GHC.Exts
 
@@ -48,6 +53,8 @@
                 (Int -> PData env -> PData a -> PData b)
                 env
 
+deriving instance T.Typeable2 (:->)
+
 -- | Closure application.
 ($:) :: (a :-> b) -> a -> b
 ($:) (Clo fv _fl env) x  = fv env x
@@ -210,6 +217,109 @@
 {-# INLINE_CLOSURE closure5 #-}
 
 
+
+-- | Construct an arity-6 closure
+--   from lifted and unlifted versions of a primitive function.
+closure6
+        :: forall a b c d e f g. (PA a, PA b, PA c, PA d, PA e)
+        => (a -> b -> c -> d -> e -> f -> g)
+        -> (Int -> PData a -> PData b -> PData c -> PData d -> PData e -> PData f -> PData g)
+        -> (a :-> b :-> c :-> d :-> e :-> f :-> g)
+        
+closure6 fv fl
+ = let  fv_1   _ xa                     = Clo  fv_2 fl_2 xa
+        fl_1 _ _ xs                     = AClo fv_2 fl_2 xs
+
+        fv_2   xa yb                    = Clo  fv_3 fl_3 (xa, yb)
+        fl_2 _ xs ys                    = AClo fv_3 fl_3 (PTuple2 xs ys)
+
+        fv_3 (xa, yb) zc                = Clo  fv_4 fl_4 (xa, yb, zc)
+        fl_3 _ (PTuple2 xs ys) zs       = AClo fv_4 fl_4 (PTuple3 xs ys zs)
+
+        fv_4 (wa, xb, yc) zd            = Clo  fv_5 fl_5 (wa, xb, yc, zd)
+        fl_4 _ (PTuple3 ws xs ys) zs    = AClo fv_5 fl_5 (PTuple4 ws xs ys zs)
+
+        fv_5 (va, wb, xc, yd) ze          = Clo  fv_6 fl_6 (va, wb, xc, yd, ze)
+        fl_5 _ (PTuple4 vs ws xs ys) zs   = AClo fv_6 fl_6 (PTuple5 vs ws xs ys zs)
+
+        fv_6 (ua, vb, wc, xd, ye) zf      = fv ua vb wc xd ye zf 
+        fl_6 n (PTuple5 us  vs ws xs ys) zs = fl n us vs ws xs ys zs 
+
+
+   in   Clo fv_1 fl_1 ()
+{-# INLINE_CLOSURE closure6 #-}
+
+
+-- | Construct an arity-6 closure
+--   from lifted and unlifted versions of a primitive function.
+closure7
+        :: forall a b c d e f g h. (PA a, PA b, PA c, PA d, PA e, PA f)
+        => (a -> b -> c -> d -> e -> f -> g -> h)
+        -> (Int -> PData a -> PData b -> PData c -> PData d -> PData e -> PData f -> PData g -> PData h)
+        -> (a :-> b :-> c :-> d :-> e :-> f :-> g :-> h)
+        
+closure7 fv fl
+ = let  fv_1   _ xa                     = Clo  fv_2 fl_2 xa
+        fl_1 _ _ xs                     = AClo fv_2 fl_2 xs
+
+        fv_2   xa yb                    = Clo  fv_3 fl_3 (xa, yb)
+        fl_2 _ xs ys                    = AClo fv_3 fl_3 (PTuple2 xs ys)
+
+        fv_3 (xa, yb) zc                = Clo  fv_4 fl_4 (xa, yb, zc)
+        fl_3 _ (PTuple2 xs ys) zs       = AClo fv_4 fl_4 (PTuple3 xs ys zs)
+
+        fv_4 (wa, xb, yc) zd            = Clo  fv_5 fl_5 (wa, xb, yc, zd)
+        fl_4 _ (PTuple3 ws xs ys) zs    = AClo fv_5 fl_5 (PTuple4 ws xs ys zs)
+
+        fv_5 (va, wb, xc, yd) ze          = Clo  fv_6 fl_6 (va, wb, xc, yd, ze)
+        fl_5 _ (PTuple4 vs ws xs ys) zs   = AClo fv_6 fl_6 (PTuple5 vs ws xs ys zs)
+
+        fv_6 (ua, vb, wc, xd, ye) zf        = Clo fv_7 fl_7 (ua, vb, wc, xd, ye, zf)
+        fl_6 _ (PTuple5 us  vs ws xs ys) zs = AClo fv_7 fl_7 (PTuple6 us vs ws xs ys zs)
+
+        fv_7 (ta, ub, vc, wd, xe, yf) zg      = fv ta ub vc wd xe yf zg
+        fl_7 n (PTuple6 ts us vs ws xs ys) zs = fl n ts us vs ws xs ys zs 
+
+   in   Clo fv_1 fl_1 ()
+{-# INLINE_CLOSURE closure7 #-}
+
+
+-- | Construct an arity-6 closure
+--   from lifted and unlifted versions of a primitive function.
+closure8
+        :: forall a b c d e f g h i. (PA a, PA b, PA c, PA d, PA e, PA f, PA g)
+        => (a -> b -> c -> d -> e -> f -> g -> h -> i)
+        -> (Int -> PData a -> PData b -> PData c -> PData d -> PData e -> PData f -> PData g -> PData h -> PData i)
+        -> (a :-> b :-> c :-> d :-> e :-> f :-> g :-> h :-> i)
+        
+closure8 fv fl
+ = let  fv_1   _ xa                     = Clo  fv_2 fl_2 xa
+        fl_1 _ _ xs                     = AClo fv_2 fl_2 xs
+
+        fv_2   xa yb                    = Clo  fv_3 fl_3 (xa, yb)
+        fl_2 _ xs ys                    = AClo fv_3 fl_3 (PTuple2 xs ys)
+
+        fv_3 (xa, yb) zc                = Clo  fv_4 fl_4 (xa, yb, zc)
+        fl_3 _ (PTuple2 xs ys) zs       = AClo fv_4 fl_4 (PTuple3 xs ys zs)
+
+        fv_4 (wa, xb, yc) zd            = Clo  fv_5 fl_5 (wa, xb, yc, zd)
+        fl_4 _ (PTuple3 ws xs ys) zs    = AClo fv_5 fl_5 (PTuple4 ws xs ys zs)
+
+        fv_5 (va, wb, xc, yd) ze          = Clo  fv_6 fl_6 (va, wb, xc, yd, ze)
+        fl_5 _ (PTuple4 vs ws xs ys) zs   = AClo fv_6 fl_6 (PTuple5 vs ws xs ys zs)
+
+        fv_6 (ua, vb, wc, xd, ye) zf        = Clo fv_7 fl_7 (ua, vb, wc, xd, ye, zf)
+        fl_6 _ (PTuple5 us  vs ws xs ys) zs = AClo fv_7 fl_7 (PTuple6 us vs ws xs ys zs)
+
+        fv_7 (ta, ub, vc, wd, xe, yf) zg      = Clo fv_8 fl_8 (ta, ub, vc, wd, xe, yf, zg)
+        fl_7 _ (PTuple6 ts us vs ws xs ys) zs = AClo fv_8 fl_8 (PTuple7 ts us vs ws xs ys zs) 
+
+        fv_8 (sa, tb, uc, vd, we, xf, yg) zh      = fv sa tb uc vd we xf yg zh
+        fl_8 n (PTuple7 ss ts us vs ws xs ys) zs = fl n ss ts us vs ws xs ys zs 
+
+   in   Clo fv_1 fl_1 ()
+{-# INLINE_CLOSURE closure8 #-}
+
 -- Closure constructors that take PArrays -------------------------------------
 -- These versions are useful when defining prelude functions such as in 
 -- D.A.P.Prelude.Int. They let us promote functions that work on PArrays 
@@ -297,7 +407,58 @@
    in   closure5 fv fl'
 {-# INLINE_CLOSURE closure5' #-}
 
+-- | Construct an arity-6 closure.
+closure6'
+        :: forall a b c d e f g. (PA a, PA b, PA c, PA d, PA e, PA f) 
+        => (a -> b -> c -> d -> e -> f -> g)
+        -> (PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> PArray g)
+        -> (a :-> b :-> c :-> d :-> e :-> f :-> g) 
 
+closure6' fv fl 
+ = let  {-# INLINE fl' #-}
+        fl' (I# n#) !pdata1 !pdata2 !pdata3 !pdata4 !pdata5 !pdata6
+         = case fl (PArray n# pdata1) (PArray n# pdata2) (PArray n# pdata3) (PArray n# pdata4) (PArray n# pdata5) (PArray n# pdata6) of
+                 PArray _ pdata' -> pdata'
+   in   closure6 fv fl'
+{-# INLINE_CLOSURE closure6' #-}
+
+
+
+-- | Construct an arity-7 closure.
+closure7'
+        :: forall a b c d e f g h. (PA a, PA b, PA c, PA d, PA e, PA f, PA g) 
+        => (a -> b -> c -> d -> e -> f -> g -> h)
+        -> (PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> PArray g -> PArray h)
+        -> (a :-> b :-> c :-> d :-> e :-> f :-> g :-> h) 
+
+closure7' fv fl 
+ = let  {-# INLINE fl' #-}
+        fl' (I# n#) !pdata1 !pdata2 !pdata3 !pdata4 !pdata5 !pdata6 !pdata7
+         = case fl (PArray n# pdata1) (PArray n# pdata2) (PArray n# pdata3) (PArray n# pdata4) 
+		           (PArray n# pdata5) (PArray n# pdata6) (PArray n# pdata7) of
+                 PArray _ pdata' -> pdata'
+   in   closure7 fv fl'
+{-# INLINE_CLOSURE closure7' #-}
+
+-- | Construct an arity-8 closure.
+closure8'
+        :: forall a b c d e f g h i. (PA a, PA b, PA c, PA d, PA e, PA f, PA g, PA h) 
+        => (a -> b -> c -> d -> e -> f -> g -> h -> i)
+        -> (PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> 
+		    PArray g -> PArray h -> PArray i)
+        -> (a :-> b :-> c :-> d :-> e :-> f :-> g :-> h :-> i) 
+
+closure8' fv fl 
+ = let  {-# INLINE fl' #-}
+        fl' (I# n#) !pdata1 !pdata2 !pdata3 !pdata4 !pdata5 !pdata6 !pdata7 !pdata8
+         = case fl (PArray n# pdata1) (PArray n# pdata2) (PArray n# pdata3) (PArray n# pdata4) 
+		           (PArray n# pdata5) (PArray n# pdata6) (PArray n# pdata7) (PArray n# pdata8) of
+                 PArray _ pdata' -> pdata'
+   in   closure8 fv fl'
+{-# INLINE_CLOSURE closure8' #-}
+
+
+
 -- PData instance for closures ------------------------------------------------
 -- This needs to be here instead of in a module D.A.P.PArray.PData.Closure
 -- to break an import loop.
@@ -338,7 +499,15 @@
         [ text "AClo"
         , pprpDataPA envs ]
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR (Clo _ _ env)
+        = typeRepPA env
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR (AClo _ _ envs)
+        = typeRepDataPA envs
+
+
   -- Constructors -------------------------------
   {-# INLINE_CLOSURE emptyPR #-}
   emptyPR
@@ -422,7 +591,7 @@
   -- right now. Note that the problematic functions are all constructors, and
   -- we can't know that all the parameters contain the same function.
   appendPR      = dieHetroFunctions "appendPR"
-  appendsPR     = dieHetroFunctions "appendsPR"
+  appendvsPR    = dieHetroFunctions "appendsPR"
   combine2PR    = dieHetroFunctions "combine2PR"
   fromVectorPR  = dieHetroFunctions "fromVectorPR"
   appenddPR     = dieHetroFunctions "appenddPR"
diff --git a/Data/Array/Parallel/PArray.hs b/Data/Array/Parallel/PArray.hs
--- a/Data/Array/Parallel/PArray.hs
+++ b/Data/Array/Parallel/PArray.hs
@@ -26,6 +26,7 @@
         ( PArray, PA
         , valid
         , nf
+        , typeRep
 
         -- * Constructors
         , empty
@@ -64,21 +65,23 @@
         , fromUArray,   toUArray        -- from D.A.P.PArray.Scalar
 	, fromUArray2)                  -- from D.A.P.PArray.Scalar
 where
-import qualified Data.Array.Parallel.Pretty     as T
+import Data.Array.Parallel.Trace
 import Data.Array.Parallel.PArray.PData
 import Data.Array.Parallel.PArray.PRepr
 import Data.Array.Parallel.PArray.Scalar
-import Data.Array.Parallel.PArray.Reference
+import Data.Array.Parallel.PArray.Reference.Convert
 import GHC.Exts
 import Data.Vector                              (Vector)
 import Data.Array.Parallel.Base                 (Tag)
-import qualified Data.Array.Parallel.Array      as A
-import qualified Data.Array.Parallel.Unlifted   as U
-import qualified Data.Vector                    as V
-import qualified "dph-lifted-base" Data.Array.Parallel.PArray           as R
-import qualified "dph-lifted-base" Data.Array.Parallel.PArray.Reference as R
+import qualified Data.Array.Parallel.Pretty			as T
+import qualified Data.Array.Parallel.Array			as A
+import qualified Data.Array.Parallel.Unlifted			as U
+import qualified Data.Vector					as V
+import qualified Data.Array.Parallel.PArray.Reference		as R
+import qualified Data.Array.Parallel.PArray.Reference.Convert	as R
+import Data.Typeable
 
-import qualified Prelude                        as P
+import qualified Prelude					as P
 import Prelude hiding 
         ( length, replicate, concat
         , enumFromTo
@@ -99,10 +102,6 @@
  pprp1          = pprpPA
 
 
-trace :: String -> a -> a
-trace _str x
-        = x -- Debug.Trace.trace ("! " ++ str) x
-
 -- Array -----------------------------------------------------------------------
 --  Generic interface to PArrays.
 --
@@ -142,8 +141,7 @@
 -- | Check that an array has a valid internal representation.
 valid :: PA a => PArray a -> Bool
 valid (PArray n# darr1)
- = trace "valid"
- $ validPA  darr1
+ = validPA  darr1
  && coversPA True darr1 (I# n#)
 {-# INLINE_PA valid #-}
 
@@ -151,43 +149,51 @@
 -- | Force an array to normal form.
 nf :: PA a => PArray a -> ()
 nf (PArray _ d)
- = trace "nf"
- $ nfPA d
+ = nfPA d
 {-# INLINE_PA nf #-}
 
 
--- Constructors ----------------------------------------------------------------
+-- | Get the type of a thing.
+typeRep :: PA a => a -> TypeRep
+typeRep x = typeRepPA x
+
+
+-- Empty ---------------------------------------------------------------------
 -- | O(1). An empty array.
 empty :: PA a => PArray a
 empty
  = withRef1 "empty" R.empty
  $ PArray 0# emptyPA
-
 {-# INLINE_PA empty #-}
 
 
+-- Singleton ------------------------------------------------------------------
 -- | O(1). Produce an array containing a single element.
 singleton :: PA a => a -> PArray a
 singleton x
- = withRef1 "singleton" (R.singleton x)
+ = traceOp (OpSingleton (typeRepPA x))
+ $ withRef1 "singleton" (R.singleton x)
  $ PArray 1# (replicatePA 1 x)
 {-# INLINE_PA singleton #-}
 
 
 -- | O(n). Produce an array of singleton arrays.
 singletonl :: PA a => PArray a -> PArray (PArray a)
-singletonl arr
- = withRef2 "singletonl" (R.singletonl (toRef1 arr))
+singletonl arr@(PArray n# pdata)
+ = traceOp (OpSingletonL (typeRepDataPA pdata) (I# n#))
+ $ withRef2 "singletonl" (R.singletonl (toRef1 arr))
  $ replicatel_ (replicate_ (length arr) 1) arr
 {-# INLINE_PA singletonl #-}
 
 
+-- Replicate ------------------------------------------------------------------
 -- | O(n). Define an array of the given size, that maps all elements to the same value.
 --   We require the replication count to be > 0 so that it's easier to maintain
 --   the validPR invariants for nested arrays.
 replicate :: PA a => Int -> a -> PArray a
 replicate n x
- = withRef1 "replicate" (R.replicate n x)
+ = traceOp (OpReplicate (typeRepPA x) n)
+ $ withRef1 "replicate" (R.replicate n x)
  $ replicate_ n x
 {-# INLINE_PA replicate #-}
  
@@ -199,8 +205,10 @@
 
 -- | O(sum lengths). Lifted replicate.
 replicatel :: PA a => PArray Int -> PArray a -> PArray (PArray a)
-replicatel reps arr
- = withRef2 "replicatel" (R.replicatel (toRef1 reps) (toRef1 arr))
+replicatel reps arr@(PArray n# pdata)
+ = traceOp (OpReplicateL (typeRepDataPA pdata) 
+                         (I# n#))
+ $ withRef2 "replicatel" (R.replicatel (toRef1 reps) (toRef1 arr))
  $ replicatel_ reps arr
 
 replicatel_ :: PA a => PArray Int -> PArray a -> PArray (PArray a)
@@ -217,7 +225,8 @@
 -- | O(sum lengths). Segmented replicate.
 replicates :: PA a => U.Segd -> PArray a -> PArray a
 replicates segd arr@(PArray _ pdata)
- = trace (T.render $ T.text "!!! replicates " T.$+$ T.pprp segd T.$+$ T.pprp arr)
+ = traceOp (OpReplicateS (typeRepDataPA pdata) 
+                         (U.elementsSegd segd))
  $ withRef1 "replicates" (R.replicates segd (toRef1 arr))
  $ let  !(I# n#) = U.elementsSegd segd
    in   PArray n# $ replicatesPA segd pdata
@@ -228,16 +237,18 @@
 --  and uses them to build the `U.Segd`.
 replicates' :: PA a => PArray Int -> PArray a -> PArray a
 replicates' (PArray _ (PInt reps)) arr
- = trace "replicates'"
- $ replicates (U.lengthsToSegd reps) arr
+ = replicates (U.lengthsToSegd reps) arr
 {-# INLINE_PA replicates' #-}
  
  
+-- Append ---------------------------------------------------------------------
 -- | Append two arrays.
 append :: PA a => PArray a -> PArray a -> PArray a
-append arr1@(PArray n1# darr1) arr2@(PArray n2# darr2)
- = withRef1 "append" (R.append (toRef1 arr1) (toRef1 arr2))
- $ PArray (n1# +# n2#) (appendPA darr1 darr2)
+append arr1@(PArray n1# pdata1) arr2@(PArray n2# pdata2)
+ = traceOp (OpAppend    (typeRepDataPA pdata1) 
+                        (I# n1#) (I# n2#) (I# (n1# +# n2#)))
+ $ withRef1 "append"    (R.append (toRef1 arr1) (toRef1 arr2))
+ $ PArray (n1# +# n2#)  (appendPA pdata1 pdata2)
 {-# INLINE_PA append #-}
 
 
@@ -245,33 +256,40 @@
 --   Both arrays must have the same length
 appendl :: PA a => PArray (PArray a) -> PArray (PArray a) -> PArray (PArray a)
 appendl arr1@(PArray n# pdata1) arr2@(PArray _ pdata2)
- = withRef2 "appendl" (R.appendl (toRef2 arr1) (toRef2 arr2))
+ = traceOp (OpAppendL   (typeRepDataPA pdata1)
+                        (I# n#))
+ $ withRef2 "appendl"   (R.appendl (toRef2 arr1) (toRef2 arr2))
  $ PArray n# $ appendlPA pdata1 pdata2
 {-# INLINE_PA appendl #-}
 
 
+-- Concat ---------------------------------------------------------------------
 -- | Concatenate a nested array.
 concat :: PA a => PArray (PArray a) -> PArray a
-concat arr@(PArray _ darr)
- = withRef1 "concat" (R.concat (toRef2 arr))
- $ let  darr'           = concatPA darr
-        !(I# n#)        = lengthPA darr'
-   in   PArray  n# darr'
+concat arr@(PArray n# pdata)
+ = let  pdata'          = concatPA pdata
+        !(I# n2#)       = lengthPA pdata'
+   in   traceOp (OpConcat    (typeRepDataPA pdata)
+                             (I# n#) (I# n2#))
+      $ withRef1 "concat"    (R.concat (toRef2 arr))
+      $ PArray  n2# pdata'
 {-# INLINE_PA concat #-}
 
 
 -- | Lifted concat.
 concatl :: PA a => PArray (PArray (PArray a)) -> PArray (PArray a)
-concatl arr@(PArray n# pdata1)
- = withRef2 "concatl" (R.concatl (toRef3 arr))
- $ PArray n# $ concatlPA pdata1
+concatl arr@(PArray n# pdata)
+ = traceOp (OpConcatL   (typeRepDataPA pdata)
+                        (I# n#))
+ $ withRef2 "concatl"   (R.concatl (toRef3 arr))
+ $ PArray n# $ concatlPA pdata
 {-# INLINE_PA concatl #-}
 
 
 -- | Impose a nesting structure on a flat array
 unconcat :: (PA a, PA b) => PArray (PArray a) -> PArray b -> PArray (PArray b)
 unconcat (PArray n# pdata1) (PArray _ pdata2)
- = trace "! unconcat"
+ = traceOp (OpUnconcat  (typeRepDataPA pdata1) (I# n#))
  $ PArray n# $ unconcatPA pdata1 pdata2
 {-# INLINE_PA unconcat #-}
 
@@ -299,7 +317,8 @@
 -- | Take the length of some arrays.
 lengthl :: PA a => PArray (PArray a) -> PArray Int
 lengthl arr@(PArray n# (PNested vsegd _ _ _))
- = withRef1 "lengthl" (R.lengthl (toRef2 arr))
+ = traceOp (OpLengthL (I# n#))
+ $ withRef1 "lengthl" (R.lengthl (toRef2 arr))
  $ PArray n# $ PInt $ U.takeLengthsOfVSegd vsegd
 {-# INLINE_PA lengthl #-}
 
@@ -307,7 +326,7 @@
 -- | O(1). Lookup a single element from the source array.
 index    :: PA a => PArray a -> Int -> a
 index (PArray _ arr) ix
- = trace "index"
+ = traceOp (OpIndex)
  $ indexPA arr ix
 {-# INLINE_PA index #-}
 
@@ -315,7 +334,7 @@
 -- | O(len indices). Lookup a several elements from several source arrays
 indexl    :: PA a => PArray (PArray a) -> PArray Int -> PArray a
 indexl (PArray n# darr) (PArray _ ixs)
- = trace "indexl"
+ = traceOp (OpIndexL (I# n#))
  $ PArray n# (indexlPA darr ixs)
 {-# INLINE_PA indexl #-}
 
@@ -323,7 +342,7 @@
 -- | Extract a range of elements from an array.
 extract  :: PA a => PArray a -> Int -> Int -> PArray a
 extract (PArray _ arr) start len@(I# len#)
- = trace "extract"
+ = traceOp (OpExtract (I# len#))
  $ PArray len# (extractPA arr start len)
 {-# INLINE_PA extract #-}
 
@@ -331,7 +350,7 @@
 -- | Segmented extract.
 extracts :: PA a => Vector (PArray a) -> U.SSegd -> PArray a
 extracts arrs ssegd
- = trace "extracts"
+ = traceOp (OpExtractS (U.sum $ U.lengthsOfSSegd ssegd))
  $ let  pdatas          = fromVectordPA $ V.map (\(PArray _ vec) -> vec) arrs
         !(I# n#)        = (U.sum $ U.lengthsOfSSegd ssegd)
    in   PArray   n#
@@ -353,8 +372,7 @@
         -> PArray Int           -- ^ length of each segment.
         -> PArray a
 extracts' arrs (PArray _ (PInt sources)) (PArray _ (PInt starts)) (PArray _ (PInt lengths))
- = trace "extracts'"
- $ let segd    = U.lengthsToSegd lengths
+ = let segd    = U.lengthsToSegd lengths
        ssegd   = U.mkSSegd starts sources segd
    in  extracts arrs ssegd
 {-# INLINE_PA extracts' #-}
@@ -364,7 +382,7 @@
 --   Like `extract` but with the parameters in a different order.
 slice :: PA a => Int -> Int -> PArray a -> PArray a
 slice start len@(I# len#) (PArray _ darr)
- = trace "slice"
+ = traceOp (OpSlice len)
  $ PArray len# (extractPA darr start len)
 {-# INLINE_PA slice #-}
 
@@ -374,7 +392,7 @@
 --   have the same length.
 slicel :: PA a => PArray Int -> PArray Int -> PArray (PArray a) -> PArray (PArray a)
 slicel (PArray n# sliceStarts) (PArray _ sliceLens) (PArray _ darr)
- = trace "slicel"
+ = traceOp (OpSliceL (I# n#))
  $ PArray n# (slicelPA sliceStarts sliceLens darr)
 {-# INLINE_PA slicel #-}
 
@@ -383,16 +401,16 @@
 --   plain Segd. This is unsafe because it can cause index space overflow.
 takeUSegd :: PArray (PArray a) -> U.Segd
 takeUSegd (PArray _ pdata)
- = trace "takeUSegd"
- $ takeSegdPD pdata
+ = takeSegdPD pdata
 {-# INLINE_PA takeUSegd #-}
 
 
 -- Pack and Combine -----------------------------------------------------------
 -- | Select the elements of an array that have their tag set to True.
 pack :: PA a => PArray a -> PArray Bool -> PArray a
-pack arr@(PArray _ xs) flags@(PArray _ (PBool sel2))
- = withRef1 "pack" (R.pack (toRef1 arr) (toRef1 flags))
+pack arr@(PArray _ xs) flags@(PArray len# (PBool sel2))
+ = traceOp (OpPack (I# len#))
+ $ withRef1 "pack" (R.pack (toRef1 arr) (toRef1 flags))
  $ let  darr'           = packByTagPA xs (U.tagsSel2 sel2) 1
 
         -- The selector knows how many elements are set to '1',
@@ -407,7 +425,8 @@
 packl :: PA a => PArray (PArray a) -> PArray (PArray Bool) -> PArray (PArray a)
 packl xss@(PArray n# xdata@(PNested _ _ segd _))
       fss@(PArray _  fdata)
- = withRef2 "packl" (R.packl (toRef2 xss) (toRef2 fss))
+ = traceOp (OpPackL (I# n#))
+ $ withRef2 "packl" (R.packl (toRef2 xss) (toRef2 fss))
  $ let  
         -- Concatenate both arrays to get the flat data.
         --   Although the virtual segmentation should be the same,
@@ -430,11 +449,12 @@
 
 -- | Filter an array based on some tags.
 packByTag :: PA a => PArray a -> U.Array Tag -> Tag -> PArray a
-packByTag arr@(PArray _ darr) tags tag
- = withRef1 "packByTag" (R.packByTag (toRef1 arr) tags tag)
+packByTag arr@(PArray n# darr) tags tag
+ = traceOp (OpPackByTag (I# n#))
+ $ withRef1 "packByTag" (R.packByTag (toRef1 arr) tags tag)
  $ let  darr'           = packByTagPA darr tags tag
-        !(I# n#)        = lengthPA darr'
-   in   PArray  n# darr'
+        !(I# n2#)        = lengthPA darr'
+   in   PArray  n2# darr'
 
 {-# INLINE_PA packByTag #-}
 
@@ -442,7 +462,8 @@
 -- | Combine two arrays based on a selector.
 combine2  :: forall a. PA a => U.Sel2 -> PArray a -> PArray a -> PArray a
 combine2 sel arr1@(PArray _ darr1) arr2@(PArray _ darr2)
- = withRef1 "combine2" (R.combine2 sel (toRef1 arr1) (toRef1 arr2))
+ = traceOp (OpCombine2 (U.elementsSel2_0 sel + U.elementsSel2_1 sel))
+ $ withRef1 "combine2" (R.combine2 sel (toRef1 arr1) (toRef1 arr2))
  $ let  darr'           = combine2PA sel darr1 darr2
         !(I# n#)        = lengthPA darr'
    in   PArray  n# darr'
@@ -454,7 +475,7 @@
 --   The two arrays must have the same length, else `error`. 
 zip :: PArray a -> PArray b -> PArray (a, b)
 zip (PArray n# pdata1) (PArray _ pdata2)
- = trace "zip"
+ = traceOp (OpZip (I# n#))
  $ PArray n# $ zipPD pdata1 pdata2
 {-# INLINE_PA zip #-}
 
@@ -463,7 +484,7 @@
 zipl    :: (PA a, PA b)
         => PArray (PArray a) -> PArray (PArray b) -> PArray (PArray (a, b))
 zipl (PArray n# xs) (PArray _ ys)
- = trace "zipl"
+ = traceOp (OpZipL (I# n#))
  $ PArray n# $ ziplPA xs ys
 {-# INLINE_PA zipl #-}
 
@@ -472,8 +493,7 @@
 --   All arrays must have the same length, else `error`. 
 zip3 :: PArray a -> PArray b -> PArray c -> PArray (a, b, c)
 zip3 (PArray n# pdata1) (PArray _ pdata2) (PArray _ pdata3)
- = trace "zip3"
- $ PArray n# $ zip3PD pdata1 pdata2 pdata3
+ = PArray n# $ zip3PD pdata1 pdata2 pdata3
 {-# INLINE_PA zip3 #-}
 
 
@@ -481,8 +501,7 @@
 --   All arrays must have the same length, else `error`. 
 zip4 :: PArray a -> PArray b -> PArray c -> PArray d -> PArray (a, b, c, d)
 zip4 (PArray n# pdata1) (PArray _ pdata2) (PArray _ pdata3) (PArray _ pdata4)
- = trace "zip4"
- $ PArray n# $ zip4PD pdata1 pdata2 pdata3 pdata4
+ = PArray n# $ zip4PD pdata1 pdata2 pdata3 pdata4
 {-# INLINE_PA zip4 #-}
 
 
@@ -490,23 +509,21 @@
 --   All arrays must have the same length, else `error`. 
 zip5 :: PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray (a, b, c, d, e)
 zip5 (PArray n# pdata1) (PArray _ pdata2) (PArray _ pdata3) (PArray _ pdata4) (PArray _ pdata5)
- = trace "zip5"
- $ PArray n# $ zip5PD pdata1 pdata2 pdata3 pdata4 pdata5
+ = PArray n# $ zip5PD pdata1 pdata2 pdata3 pdata4 pdata5
 {-# INLINE_PA zip5 #-}
 
 
 -- | O(1). Unzip an array of pairs into a pair of arrays.
 unzip :: PArray (a, b) -> (PArray a, PArray b)
 unzip (PArray n# (PTuple2 xs ys))
- = trace "unzip"
- $ (PArray n# xs, PArray n# ys)
+ = (PArray n# xs, PArray n# ys)
 {-# INLINE_PA unzip #-}
 
 
 -- | Lifted unzip
 unzipl :: PArray (PArray (a, b)) -> PArray (PArray a, PArray b)
 unzipl (PArray n# pdata)
- = trace "unzipl"
+ = traceOp (OpZipL (I# n#))
  $ PArray n# $ unziplPD pdata
 {-# INLINE_PA unzipl #-}
 
@@ -515,8 +532,7 @@
 -- | Convert a `Vector` to a `PArray`
 fromVector :: PA a => Vector a -> PArray a
 fromVector vec
- = trace "fromVector"
- $ let !(I# n#) = V.length vec
+ = let !(I# n#) = V.length vec
    in  PArray n#  (fromVectorPA vec)
 {-# INLINE_PA fromVector #-}
 
@@ -524,16 +540,14 @@
 -- | Convert a `PArray` to a `Vector`        
 toVector   :: PA a => PArray a -> Vector a
 toVector (PArray _ arr)
- = trace "toVector"
- $ toVectorPA arr
+ = toVectorPA arr
 {-# INLINE_PA toVector #-}
 
 
 -- | Convert a list to a `PArray`.
 fromList :: PA a => [a] -> PArray a
 fromList xx
- = trace "fromList"
- $ let  !(I# n#) = P.length xx
+ = let  !(I# n#) = P.length xx
    in   PArray n# (fromVectorPA $ V.fromList xx)
 {-# INLINE_PA fromList #-}
 
@@ -541,7 +555,6 @@
 -- | Convert a `PArray` to a list.
 toList   :: PA a => PArray a -> [a]
 toList (PArray _ arr)
- = trace "toList"
- $ V.toList $ toVectorPA arr
+ = V.toList $ toVectorPA arr
 {-# INLINE_PA toList #-}
 
diff --git a/Data/Array/Parallel/PArray/PData.hs b/Data/Array/Parallel/PArray/PData.hs
--- a/Data/Array/Parallel/PArray/PData.hs
+++ b/Data/Array/Parallel/PArray/PData.hs
@@ -22,7 +22,8 @@
         , module Data.Array.Parallel.PArray.PData.Tuple2
         , module Data.Array.Parallel.PArray.PData.Tuple3
         , module Data.Array.Parallel.PArray.PData.Tuple4
-        , module Data.Array.Parallel.PArray.PData.Tuple5)
+        , module Data.Array.Parallel.PArray.PData.Tuple5
+        , module Data.Array.Parallel.PArray.PData.Tuple6)
 where
 import Data.Array.Parallel.PArray.PData.Base
 import Data.Array.Parallel.PArray.PData.Wrap
@@ -31,6 +32,8 @@
 import Data.Array.Parallel.PArray.PData.Tuple3
 import Data.Array.Parallel.PArray.PData.Tuple4
 import Data.Array.Parallel.PArray.PData.Tuple5
+import Data.Array.Parallel.PArray.PData.Tuple6
+import Data.Array.Parallel.PArray.PData.Tuple7
 import Data.Array.Parallel.PArray.PData.Void            ()
 import Data.Array.Parallel.PArray.PData.Unit            ()
 import Data.Array.Parallel.PArray.PData.Int             ()
diff --git a/Data/Array/Parallel/PArray/PData/Base.hs b/Data/Array/Parallel/PArray/PData/Base.hs
--- a/Data/Array/Parallel/PArray/PData/Base.hs
+++ b/Data/Array/Parallel/PArray/PData/Base.hs
@@ -21,8 +21,10 @@
 import Data.Array.Parallel.Base                 (Tag)
 import qualified Data.Array.Parallel.Unlifted   as U
 import qualified Data.Vector                    as V
+import qualified Data.Typeable                  as T
 import Prelude hiding (length)
 
+
 -- PArray ---------------------------------------------------------------------
 -- | A parallel array consisting of a length field and some array data.
 
@@ -37,6 +39,9 @@
 data PArray a
         = PArray Int# (PData  a)
 
+deriving instance T.Typeable1 PArray
+
+
 -- | Take the length field of a `PArray`.
 {-# INLINE_PA length #-}
 length :: PArray a -> Int
@@ -126,7 +131,18 @@
   -- | (debugging) Pretty print the physical representation of some array data.
   pprpDataPR    :: PData a -> Doc
 
+  -- | (debugging) Get the representation of this type.
+  --   We don't use the Typeable class for this because the vectoriser
+  --   won't handle the Typeable superclass on PR.
+  typeRepPR      :: a        -> T.TypeRep
 
+  -- | (debugging) Given a 'PData a' get the representation of the 'a'
+  typeRepDataPR  :: PData  a -> T.TypeRep
+
+  -- | (debugging) Given a 'PDatas a' get the representation of the 'a'
+  typeRepDatasPR :: PDatas a -> T.TypeRep
+
+
   -- Constructors -------------------------------
   -- | Produce an empty array with size zero.
   emptyPR       :: PData a
@@ -160,9 +176,9 @@
   --
   --   The first descriptor defines the segmentation of the result, 
   --   and the others define the segmentation of each source array.
-  appendsPR     :: U.Segd
-                -> U.Segd -> PData a
-                -> U.Segd -> PData a
+  appendvsPR    :: U.Segd
+                -> U.VSegd -> PDatas a
+                -> U.VSegd -> PDatas a
                 -> PData a
 
 
diff --git a/Data/Array/Parallel/PArray/PData/Double.hs b/Data/Array/Parallel/PArray/PData/Double.hs
--- a/Data/Array/Parallel/PArray/PData/Double.hs
+++ b/Data/Array/Parallel/PArray/PData/Double.hs
@@ -12,6 +12,7 @@
 import Data.Array.Parallel.PArray.PData.Nested
 import qualified Data.Array.Parallel.Unlifted   as U
 import qualified Data.Vector                    as V
+import qualified Data.Typeable                  as T
 
 
 -------------------------------------------------------------------------------
@@ -50,7 +51,16 @@
    =   text "PDouble"
    <+> text (show $ U.toList vec)
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x           = T.typeOf x
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR _       = T.typeOf (5 :: Double)
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR _      = T.typeOf (5 :: Double)
+
+
   -- Constructors -------------------------------
   {-# INLINE_PDATA emptyPR #-}
   emptyPR
@@ -68,9 +78,9 @@
   appendPR (PDouble arr1) (PDouble arr2)
         = PDouble $ arr1 U.+:+ arr2
 
-  {-# INLINE_PDATA appendsPR #-}
-  appendsPR segdResult segd1 (PDouble arr1) segd2 (PDouble arr2)
-        = PDouble $ U.append_s segdResult segd1 arr1 segd2 arr2
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult segd1 (PDoubles arr1) segd2 (PDoubles arr2)
+        = PDouble $ U.append_vs segdResult segd1 arr1 segd2 arr2
 
 
   -- Projections --------------------------------                
diff --git a/Data/Array/Parallel/PArray/PData/Int.hs b/Data/Array/Parallel/PArray/PData/Int.hs
--- a/Data/Array/Parallel/PArray/PData/Int.hs
+++ b/Data/Array/Parallel/PArray/PData/Int.hs
@@ -5,6 +5,7 @@
 -- | PR instance for Ints
 module Data.Array.Parallel.PArray.PData.Int () where
 import Data.Array.Parallel.PArray.PData.Base
+import Data.Typeable                            as T
 import qualified Data.Array.Parallel.Unlifted   as U
 import qualified Data.Vector                    as V
 import Text.PrettyPrint
@@ -39,7 +40,16 @@
   pprpDataPR (PInt uarr)
    =    text "PInt" <+> pprp uarr
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x           = T.typeOf x
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR _       = T.typeOf (5 :: Int)
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR _      = T.typeOf (5 :: Int)
+
+
   -- Constructors -------------------------------
   {-# INLINE_PDATA emptyPR #-}
   emptyPR
@@ -57,9 +67,9 @@
   appendPR (PInt arr1) (PInt arr2)
         = PInt $ arr1 U.+:+ arr2
 
-  {-# INLINE_PDATA appendsPR #-}
-  appendsPR segdResult segd1 (PInt arr1) segd2 (PInt arr2)
-        = PInt $ U.append_s segdResult segd1 arr1 segd2 arr2
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult segd1 (PInts arr1) segd2 (PInts arr2)
+        = PInt $ U.append_vs segdResult segd1 arr1 segd2 arr2
 
 
   -- Projections --------------------------------                
diff --git a/Data/Array/Parallel/PArray/PData/Nested.hs b/Data/Array/Parallel/PArray/PData/Nested.hs
--- a/Data/Array/Parallel/PArray/PData/Nested.hs
+++ b/Data/Array/Parallel/PArray/PData/Nested.hs
@@ -18,10 +18,12 @@
 where
 import Data.Array.Parallel.Base
 import Data.Array.Parallel.Pretty
+import Data.Array.Parallel.PArray.PData.Unit
 import Data.Array.Parallel.PArray.PData.Base    as PA
 import qualified Data.IntSet                    as IS
 import qualified Data.Array.Parallel.Unlifted   as U
 import qualified Data.Vector                    as V
+import qualified Data.Typeable                  as T
 import GHC.Exts
 import System.IO.Unsafe
 
@@ -47,7 +49,9 @@
           --   then it should stash it here, otherwise build a thunk that makes it.
         }
 
+deriving instance T.Typeable1 PData
 
+
 -- TODO: should we unpack the vsegd fields here?
 data instance PDatas (PArray a)
         = PNesteds (V.Vector (PData (PArray a)))
@@ -197,7 +201,31 @@
         $+$ ( nest 4
             $ pprp vsegd $$ pprp pdatas)
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR arr@(PArray _ pdata)
+        = T.typeOf1 arr
+                `T.mkAppTy` typeRepDataPR pdata
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR (PNested _ pdatas _ _)
+        = T.typeOf1 (PArray 0# (emptyPR :: PData ()))
+                `T.mkAppTy` typeRepDatasPR pdatas
+
+  {-# NOINLINE typeRepDatasPR #-}
+  -- CAREFUL: 
+  --  Our generics setup turns implicitly recursive types in the source
+  --  program (defined via data type declarations) into explicitly recursive
+  --  ones in the Core program. If there is no data in the PNesteds then we
+  --  can't continue printing the type. An empty vector may have an infinite
+  --  type, and we could loop forever. This happens in the Barnes-Hut benchmark,
+  --  due to the recursive tree structure.
+  typeRepDatasPR (PNesteds vec)
+        = T.typeOf1 (PArray 0# (emptyPR :: PData ()))
+                `T.mkAppTy` (if V.length vec == 0 
+                                then T.typeOf ()
+                                else typeRepDataPR (vec V.! 0))
+
+
   -- Constructors -----------------------------------------
   {-# INLINE_PDATA emptyPR #-}
   emptyPR = PNested U.emptyVSegd emptydPR U.emptySegd emptyPR
@@ -256,38 +284,82 @@
   -- Performing segmented append requires segments from the physical arrays to
   -- be interspersed, so we need to copy data from the second level of nesting.  
   --
-  -- In the implementation we can safely flatten out replication in the vsegs
-  -- because the source program result would have this same physical size
-  -- anyway. Once this is done we use copying segmented append on the flat 
-  -- arrays, and then reconstruct the segment descriptor.
+  -- Each element of @xarr@ is a @PData (PArray a)@, and contains a vector of @PData a@.
+  -- We collect all the @PData a@s in @xarr@ and @yarr@ into one vector,
+  -- then do segmented append (@U.append_vs@) for the lengths and starts.
   --
-  {-# NOINLINE appendsPR #-}
-  appendsPR rsegd segd1 xarr segd2 yarr
-   = let (xsegd, xs)    = flattenPR xarr
-         (ysegd, ys)    = flattenPR yarr
-   
-         xsegd' = U.lengthsToSegd 
-                $ U.sum_s segd1 (U.lengthsSegd xsegd)
-                
-         ysegd' = U.lengthsToSegd
-                $ U.sum_s segd2 (U.lengthsSegd ysegd)
-                
+  -- The sources are segmented append of the input sources summed with the
+  -- scan of the length of each @PDatas a@ in @xarr@ and @yarr@,
+  -- to find the index into the concatenated source arrays.
+  {-# NOINLINE appendvsPR #-}
+  appendvsPR rsegd segd1 (PNesteds xarr) segd2 (PNesteds yarr)
+   = let 
+         -- lengths of flattened segments
+         flen           = U.lengthsSegd . takeSegdPD
+         xlens          = U.fromVectors $ V.map flen xarr
+         ylens          = U.fromVectors $ V.map flen yarr
+
+         -- scattered segment starts
+         fstart         = U.startsOfSSegd . U.takeSSegdOfVSegd . pnested_uvsegd
+         xstarts        = U.fromVectors $ V.map fstart xarr
+         ystarts        = U.fromVectors $ V.map fstart yarr
+
+         -- input sources (without sum of scan)
+         fsource        = U.sourcesOfSSegd . U.takeSSegdOfVSegd . pnested_uvsegd
+         xsources       = U.fromVectors $ V.map fsource xarr
+         ysources       = U.fromVectors $ V.map fsource yarr
+
+         -- data arrays, the result will have these concatenated
+         -- scan of lengths is used to generate new source indices
+         fdata          = toVectordPR . pnested_psegdata
+         xdata          = V.map fdata xarr
+         ydata          = V.map fdata yarr
+
+         -- why does V.concat take list, not vector?
+         ccat   = V.concatMap id
+
+         -- concatenate input data arrays
+         datas' = fromVectordPR (ccat xdata V.++ ccat ydata)
+
+         -- get data lengths to generate new source indices
+         xdatalens = V.map V.length xdata
+         ydatalens = V.map V.length ydata
+
+         -- increase each source by scan so far
+         getsrc srcs inc = U.map (+inc) srcs
+
+         -- increase x's sources by scan of lengths
+         xsrc'  = U.fromVectors $ V.zipWith getsrc (U.toVectors xsources)
+                $ V.prescanl (+) 0 xdatalens
+
+         -- increase y's sources, starting from sum of xdatalens
+         ysrc'  = U.fromVectors $ V.zipWith getsrc (U.toVectors ysources)
+                $ V.prescanl (+) (V.sum xdatalens) ydatalens
+
+
+         -- segmented append to get new sources, lengths, and starts.
+         -- TODO: would be nice if append_vs could do triples.
+         src'   = U.append_vs rsegd segd1 xsrc'
+                                    segd2 ysrc'
+
          segd'  = U.lengthsToSegd
-                $ U.append_s rsegd segd1 (U.lengthsSegd xsegd)
-                                   segd2 (U.lengthsSegd ysegd)
+                $ U.append_vs rsegd segd1 xlens
+                                    segd2 ylens
 
+         start' = U.append_vs rsegd segd1 xstarts
+                                    segd2 ystarts
 
-         -- The pdatas only contains a single flat chunk.
-         vsegd'  = U.promoteSegdToVSegd segd'
-         flat'   = appendsPR (U.plusSegd xsegd' ysegd')
-                            xsegd' xs
-                            ysegd' ys
+         -- generate vseg with new sources etc
+         vsegd' = U.promoteSSegdToVSegd
+                $ U.mkSSegd start' src' segd'
 
-         pdatas' = singletondPR flat'
+         -- lazy flattening of data
+         flat'  = extractvs_delay datas' vsegd'
 
-     in  PNested vsegd' pdatas' segd' flat'
+     in PNested vsegd' datas' segd' flat'
 
 
+
   -- Projections ------------------------------------------
   {-# INLINE_PDATA lengthPR #-}
   lengthPR (PNested vsegd _ _ _)
@@ -651,13 +723,13 @@
 -- | Lifted append.
 --   Both arrays must contain the same number of elements.
 appendlPR :: PR a => PData (PArray a) -> PData (PArray a) -> PData (PArray a)
-appendlPR  arr1 arr2
- = let  (segd1, darr1)  = flattenPR arr1
-        (segd2, darr2)  = flattenPR arr2
+appendlPR  arr1@(PNested vsegd1 darr1 _ _) arr2@(PNested vsegd2 darr2 _ _)
+ = let  segd1           = takeSegdPD arr1
+        segd2           = takeSegdPD arr2
         segd'           = U.plusSegd segd1 segd2
         vsegd'          = U.promoteSegdToVSegd segd'
 
-        flat'           = appendsPR segd' segd1 darr1 segd2 darr2
+        flat'           = appendvsPR segd' vsegd1 darr1 vsegd2 darr2
         pdatas'         = singletondPR flat'
    in   PNested vsegd' pdatas' segd' flat'
 {-# INLINE_PDATA appendlPR #-}
diff --git a/Data/Array/Parallel/PArray/PData/Sum2.hs b/Data/Array/Parallel/PArray/PData/Sum2.hs
--- a/Data/Array/Parallel/PArray/PData/Sum2.hs
+++ b/Data/Array/Parallel/PArray/PData/Sum2.hs
@@ -15,10 +15,12 @@
 import Data.Array.Parallel.Base                 (intToTag)
 import Data.Array.Parallel.Unlifted             as U
 import qualified Data.Vector                    as V
+import qualified Data.Typeable                  as T
 import Text.PrettyPrint
 import Prelude                                  as P
 import Data.Array.Parallel.Pretty
 
+
 -------------------------------------------------------------------------------
 data instance PData (Sum2 a b)
         = PSum2  U.Sel2
@@ -76,6 +78,24 @@
         [ pprp sel
         , text "ALTS0: " <+> pprp pdatas1
         , text "ALTS1: " <+> pprp pdatas2])
+
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR ss
+   = case ss of
+        Alt2_1 x -> T.typeOf2 ss `T.mkAppTy` typeRepPR x `T.mkAppTy` typeRepPR x
+        Alt2_2 y -> T.typeOf2 ss `T.mkAppTy` typeRepPR y `T.mkAppTy` typeRepPR y
+
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR (PSum2 _ xs ys)
+   = T.typeOf2 (Alt2_1 ())
+        `T.mkAppTy` typeRepDataPR xs 
+        `T.mkAppTy` typeRepDataPR ys
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR (PSum2s _ pdatas1 pdatas2)
+   = T.typeOf2 (Alt2_1 ())
+        `T.mkAppTy` typeRepDatasPR pdatas1
+        `T.mkAppTy` typeRepDatasPR pdatas2
 
 
   -- Constructors -------------------------------
diff --git a/Data/Array/Parallel/PArray/PData/Tuple2.hs b/Data/Array/Parallel/PArray/PData/Tuple2.hs
--- a/Data/Array/Parallel/PArray/PData/Tuple2.hs
+++ b/Data/Array/Parallel/PArray/PData/Tuple2.hs
@@ -15,10 +15,12 @@
 import Data.Array.Parallel.PArray.PData.Nested
 import GHC.Exts
 import Prelude hiding (zip, unzip)
+import qualified Data.Array.Parallel.Unlifted   as U
 import qualified Data.Vector                    as V
+import qualified Data.Typeable                  as T
 import qualified Prelude                        as P
-import qualified Data.Array.Parallel.Unlifted   as U
 
+
 -------------------------------------------------------------------------------
 data instance PData (a, b)
         = PTuple2  (PData a)  (PData b)
@@ -60,6 +62,25 @@
   pprpDataPR (PTuple2 xs ys)
         = text "PTuple2 " <> vcat [pprpDataPR xs, pprpDataPR ys]
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x@(a, b)
+        = T.typeOf2 x 
+                `T.mkAppTy` (typeRepPR a)
+                `T.mkAppTy` (typeRepPR b)
+
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR (PTuple2 xs ys)
+        = T.typeOf2 ((), ())
+                `T.mkAppTy` (typeRepDataPR xs)
+                `T.mkAppTy` (typeRepDataPR ys)
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR (PTuple2s xs ys)
+        = T.typeOf2 ((), ())
+                `T.mkAppTy` (typeRepDatasPR xs)
+                `T.mkAppTy` (typeRepDatasPR ys)
+
+
   -- Constructors -------------------------------
   {-# INLINE_PDATA emptyPR #-}
   emptyPR
@@ -84,10 +105,10 @@
                   (arr12 `appendPR` arr22)
 
 
-  {-# INLINE_PDATA appendsPR #-}
-  appendsPR segdResult segd1 (PTuple2 arrs11 arrs12) segd2 (PTuple2 arrs21 arrs22)
-        = PTuple2 (appendsPR segdResult segd1 arrs11 segd2 arrs21)
-                  (appendsPR segdResult segd1 arrs12 segd2 arrs22)
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult segd1 (PTuple2s arrs11 arrs12) segd2 (PTuple2s arrs21 arrs22)
+        = PTuple2 (appendvsPR segdResult segd1 arrs11 segd2 arrs21)
+                  (appendvsPR segdResult segd1 arrs12 segd2 arrs22)
 
 
   -- Projections ---------------------------------
diff --git a/Data/Array/Parallel/PArray/PData/Tuple3.hs b/Data/Array/Parallel/PArray/PData/Tuple3.hs
--- a/Data/Array/Parallel/PArray/PData/Tuple3.hs
+++ b/Data/Array/Parallel/PArray/PData/Tuple3.hs
@@ -12,6 +12,7 @@
 import Data.Array.Parallel.PArray.PData.Nested
 import GHC.Exts
 import Prelude hiding (zip, unzip)
+import qualified Data.Typeable                  as T
 import qualified Data.Vector                    as V
 import qualified Prelude                        as P
 
@@ -64,7 +65,28 @@
                 , pprpDataPR ys
                 , pprpDataPR zs]
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x@(a, b, c)
+        = T.typeOf3 x 
+                `T.mkAppTy` (typeRepPR a)
+                `T.mkAppTy` (typeRepPR b)
+                `T.mkAppTy` (typeRepPR c)
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR (PTuple3 as bs cs)
+        = T.typeOf3 ((), (), ())
+                `T.mkAppTy` (typeRepDataPR as)
+                `T.mkAppTy` (typeRepDataPR bs)
+                `T.mkAppTy` (typeRepDataPR cs)
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR (PTuple3s as bs cs)
+        = T.typeOf3 ((), (), ())
+                `T.mkAppTy` (typeRepDatasPR as)
+                `T.mkAppTy` (typeRepDatasPR bs)
+                `T.mkAppTy` (typeRepDatasPR cs)
+
+
   -- Constructors -------------------------------
   {-# INLINE_PDATA emptyPR #-}
   emptyPR
@@ -92,11 +114,11 @@
                   (arr13 `appendPR` arr23) 
 
 
-  {-# INLINE_PDATA appendsPR #-}
-  appendsPR segdResult segd1 (PTuple3 arrs11 arrs12 arrs13) segd2 (PTuple3 arrs21 arrs22 arrs23)
-        = PTuple3 (appendsPR segdResult segd1 arrs11 segd2 arrs21)
-                  (appendsPR segdResult segd1 arrs12 segd2 arrs22)
-                  (appendsPR segdResult segd1 arrs13 segd2 arrs23)
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult segd1 (PTuple3s arrs11 arrs12 arrs13) segd2 (PTuple3s arrs21 arrs22 arrs23)
+        = PTuple3 (appendvsPR segdResult segd1 arrs11 segd2 arrs21)
+                  (appendvsPR segdResult segd1 arrs12 segd2 arrs22)
+                  (appendvsPR segdResult segd1 arrs13 segd2 arrs23)
 
 
   -- Projections ---------------------------------
diff --git a/Data/Array/Parallel/PArray/PData/Tuple4.hs b/Data/Array/Parallel/PArray/PData/Tuple4.hs
--- a/Data/Array/Parallel/PArray/PData/Tuple4.hs
+++ b/Data/Array/Parallel/PArray/PData/Tuple4.hs
@@ -12,6 +12,7 @@
 import Data.Array.Parallel.PArray.PData.Nested
 import GHC.Exts
 import Prelude hiding (zip, unzip)
+import qualified Data.Typeable                  as T
 import qualified Data.Vector                    as V
 import qualified Prelude                        as P
 import qualified Data.List                      as P
@@ -70,7 +71,31 @@
                 , pprpDataPR zs
                 , pprpDataPR ds]
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x@(a, b, c, d)
+        = T.typeOf4 x 
+                `T.mkAppTy` (typeRepPR a)
+                `T.mkAppTy` (typeRepPR b)
+                `T.mkAppTy` (typeRepPR c)
+                `T.mkAppTy` (typeRepPR d)
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR (PTuple4 as bs cs ds)
+        = T.typeOf4 ((), (), (), ())
+                `T.mkAppTy` (typeRepDataPR as)
+                `T.mkAppTy` (typeRepDataPR bs)
+                `T.mkAppTy` (typeRepDataPR cs)
+                `T.mkAppTy` (typeRepDataPR ds)
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR (PTuple4s as bs cs ds)
+        = T.typeOf4 ((), (), (), ())
+                `T.mkAppTy` (typeRepDatasPR as)
+                `T.mkAppTy` (typeRepDatasPR bs)
+                `T.mkAppTy` (typeRepDatasPR cs)
+                `T.mkAppTy` (typeRepDatasPR ds)
+
+
   -- Constructors -------------------------------
   {-# INLINE_PDATA emptyPR #-}
   emptyPR
@@ -102,13 +127,13 @@
                   (arr14 `appendPR` arr24) 
 
 
-  {-# INLINE_PDATA appendsPR #-}
-  appendsPR segdResult segd1 (PTuple4 arrs11 arrs12 arrs13 arrs14)
-                       segd2 (PTuple4 arrs21 arrs22 arrs23 arrs24)
-        = PTuple4 (appendsPR segdResult segd1 arrs11 segd2 arrs21)
-                  (appendsPR segdResult segd1 arrs12 segd2 arrs22)
-                  (appendsPR segdResult segd1 arrs13 segd2 arrs23)
-                  (appendsPR segdResult segd1 arrs14 segd2 arrs24)
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult segd1 (PTuple4s arrs11 arrs12 arrs13 arrs14)
+                       segd2 (PTuple4s arrs21 arrs22 arrs23 arrs24)
+        = PTuple4 (appendvsPR segdResult segd1 arrs11 segd2 arrs21)
+                  (appendvsPR segdResult segd1 arrs12 segd2 arrs22)
+                  (appendvsPR segdResult segd1 arrs13 segd2 arrs23)
+                  (appendvsPR segdResult segd1 arrs14 segd2 arrs24)
 
 
   -- Projections ---------------------------------
diff --git a/Data/Array/Parallel/PArray/PData/Tuple5.hs b/Data/Array/Parallel/PArray/PData/Tuple5.hs
--- a/Data/Array/Parallel/PArray/PData/Tuple5.hs
+++ b/Data/Array/Parallel/PArray/PData/Tuple5.hs
@@ -12,6 +12,7 @@
 import Data.Array.Parallel.PArray.PData.Nested
 import GHC.Exts
 import Prelude hiding (zip, unzip)
+import qualified Data.Typeable                  as T
 import qualified Data.Vector                    as V
 import qualified Prelude                        as P
 import qualified Data.List                      as P
@@ -74,7 +75,34 @@
                 , pprpDataPR ds
                 , pprpDataPR es]
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x@(a, b, c, d, e)
+        = T.typeOf5 x 
+                `T.mkAppTy` (typeRepPR a)
+                `T.mkAppTy` (typeRepPR b)
+                `T.mkAppTy` (typeRepPR c)
+                `T.mkAppTy` (typeRepPR d)
+                `T.mkAppTy` (typeRepPR e)
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR (PTuple5 as bs cs ds es)
+        = T.typeOf5 ((), (), (), (), ())
+                `T.mkAppTy` (typeRepDataPR as)
+                `T.mkAppTy` (typeRepDataPR bs)
+                `T.mkAppTy` (typeRepDataPR cs)
+                `T.mkAppTy` (typeRepDataPR ds)
+                `T.mkAppTy` (typeRepDataPR es)
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR (PTuple5s as bs cs ds es)
+        = T.typeOf5 ((), (), (), (), ())
+                `T.mkAppTy` (typeRepDatasPR as)
+                `T.mkAppTy` (typeRepDatasPR bs)
+                `T.mkAppTy` (typeRepDatasPR cs)
+                `T.mkAppTy` (typeRepDatasPR ds)
+                `T.mkAppTy` (typeRepDatasPR es)
+
+
   -- Constructors -------------------------------
   {-# INLINE_PDATA emptyPR #-}
   emptyPR
@@ -109,14 +137,14 @@
                   (arr15 `appendPR` arr25) 
 
 
-  {-# INLINE_PDATA appendsPR #-}
-  appendsPR segdResult segd1 (PTuple5 arrs11 arrs12 arrs13 arrs14 arrs15)
-                       segd2 (PTuple5 arrs21 arrs22 arrs23 arrs24 arrs25)
-        = PTuple5 (appendsPR segdResult segd1 arrs11 segd2 arrs21)
-                  (appendsPR segdResult segd1 arrs12 segd2 arrs22)
-                  (appendsPR segdResult segd1 arrs13 segd2 arrs23)
-                  (appendsPR segdResult segd1 arrs14 segd2 arrs24)
-                  (appendsPR segdResult segd1 arrs15 segd2 arrs25)
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult segd1 (PTuple5s arrs11 arrs12 arrs13 arrs14 arrs15)
+                       segd2 (PTuple5s arrs21 arrs22 arrs23 arrs24 arrs25)
+        = PTuple5 (appendvsPR segdResult segd1 arrs11 segd2 arrs21)
+                  (appendvsPR segdResult segd1 arrs12 segd2 arrs22)
+                  (appendvsPR segdResult segd1 arrs13 segd2 arrs23)
+                  (appendvsPR segdResult segd1 arrs14 segd2 arrs24)
+                  (appendvsPR segdResult segd1 arrs15 segd2 arrs25)
 
 
   -- Projections ---------------------------------
diff --git a/Data/Array/Parallel/PArray/PData/Tuple6.hs b/Data/Array/Parallel/PArray/PData/Tuple6.hs
new file mode 100644
--- /dev/null
+++ b/Data/Array/Parallel/PArray/PData/Tuple6.hs
@@ -0,0 +1,362 @@
+{-# OPTIONS_HADDOCK hide #-}
+{-# LANGUAGE CPP #-}
+#include "fusion-phases.h"
+
+-- | PR instance for tuples.
+module Data.Array.Parallel.PArray.PData.Tuple6
+        ( PData(..),    PDatas(..)
+        , zip6PD)
+where
+import Data.Array.Parallel.Pretty
+import Data.Array.Parallel.PArray.PData.Base
+import Data.Array.Parallel.PArray.PData.Nested
+import GHC.Exts
+import Prelude hiding (zip, unzip)
+import qualified Data.Typeable                  as T
+import qualified Data.Vector                    as V
+import qualified Prelude                        as P
+import qualified Data.List                      as P
+
+-------------------------------------------------------------------------------
+data instance PData (a, b, c, d, e, f)
+        = PTuple6  (PData a)  (PData b)  (PData c)  (PData d)  (PData e) (PData f)
+
+data instance PDatas (a, b, c, d, e, f)
+        = PTuple6s (PDatas a) (PDatas b) (PDatas c) (PDatas d) (PDatas e) (PDatas f)
+
+
+-- PR -------------------------------------------------------------------------
+instance (PR a, PR b, PR c, PR d, PR e, PR f) => PR (a, b, c, d, e, f) where
+
+  {-# NOINLINE validPR #-}
+  validPR (PTuple6 xs ys zs ds es fs)
+        = validPR xs && validPR ys && validPR zs && validPR ds && validPR es && validPR fs
+
+
+  {-# NOINLINE nfPR #-}
+  nfPR (PTuple6 arr1 arr2 arr3 arr4 arr5 arr6)
+        = nfPR arr1 `seq` nfPR arr2 `seq` nfPR arr3 `seq` nfPR arr4 `seq` nfPR arr5 `seq` nfPR arr6 `seq` ()
+
+
+  {-# NOINLINE similarPR #-}
+  similarPR (x1, y1, z1, d1, e1, f1) (x2, y2, z2, d2, e2, f2)
+        =  similarPR x1 x2
+        && similarPR y1 y2
+        && similarPR z1 z2
+        && similarPR d1 d2
+        && similarPR e1 e2
+        && similarPR f1 f2
+        
+
+
+  {-# NOINLINE coversPR #-}
+  coversPR weak (PTuple6 arr1 arr2 arr3 arr4 arr5 arr6) ix
+        =  coversPR weak arr1 ix
+        && coversPR weak arr2 ix
+        && coversPR weak arr3 ix
+        && coversPR weak arr4 ix
+        && coversPR weak arr5 ix
+        && coversPR weak arr6 ix
+
+
+  {-# NOINLINE pprpPR #-}
+  pprpPR (x, y, z, d, e, f)
+        = text "Tuple6 "
+        <> vcat [ pprpPR x
+                , pprpPR y
+                , pprpPR z
+                , pprpPR d
+                , pprpPR e
+                , pprpPR f ]
+        
+
+  {-# NOINLINE pprpDataPR #-}
+  pprpDataPR (PTuple6 xs ys zs ds es fs)
+        = text "PTuple6 " 
+        <> vcat [ pprpDataPR xs
+                , pprpDataPR ys
+                , pprpDataPR zs
+                , pprpDataPR ds
+                , pprpDataPR es
+                , pprpDataPR fs]
+
+
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x@(a, b, c, d, e, f)
+        = T.typeOf6 x 
+                `T.mkAppTy` (typeRepPR a)
+                `T.mkAppTy` (typeRepPR b)
+                `T.mkAppTy` (typeRepPR c)
+                `T.mkAppTy` (typeRepPR d)
+                `T.mkAppTy` (typeRepPR e)
+                `T.mkAppTy` (typeRepPR f)
+
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR (PTuple6 as bs cs ds es fs)
+        = T.typeOf6 ((), (), (), (), (), ())
+                `T.mkAppTy` (typeRepDataPR as)
+                `T.mkAppTy` (typeRepDataPR bs)
+                `T.mkAppTy` (typeRepDataPR cs)
+                `T.mkAppTy` (typeRepDataPR ds)
+                `T.mkAppTy` (typeRepDataPR es)
+                `T.mkAppTy` (typeRepDataPR fs)
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR (PTuple6s as bs cs ds es fs)
+        = T.typeOf6 ((), (), (), (), (), ())
+                `T.mkAppTy` (typeRepDatasPR as)
+                `T.mkAppTy` (typeRepDatasPR bs)
+                `T.mkAppTy` (typeRepDatasPR cs)
+                `T.mkAppTy` (typeRepDatasPR ds)
+                `T.mkAppTy` (typeRepDatasPR es)
+                `T.mkAppTy` (typeRepDatasPR fs)
+
+
+  -- Constructors -------------------------------
+  {-# INLINE_PDATA emptyPR #-}
+  emptyPR
+        = PTuple6 emptyPR emptyPR emptyPR emptyPR emptyPR emptyPR
+
+
+  {-# INLINE_PDATA replicatePR #-}
+  replicatePR len (x, y, z, d, e, f)
+        = PTuple6 (replicatePR len x)
+                  (replicatePR len y)
+                  (replicatePR len z)
+                  (replicatePR len d)
+                  (replicatePR len e)
+                  (replicatePR len f)
+
+
+  {-# INLINE_PDATA replicatesPR #-}
+  replicatesPR lens (PTuple6 arr1 arr2 arr3 arr4 arr5 arr6)
+        = PTuple6 (replicatesPR lens arr1)
+                  (replicatesPR lens arr2)
+                  (replicatesPR lens arr3)
+                  (replicatesPR lens arr4)
+                  (replicatesPR lens arr5)
+                  (replicatesPR lens arr6)
+
+
+  {-# INLINE_PDATA appendPR #-}
+  appendPR (PTuple6 arr11 arr12 arr13 arr14 arr15 arr16)
+           (PTuple6 arr21 arr22 arr23 arr24 arr25 arr26)
+        = PTuple6 (arr11 `appendPR` arr21)
+                  (arr12 `appendPR` arr22)
+                  (arr13 `appendPR` arr23) 
+                  (arr14 `appendPR` arr24) 
+                  (arr15 `appendPR` arr25) 
+                  (arr16 `appendPR` arr26) 
+
+
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult segd1 (PTuple6s arrs11 arrs12 arrs13 arrs14 arrs15 arrs16)
+                       segd2 (PTuple6s arrs21 arrs22 arrs23 arrs24 arrs25 arrs26)
+        = PTuple6 (appendvsPR segdResult segd1 arrs11 segd2 arrs21)
+                  (appendvsPR segdResult segd1 arrs12 segd2 arrs22)
+                  (appendvsPR segdResult segd1 arrs13 segd2 arrs23)
+                  (appendvsPR segdResult segd1 arrs14 segd2 arrs24)
+                  (appendvsPR segdResult segd1 arrs15 segd2 arrs25)
+                  (appendvsPR segdResult segd1 arrs16 segd2 arrs26)
+
+
+  -- Projections ---------------------------------
+  {-# INLINE_PDATA lengthPR #-}
+  lengthPR (PTuple6 arr1 _ _ _ _ _) 
+        = lengthPR arr1
+  
+  {-# INLINE_PDATA indexPR #-}
+  indexPR (PTuple6 arr1 arr2 arr3 arr4 arr5 arr6) ix
+        = ( indexPR arr1 ix
+          , indexPR arr2 ix
+          , indexPR arr3 ix
+          , indexPR arr4 ix
+          , indexPR arr5 ix
+          , indexPR arr6 ix)
+
+
+  {-# INLINE_PDATA indexsPR #-}
+  indexsPR (PTuple6s xs ys zs ds es fs) srcixs
+        = PTuple6 (indexsPR xs srcixs)
+                  (indexsPR ys srcixs)
+                  (indexsPR zs srcixs)
+                  (indexsPR ds srcixs)
+                  (indexsPR es srcixs)
+                  (indexsPR fs srcixs)
+
+  {-# INLINE_PDATA indexvsPR #-}
+  indexvsPR (PTuple6s xs ys zs ds es fs) vsegd srcixs
+        = PTuple6 (indexvsPR xs vsegd srcixs)
+                  (indexvsPR ys vsegd srcixs)
+                  (indexvsPR zs vsegd srcixs)
+                  (indexvsPR ds vsegd srcixs)
+                  (indexvsPR es vsegd srcixs)
+                  (indexvsPR fs vsegd srcixs)
+
+  {-# INLINE_PDATA extractPR #-}
+  extractPR (PTuple6 arr1 arr2 arr3 arr4 arr5 arr6) start len
+        = PTuple6 (extractPR arr1 start len) 
+                  (extractPR arr2 start len)
+                  (extractPR arr3 start len)
+                  (extractPR arr4 start len)
+                  (extractPR arr5 start len)
+                  (extractPR arr6 start len)
+
+  {-# INLINE_PDATA extractssPR #-}
+  extractssPR (PTuple6s xs ys zs ds es fs) ussegd
+        = PTuple6 (extractssPR xs ussegd)
+                  (extractssPR ys ussegd)
+                  (extractssPR zs ussegd)
+                  (extractssPR ds ussegd)
+                  (extractssPR es ussegd)
+                  (extractssPR fs ussegd)
+
+  {-# INLINE_PDATA extractvsPR #-}
+  extractvsPR (PTuple6s xs ys zs ds es fs) uvsegd
+        = PTuple6 (extractvsPR xs uvsegd)
+                  (extractvsPR ys uvsegd)
+                  (extractvsPR zs uvsegd)
+                  (extractvsPR ds uvsegd)
+                  (extractvsPR es uvsegd)
+                  (extractvsPR fs uvsegd)
+
+
+  -- Pack and Combine ---------------------------
+  {-# INLINE_PDATA packByTagPR #-}
+  packByTagPR (PTuple6 arr1 arr2 arr3 arr4 arr5 arr6) tags tag
+        = PTuple6 (packByTagPR arr1 tags tag)
+                  (packByTagPR arr2 tags tag)
+                  (packByTagPR arr3 tags tag)
+                  (packByTagPR arr4 tags tag)
+                  (packByTagPR arr5 tags tag)
+                  (packByTagPR arr6 tags tag)
+
+
+  {-# INLINE_PDATA combine2PR #-}
+  combine2PR sel (PTuple6 xs1 ys1 zs1 ds1 es1 fs1) (PTuple6 xs2 ys2 zs2 ds2 es2 fs2)
+        = PTuple6 (combine2PR sel xs1 xs2)
+                  (combine2PR sel ys1 ys2)
+                  (combine2PR sel zs1 zs2)
+                  (combine2PR sel ds1 ds2)
+                  (combine2PR sel es1 es2)
+                  (combine2PR sel fs1 fs2)
+
+
+  -- Conversions --------------------------------
+  {-# NOINLINE fromVectorPR #-}
+  fromVectorPR vec
+   = let (xs, ys, zs, ds, es, fs)       = V.unzip6 vec
+     in  PTuple6  (fromVectorPR xs)
+                  (fromVectorPR ys)
+                  (fromVectorPR zs)
+                  (fromVectorPR ds)
+                  (fromVectorPR es)
+                  (fromVectorPR fs)
+
+  {-# NOINLINE toVectorPR #-}
+  toVectorPR (PTuple6 xs ys zs ds es fs)
+        = V.zip6  (toVectorPR xs)
+                  (toVectorPR ys)
+                  (toVectorPR zs)
+                  (toVectorPR ds)
+                  (toVectorPR es)
+                  (toVectorPR fs)
+
+
+  -- PData --------------------------------------
+  {-# INLINE_PDATA emptydPR #-}
+  emptydPR      
+        = PTuple6s emptydPR
+                   emptydPR
+                   emptydPR 
+                   emptydPR 
+                   emptydPR 
+                   emptydPR 
+
+  
+  {-# INLINE_PDATA singletondPR #-}
+  singletondPR (PTuple6 x y z d e f)
+        = PTuple6s (singletondPR x)
+                   (singletondPR y)
+                   (singletondPR z)
+                   (singletondPR d)
+                   (singletondPR e)
+                   (singletondPR f)
+
+
+  {-# INLINE_PDATA lengthdPR #-}
+  lengthdPR (PTuple6s xs _ _ _ _ _)
+        = lengthdPR xs
+   
+   
+  {-# INLINE_PDATA indexdPR #-}
+  indexdPR (PTuple6s xs ys zs ds es fs) i
+        = PTuple6  (indexdPR xs i)
+                   (indexdPR ys i)
+                   (indexdPR zs i)
+                   (indexdPR ds i)
+                   (indexdPR es i)
+                   (indexdPR fs i)
+
+   
+  {-# INLINE_PDATA appenddPR #-}
+  appenddPR (PTuple6s xs1 ys1 zs1 ds1 es1 fs1) (PTuple6s xs2 ys2 zs2 ds2 es2 fs2)
+        = PTuple6s (appenddPR xs1 xs2)
+                   (appenddPR ys1 ys2)
+                   (appenddPR zs1 zs2)
+                   (appenddPR ds1 ds2)
+                   (appenddPR es1 es2)
+                   (appenddPR fs1 fs2)
+  
+
+  {-# NOINLINE fromVectordPR #-}
+  fromVectordPR vec
+   = let (xss, yss, zss, dss, ess, fss) = V.unzip6 $ V.map (\(PTuple6 xs ys zs ds es fs) -> (xs, ys, zs, ds, es, fs)) vec
+     in  PTuple6s  (fromVectordPR xss)
+                   (fromVectordPR yss)
+                   (fromVectordPR zss)
+                   (fromVectordPR dss)
+                   (fromVectordPR ess)
+                   (fromVectordPR fss)
+
+
+  {-# NOINLINE toVectordPR #-}
+  toVectordPR (PTuple6s pdatas1 pdatas2 pdatas3 pdatas4 pdatas5 pdatas6)
+        = V.zipWith6 PTuple6
+                   (toVectordPR pdatas1)
+                   (toVectordPR pdatas2)
+                   (toVectordPR pdatas3)
+                   (toVectordPR pdatas4)
+                   (toVectordPR pdatas5)
+                   (toVectordPR pdatas6)
+
+
+-- PD Functions ---------------------------------------------------------------
+-- | O(1). Zip a pair of arrays into an array of pairs.
+zip6PD   :: PData a -> PData b -> PData c -> PData d -> PData e -> PData f -> PData (a, b, c, d, e, f)
+zip6PD   = PTuple6
+{-# INLINE_PA zip6PD #-}
+
+
+-- Show -----------------------------------------------------------------------
+deriving instance (Show (PData  a), Show (PData  b), Show (PData c), Show (PData d), Show (PData e), Show (PData f))
+        => Show (PData  (a, b, c, d, e, f))
+
+deriving instance (Show (PDatas a), Show (PDatas b), Show (PDatas c), Show (PDatas d), Show (PDatas e), Show (PDatas f))
+        => Show (PDatas (a, b, c, d, e, f))
+
+
+instance ( PR a, PR b, PR c, PR d, PR e, PR f, Show a, Show b, Show c, Show d, Show e, Show f
+         , PprVirtual (PData a), PprVirtual (PData b), PprVirtual (PData c), PprVirtual (PData d), PprVirtual (PData e), PprVirtual (PData f))
+        => PprVirtual (PData (a, b, c, d, e, f)) where
+ pprv   (PTuple6 xs ys zs ds es fs)
+        = text $ show 
+        $ P.zip6 (V.toList $ toVectorPR xs) 
+                 (V.toList $ toVectorPR ys)
+                 (V.toList $ toVectorPR zs)
+                 (V.toList $ toVectorPR ds)
+                 (V.toList $ toVectorPR es)
+                 (V.toList $ toVectorPR fs)
+
+                 
+                 
diff --git a/Data/Array/Parallel/PArray/PData/Tuple7.hs b/Data/Array/Parallel/PArray/PData/Tuple7.hs
new file mode 100644
--- /dev/null
+++ b/Data/Array/Parallel/PArray/PData/Tuple7.hs
@@ -0,0 +1,483 @@
+{-# OPTIONS_HADDOCK hide #-}
+{-# LANGUAGE CPP #-}
+#include "fusion-phases.h"
+
+-- | PR instance for tuples.
+module Data.Array.Parallel.PArray.PData.Tuple7
+        ( PData(..),    PDatas(..)
+        , zip7PD)
+where
+import Data.Array.Parallel.Pretty
+import Data.Array.Parallel.PArray.PData.Base
+import Data.Array.Parallel.PArray.PData.Nested
+import GHC.Exts
+import Prelude hiding (zip, unzip)
+import qualified Data.Typeable                  as T
+import qualified Data.Vector                    as V
+import qualified Prelude                        as P
+import qualified Data.List                      as P
+
+
+-- The following are only imported for zip7,
+-- remove once that's where it's supposed to be
+import qualified Data.Vector as DV
+import qualified Data.Vector.Fusion.Stream.Monadic  as MS 
+import qualified Data.Vector.Generic                as G
+import Data.Vector.Fusion.Stream (inplace)
+
+-------------------------------------------------------------------------------
+data instance PData (a, b, c, d, e, f, g)
+        = PTuple7  (PData a)  (PData b)  (PData c)  (PData d)  (PData e) (PData f) (PData g)
+
+data instance PDatas (a, b, c, d, e, f, g)
+        = PTuple7s (PDatas a) (PDatas b) (PDatas c) (PDatas d) (PDatas e) (PDatas f) (PDatas g)
+
+
+-- PR -------------------------------------------------------------------------
+instance (PR a, PR b, PR c, PR d, PR e, PR f, PR g) => PR (a, b, c, d, e, f, g) where
+
+  {-# NOINLINE validPR #-}
+  validPR (PTuple7 xs ys zs ds es fs gs)
+        = validPR xs && validPR ys && validPR zs && validPR ds && validPR es && validPR fs && validPR gs
+
+
+  {-# NOINLINE nfPR #-}
+  nfPR (PTuple7 arr1 arr2 arr3 arr4 arr5 arr6 arr7)
+        = nfPR arr1 `seq` nfPR arr2 `seq` nfPR arr3 `seq` nfPR arr4 `seq` nfPR arr5 `seq` 
+          nfPR arr6 `seq` nfPR arr7 `seq` ()
+
+
+  {-# NOINLINE similarPR #-}
+  similarPR (x1, y1, z1, d1, e1, f1, g1) (x2, y2, z2, d2, e2, f2, g2)
+        =  similarPR x1 x2
+        && similarPR y1 y2
+        && similarPR z1 z2
+        && similarPR d1 d2
+        && similarPR e1 e2
+        && similarPR f1 f2
+        && similarPR g1 g2
+        
+
+  {-# NOINLINE coversPR #-}
+  coversPR weak (PTuple7 arr1 arr2 arr3 arr4 arr5 arr6 arr7) ix
+        =  coversPR weak arr1 ix
+        && coversPR weak arr2 ix
+        && coversPR weak arr3 ix
+        && coversPR weak arr4 ix
+        && coversPR weak arr5 ix
+        && coversPR weak arr6 ix
+        && coversPR weak arr7 ix
+
+
+  {-# NOINLINE pprpPR #-}
+  pprpPR (x, y, z, d, e, f, g)
+        = text "Tuple7 "
+        <> vcat [ pprpPR x
+                , pprpPR y
+                , pprpPR z
+                , pprpPR d
+                , pprpPR e
+                , pprpPR f
+                , pprpPR g]
+        
+
+  {-# NOINLINE pprpDataPR #-}
+  pprpDataPR (PTuple7 xs ys zs ds es fs gs)
+        = text "PTuple7 " 
+        <> vcat [ pprpDataPR xs
+                , pprpDataPR ys
+                , pprpDataPR zs
+                , pprpDataPR ds
+                , pprpDataPR es
+                , pprpDataPR fs
+                , pprpDataPR gs]
+
+
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x@(a, b, c, d, e, f, g)
+        = T.typeOf7 x 
+                `T.mkAppTy` (typeRepPR a)
+                `T.mkAppTy` (typeRepPR b)
+                `T.mkAppTy` (typeRepPR c)
+                `T.mkAppTy` (typeRepPR d)
+                `T.mkAppTy` (typeRepPR e)
+                `T.mkAppTy` (typeRepPR f)
+                `T.mkAppTy` (typeRepPR g)
+
+
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR (PTuple7 as bs cs ds es fs gs)
+        = T.typeOf7 ((), (), (), (), (), (), ())
+                `T.mkAppTy` (typeRepDataPR as)
+                `T.mkAppTy` (typeRepDataPR bs)
+                `T.mkAppTy` (typeRepDataPR cs)
+                `T.mkAppTy` (typeRepDataPR ds)
+                `T.mkAppTy` (typeRepDataPR es)
+                `T.mkAppTy` (typeRepDataPR fs)
+                `T.mkAppTy` (typeRepDataPR gs)
+
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR (PTuple7s as bs cs ds es fs gs)
+        = T.typeOf7 ((), (), (), (), (), (), ())
+                `T.mkAppTy` (typeRepDatasPR as)
+                `T.mkAppTy` (typeRepDatasPR bs)
+                `T.mkAppTy` (typeRepDatasPR cs)
+                `T.mkAppTy` (typeRepDatasPR ds)
+                `T.mkAppTy` (typeRepDatasPR es)
+                `T.mkAppTy` (typeRepDatasPR fs)
+                `T.mkAppTy` (typeRepDatasPR gs)
+
+
+  -- Constructors -------------------------------
+  {-# INLINE_PDATA emptyPR #-}
+  emptyPR
+        = PTuple7 emptyPR emptyPR emptyPR emptyPR emptyPR emptyPR emptyPR
+
+
+  {-# INLINE_PDATA replicatePR #-}
+  replicatePR len (x, y, z, d, e, f, g)
+        = PTuple7 (replicatePR len x)
+                  (replicatePR len y)
+                  (replicatePR len z)
+                  (replicatePR len d)
+                  (replicatePR len e)
+                  (replicatePR len f)
+                  (replicatePR len g)
+
+
+  {-# INLINE_PDATA replicatesPR #-}
+  replicatesPR lens (PTuple7 arr1 arr2 arr3 arr4 arr5 arr6 arr7)
+        = PTuple7 (replicatesPR lens arr1)
+                  (replicatesPR lens arr2)
+                  (replicatesPR lens arr3)
+                  (replicatesPR lens arr4)
+                  (replicatesPR lens arr5)
+                  (replicatesPR lens arr6)
+                  (replicatesPR lens arr7)
+
+
+  {-# INLINE_PDATA appendPR #-}
+  appendPR (PTuple7 arr11 arr12 arr13 arr14 arr15 arr16 arr17)
+           (PTuple7 arr21 arr22 arr23 arr24 arr25 arr26 arr27)
+        = PTuple7 (arr11 `appendPR` arr21)
+                  (arr12 `appendPR` arr22)
+                  (arr13 `appendPR` arr23) 
+                  (arr14 `appendPR` arr24) 
+                  (arr15 `appendPR` arr25) 
+                  (arr16 `appendPR` arr26) 
+                  (arr17 `appendPR` arr27) 
+
+
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult segd1 (PTuple7s arrs11 arrs12 arrs13 arrs14 arrs15 arrs16 arrs17)
+                       segd2 (PTuple7s arrs21 arrs22 arrs23 arrs24 arrs25 arrs26 arrs27)
+        = PTuple7 (appendvsPR segdResult segd1 arrs11 segd2 arrs21)
+                  (appendvsPR segdResult segd1 arrs12 segd2 arrs22)
+                  (appendvsPR segdResult segd1 arrs13 segd2 arrs23)
+                  (appendvsPR segdResult segd1 arrs14 segd2 arrs24)
+                  (appendvsPR segdResult segd1 arrs15 segd2 arrs25)
+                  (appendvsPR segdResult segd1 arrs16 segd2 arrs26)
+                  (appendvsPR segdResult segd1 arrs17 segd2 arrs27)
+
+  -- Projections ---------------------------------
+  {-# INLINE_PDATA lengthPR #-}
+  lengthPR (PTuple7 arr1 _ _ _ _ _ _) 
+        = lengthPR arr1
+  
+  {-# INLINE_PDATA indexPR #-}
+  indexPR (PTuple7 arr1 arr2 arr3 arr4 arr5 arr6 arr7) ix
+        = ( indexPR arr1 ix
+          , indexPR arr2 ix
+          , indexPR arr3 ix
+          , indexPR arr4 ix
+          , indexPR arr5 ix
+          , indexPR arr6 ix
+          , indexPR arr7 ix)
+
+
+  {-# INLINE_PDATA indexsPR #-}
+  indexsPR (PTuple7s xs ys zs ds es fs gs) srcixs
+        = PTuple7 (indexsPR xs srcixs)
+                  (indexsPR ys srcixs)
+                  (indexsPR zs srcixs)
+                  (indexsPR ds srcixs)
+                  (indexsPR es srcixs)
+                  (indexsPR fs srcixs)
+                  (indexsPR gs srcixs)
+
+  {-# INLINE_PDATA indexvsPR #-}
+  indexvsPR (PTuple7s xs ys zs ds es fs gs) vsegd srcixs
+        = PTuple7 (indexvsPR xs vsegd srcixs)
+                  (indexvsPR ys vsegd srcixs)
+                  (indexvsPR zs vsegd srcixs)
+                  (indexvsPR ds vsegd srcixs)
+                  (indexvsPR es vsegd srcixs)
+                  (indexvsPR fs vsegd srcixs)
+                  (indexvsPR gs vsegd srcixs)
+
+  {-# INLINE_PDATA extractPR #-}
+  extractPR (PTuple7 arr1 arr2 arr3 arr4 arr5 arr6 arr7) start len
+        = PTuple7 (extractPR arr1 start len) 
+                  (extractPR arr2 start len)
+                  (extractPR arr3 start len)
+                  (extractPR arr4 start len)
+                  (extractPR arr5 start len)
+                  (extractPR arr6 start len)
+                  (extractPR arr7 start len)
+
+  {-# INLINE_PDATA extractssPR #-}
+  extractssPR (PTuple7s xs ys zs ds es fs gs) ussegd
+        = PTuple7 (extractssPR xs ussegd)
+                  (extractssPR ys ussegd)
+                  (extractssPR zs ussegd)
+                  (extractssPR ds ussegd)
+                  (extractssPR es ussegd)
+                  (extractssPR fs ussegd)
+                  (extractssPR gs ussegd)
+
+  {-# INLINE_PDATA extractvsPR #-}
+  extractvsPR (PTuple7s xs ys zs ds es fs gs) uvsegd
+        = PTuple7 (extractvsPR xs uvsegd)
+                  (extractvsPR ys uvsegd)
+                  (extractvsPR zs uvsegd)
+                  (extractvsPR ds uvsegd)
+                  (extractvsPR es uvsegd)
+                  (extractvsPR fs uvsegd)
+                  (extractvsPR gs uvsegd)
+
+
+  -- Pack and Combine ---------------------------
+  {-# INLINE_PDATA packByTagPR #-}
+  packByTagPR (PTuple7 arr1 arr2 arr3 arr4 arr5 arr6 arr7) tags tag
+        = PTuple7 (packByTagPR arr1 tags tag)
+                  (packByTagPR arr2 tags tag)
+                  (packByTagPR arr3 tags tag)
+                  (packByTagPR arr4 tags tag)
+                  (packByTagPR arr5 tags tag)
+                  (packByTagPR arr6 tags tag)
+                  (packByTagPR arr7 tags tag)
+
+
+  {-# INLINE_PDATA combine2PR #-}
+  combine2PR sel (PTuple7 xs1 ys1 zs1 ds1 es1 fs1 gs1) (PTuple7 xs2 ys2 zs2 ds2 es2 fs2 gs2)
+        = PTuple7 (combine2PR sel xs1 xs2)
+                  (combine2PR sel ys1 ys2)
+                  (combine2PR sel zs1 zs2)
+                  (combine2PR sel ds1 ds2)
+                  (combine2PR sel es1 es2)
+                  (combine2PR sel fs1 fs2)
+                  (combine2PR sel gs1 gs2)
+
+
+  -- Conversions --------------------------------
+  {-# NOINLINE fromVectorPR #-}
+  fromVectorPR vec
+   = let (xs, ys, zs, ds, es, fs, gs)       = unzip7 vec
+     in  PTuple7  (fromVectorPR xs)
+                  (fromVectorPR ys)
+                  (fromVectorPR zs)
+                  (fromVectorPR ds)
+                  (fromVectorPR es)
+                  (fromVectorPR fs)
+                  (fromVectorPR gs)
+
+  {-# NOINLINE toVectorPR #-}
+  toVectorPR (PTuple7 xs ys zs ds es fs gs)
+        =    zip7  (toVectorPR xs)
+                   (toVectorPR ys)
+                   (toVectorPR zs)
+                   (toVectorPR ds)
+                   (toVectorPR es)
+                   (toVectorPR fs)
+                   (toVectorPR gs)
+
+
+  -- PData --------------------------------------
+  {-# INLINE_PDATA emptydPR #-}
+  emptydPR      
+        = PTuple7s emptydPR
+                   emptydPR
+                   emptydPR 
+                   emptydPR 
+                   emptydPR 
+                   emptydPR
+                   emptydPR 
+
+  
+  {-# INLINE_PDATA singletondPR #-}
+  singletondPR (PTuple7 x y z d e f g)
+        = PTuple7s (singletondPR x)
+                   (singletondPR y)
+                   (singletondPR z)
+                   (singletondPR d)
+                   (singletondPR e)
+                   (singletondPR f)
+                   (singletondPR g)
+
+
+  {-# INLINE_PDATA lengthdPR #-}
+  lengthdPR (PTuple7s xs _ _ _ _ _ _)
+        = lengthdPR xs
+   
+   
+  {-# INLINE_PDATA indexdPR #-}
+  indexdPR (PTuple7s xs ys zs ds es fs gs) i
+        = PTuple7  (indexdPR xs i)
+                   (indexdPR ys i)
+                   (indexdPR zs i)
+                   (indexdPR ds i)
+                   (indexdPR es i)
+                   (indexdPR fs i)
+                   (indexdPR gs i)
+
+   
+  {-# INLINE_PDATA appenddPR #-}
+  appenddPR (PTuple7s xs1 ys1 zs1 ds1 es1 fs1 gs1) (PTuple7s xs2 ys2 zs2 ds2 es2 fs2 gs2)
+        = PTuple7s (appenddPR xs1 xs2)
+                   (appenddPR ys1 ys2)
+                   (appenddPR zs1 zs2)
+                   (appenddPR ds1 ds2)
+                   (appenddPR es1 es2)
+                   (appenddPR fs1 fs2)
+                   (appenddPR gs1 gs2)
+  
+
+  {-# NOINLINE fromVectordPR #-}
+  fromVectordPR vec
+   = let (xss, yss, zss, dss, ess, fss, gss) = unzip7 $ V.map (\(PTuple7 xs ys zs ds es fs gs) -> (xs, ys, zs, ds, es, fs, gs)) vec
+     in  PTuple7s  (fromVectordPR xss)
+                   (fromVectordPR yss)
+                   (fromVectordPR zss)
+                   (fromVectordPR dss)
+                   (fromVectordPR ess)
+                   (fromVectordPR fss)
+                   (fromVectordPR gss)
+
+
+  {-# NOINLINE toVectordPR #-}
+  toVectordPR (PTuple7s pdatas1 pdatas2 pdatas3 pdatas4 pdatas5 pdatas6 pdatas7)
+        = zipWith7 PTuple7
+                   (toVectordPR pdatas1)
+                   (toVectordPR pdatas2)
+                   (toVectordPR pdatas3)
+                   (toVectordPR pdatas4)
+                   (toVectordPR pdatas5)
+                   (toVectordPR pdatas6)
+                   (toVectordPR pdatas7)
+
+
+-- PD Functions ---------------------------------------------------------------
+-- | O(1). Zip a pair of arrays into an array of pairs.
+zip7PD   :: PData a -> PData b -> PData c -> PData d -> PData e -> PData f -> PData g -> PData (a, b, c, d, e, f, g)
+zip7PD   = PTuple7
+{-# INLINE_PA zip7PD #-}
+
+
+-- Show -----------------------------------------------------------------------
+deriving instance (Show (PData  a), Show (PData  b), Show (PData c), Show (PData d), Show (PData e), Show (PData f), Show (PData g))
+        => Show (PData  (a, b, c, d, e, f, g))
+
+deriving instance (Show (PDatas a), Show (PDatas b), Show (PDatas c), Show (PDatas d), Show (PDatas e), Show (PDatas f), Show (PDatas g))
+        => Show (PDatas (a, b, c, d, e, f, g))
+
+
+instance ( PR a, PR b, PR c, PR d, PR e, PR f, PR g, Show a, Show b, Show c, Show d, Show e, Show f, Show g
+         , PprVirtual (PData a), PprVirtual (PData b), PprVirtual (PData c), PprVirtual (PData d), PprVirtual (PData e), PprVirtual (PData f), PprVirtual (PData g))
+        => PprVirtual (PData (a, b, c, d, e, f, g)) where
+ pprv   (PTuple7 xs ys zs ds es fs gs)
+        = text $ show 
+        $ P.zip7 (V.toList $ toVectorPR xs) 
+                 (V.toList $ toVectorPR ys)
+                 (V.toList $ toVectorPR zs)
+                 (V.toList $ toVectorPR ds)
+                 (V.toList $ toVectorPR es)
+                 (V.toList $ toVectorPR fs)
+                 (V.toList $ toVectorPR gs)
+
+                 
+-- zips and related functions -------------------------------------------------
+-- should be in Data.Vector
+
+zipWith7MS :: Monad m => (a -> b -> c -> d -> e -> f -> g -> h)
+                    -> MS.Stream m a -> MS.Stream m b -> MS.Stream m c -> MS.Stream m d
+                    -> MS.Stream m e -> MS.Stream m f -> MS.Stream m g -> MS.Stream m h
+{-# INLINE zipWith7MS #-}
+zipWith7MS fn = zipWith7M (\a b c d e f g -> return (fn a b c d e f g))
+
+
+zipWith7Generic :: (G.Vector v a, G.Vector v b, G.Vector v c, G.Vector v d, G.Vector v e,
+             G.Vector v f, G.Vector v g, G.Vector v h)
+         => (a -> b -> c -> d -> e -> f -> g -> h)
+         -> v a -> v b -> v c -> v d -> v e -> v f -> v g -> v h
+{-# INLINE zipWith7Generic #-}
+zipWith7Generic f as bs cs ds es fs gs
+  = G.unstream (zipWith7MS f (G.stream as)
+                          (G.stream bs)
+                          (G.stream cs)
+                          (G.stream ds)
+                          (G.stream es)
+                          (G.stream fs)
+                          (G.stream gs))
+zip7Generic :: (G.Vector v a, G.Vector v b, G.Vector v c, G.Vector v d, G.Vector v e,
+         G.Vector v f, G.Vector v g, G.Vector v (a, b, c, d, e, f, g))
+     => v a -> v b -> v c -> v d -> v e -> v f -> v g -> v (a, b, c, d, e, f, g)
+{-# INLINE zip7Generic #-}
+zip7Generic = zipWith7Generic (,,,,,,)
+
+unzip7Generic :: (G.Vector v a, G.Vector v b, G.Vector v c, G.Vector v d, G.Vector v e,
+           G.Vector v f, G.Vector v g, G.Vector v (a, b, c, d, e, f, g))
+       => v (a, b, c, d, e, f, g) -> (v a, v b, v c, v d, v e, v f, v g)
+{-# INLINE unzip7Generic #-}
+unzip7Generic xs = 
+            (mapG (\(a, _b, _c, _d, _e, _f, _g) -> a) xs,
+             mapG (\(_a, b, _c, _d, _e, _f, _g) -> b) xs,
+             mapG (\(_a, _b, c, _d, _e, _f, _g) -> c) xs,
+             mapG (\(_a, _b, _c, d, _e, _f, _g) -> d) xs,
+             mapG (\(_a, _b, _c, _d, e, _f, _g) -> e) xs,
+             mapG (\(_a, _b, _c, _d, _e, f, _g) -> f) xs,
+             mapG (\(_a, _b, _c, _d, _e, _f, g) -> g) xs)
+  where
+    -- | /O(n)/ Map a function over a vector
+    mapG :: (G.Vector v a, G.Vector v b) => (a -> b) -> v a -> v b
+    {-# INLINE mapG #-}
+    mapG f = G.unstream . inplace (MS.map f) . G.stream
+
+zipWith7M :: Monad m => (a -> b -> c -> d -> e -> f -> g -> m h)
+                     -> MS.Stream m a -> MS.Stream m b -> MS.Stream m c -> MS.Stream m d
+                     -> MS.Stream m e -> MS.Stream m f -> MS.Stream m g -> MS.Stream m h
+{-# INLINE zipWith7M #-}
+zipWith7M fn sa sb sc sd se sf sg
+  = MS.zipWithM (\(a,b,c) (d,e,(f, g)) -> fn a b c d e f g) (MS.zip3 sa sb sc)
+                                                  (MS.zip3 sd se (MS.zip sf sg))
+
+{-}                                                  
+zipWith7Monad :: Monad m => (a -> b -> c -> d -> e -> f -> g -> h)
+                    -> MS.Stream m a -> MS.Stream m b -> MS.Stream m c -> MS.Stream m d
+                    -> MS.Stream m e -> MS.Stream m f -> MS.Stream m g -> MS.Stream m h
+{-# INLINE zipWith7Monad #-}
+zipWith7Monad fn = zipWith7M (\a b c d e f g -> return (fn a b c d e f g))
+
+
+
+zip7Monad :: Monad m => MS.Stream m a -> MS.Stream m b -> MS.Stream m c -> MS.Stream m d
+                -> MS.Stream m e -> MS.Stream m f -> MS.Stream m g -> MS.Stream m (a,b,c,d,e,f,g)
+{-# INLINE zip7Monad #-}
+zip7Monad = zipWith7Monad (,,,,,,)
+-}
+
+zip7 :: DV.Vector a -> DV.Vector b -> DV.Vector c -> DV.Vector d -> DV.Vector e -> DV.Vector f -> DV.Vector g
+     -> DV.Vector (a, b, c, d, e, f, g)
+{-# INLINE zip7 #-}
+zip7 = zip7Generic
+
+unzip7 :: DV.Vector (a, b, c, d, e, f, g)
+       -> (DV.Vector a, DV.Vector b, DV.Vector c, DV.Vector d, DV.Vector e, DV.Vector f, DV.Vector g)
+{-# INLINE unzip7 #-}
+unzip7 = unzip7Generic
+
+zipWith7 :: (a -> b -> c -> d -> e -> f -> g -> h)
+         -> DV.Vector a -> DV.Vector b -> DV.Vector c -> DV.Vector d -> DV.Vector e
+         -> DV.Vector f -> DV.Vector g -> DV.Vector h
+{-# INLINE zipWith7 #-}
+zipWith7 = zipWith7Generic
diff --git a/Data/Array/Parallel/PArray/PData/Unit.hs b/Data/Array/Parallel/PArray/PData/Unit.hs
--- a/Data/Array/Parallel/PArray/PData/Unit.hs
+++ b/Data/Array/Parallel/PArray/PData/Unit.hs
@@ -8,6 +8,7 @@
 import Data.Array.Parallel.Pretty
 import qualified Data.Array.Parallel.Unlifted   as U
 import qualified Data.Vector                    as V
+import qualified Data.Typeable                  as T
 
 -------------------------------------------------------------------------------
 -- | TODO: For arrays of units, we're currently maintaining their length so
@@ -52,7 +53,19 @@
   pprpDataPR uu
         = text $ show uu
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x
+        = T.typeOf x
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR _
+        = T.typeOf ()
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR _
+        = T.typeOf ()
+
+
   -- Constructors -------------------------------
   {-# INLINE_PDATA emptyPR #-}
   emptyPR
@@ -70,8 +83,8 @@
   appendPR (PUnit len1) (PUnit len2)
         = PUnit (len1 + len2)
 
-  {-# INLINE_PDATA appendsPR #-}
-  appendsPR segdResult _ _ _ _
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult _ _ _ _
         = PUnit (U.lengthSegd segdResult)
 
 
@@ -153,6 +166,7 @@
   {-# NOINLINE toVectordPR #-}
   toVectordPR (PUnits uvecs)
         = V.map PUnit $ V.convert uvecs
+
 
 -- Show -----------------------------------------------------------------------
 deriving instance Show (PData  ())
diff --git a/Data/Array/Parallel/PArray/PData/Void.hs b/Data/Array/Parallel/PArray/PData/Void.hs
--- a/Data/Array/Parallel/PArray/PData/Void.hs
+++ b/Data/Array/Parallel/PArray/PData/Void.hs
@@ -10,6 +10,7 @@
 import Data.Array.Parallel.PArray.PRepr.Base    ()
 import Data.Array.Parallel.PArray.Types
 import Data.Array.Parallel.Pretty
+import qualified Data.Typeable                  as T
 import qualified Data.Vector                    as V
 
 -------------------------------------------------------------------------------
@@ -63,7 +64,17 @@
   {-# NOINLINE pprpDataPR #-}
   pprpDataPR _    = text "pvoid"
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x     = T.typeOf x
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR _
+        = T.typeOf (error "typeRepDataPR:  void proxy" :: Void)
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR _
+        = T.typeOf (error "typeRepDatasPR: void proxy" :: Void)
+
   -- Constructors -------------------------------        
   {-# INLINE_PDATA emptyPR #-}
   emptyPR       = nope "emptyPR"
@@ -77,8 +88,8 @@
   {-# INLINE_PDATA appendPR #-}
   appendPR      = nope "append"
   
-  {-# INLINE_PDATA appendsPR #-}
-  appendsPR     = nope "appends"
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR     = nope "appendvs"
 
 
   -- Projections --------------------------------
diff --git a/Data/Array/Parallel/PArray/PData/Word8.hs b/Data/Array/Parallel/PArray/PData/Word8.hs
--- a/Data/Array/Parallel/PArray/PData/Word8.hs
+++ b/Data/Array/Parallel/PArray/PData/Word8.hs
@@ -5,12 +5,12 @@
 -- | PR instance for Word8.
 module Data.Array.Parallel.PArray.PData.Word8 where
 import Data.Array.Parallel.PArray.PData.Base
+import Data.Array.Parallel.Pretty
+import Data.Word
+import qualified Data.Typeable                  as T
 import qualified Data.Array.Parallel.Unlifted   as U
 import qualified Data.Vector                    as V
-import Text.PrettyPrint
 import Prelude                                  as P
-import Data.Word
-import Data.Array.Parallel.Pretty
 
 -------------------------------------------------------------------------------
 data instance PData Word8
@@ -47,7 +47,19 @@
   pprpDataPR (PWord8 uarr)
    =    text "PWord8" <+> pprp uarr
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR x
+   =    T.typeOf x
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR _
+   =    T.typeOf (5 :: Word8)
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR _
+   =    T.typeOf (5 :: Word8)
+
+
   -- Constructors -------------------------------
   {-# INLINE_PDATA emptyPR #-}
   emptyPR
@@ -65,9 +77,9 @@
   appendPR (PWord8 arr1) (PWord8 arr2)
         = PWord8 $ arr1 U.+:+ arr2
 
-  {-# INLINE_PDATA appendsPR #-}
-  appendsPR segdResult segd1 (PWord8 arr1) segd2 (PWord8 arr2)
-        = PWord8 $ U.append_s segdResult segd1 arr1 segd2 arr2
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult segd1 (PWord8s arr1) segd2 (PWord8s arr2)
+        = PWord8 $ U.append_vs segdResult segd1 arr1 segd2 arr2
 
 
   -- Projections --------------------------------                
diff --git a/Data/Array/Parallel/PArray/PData/Wrap.hs b/Data/Array/Parallel/PArray/PData/Wrap.hs
--- a/Data/Array/Parallel/PArray/PData/Wrap.hs
+++ b/Data/Array/Parallel/PArray/PData/Wrap.hs
@@ -44,7 +44,19 @@
   pprpDataPR (PWrap pdata)
         = pprpDataPA pdata
 
+  {-# NOINLINE typeRepPR #-}
+  typeRepPR  (Wrap x)
+        = typeRepPA x
 
+  {-# NOINLINE typeRepDataPR #-}
+  typeRepDataPR (PWrap pdata)
+        = typeRepDataPA pdata
+
+  {-# NOINLINE typeRepDatasPR #-}
+  typeRepDatasPR (PWraps pdata)
+        = typeRepDatasPA pdata
+
+
   -- Constructors -------------------------------
   {-# INLINE_PDATA emptyPR #-}
   emptyPR               
@@ -62,8 +74,8 @@
   appendPR (PWrap xs) (PWrap ys)
         = PWrap $ appendPA xs ys
         
-  {-# INLINE_PDATA appendsPR #-}
-  appendsPR segdResult segd1 (PWrap xs) segd2 (PWrap ys)
+  {-# INLINE_PDATA appendvsPR #-}
+  appendvsPR segdResult segd1 (PWraps xs) segd2 (PWraps ys)
         = PWrap $ appendsPA segdResult segd1 xs segd2 ys
         
 
diff --git a/Data/Array/Parallel/PArray/PRepr/Base.hs b/Data/Array/Parallel/PArray/PRepr/Base.hs
--- a/Data/Array/Parallel/PArray/PRepr/Base.hs
+++ b/Data/Array/Parallel/PArray/PRepr/Base.hs
@@ -17,6 +17,9 @@
         , coversPA
         , pprpPA
         , pprpDataPA
+        , typeRepPA
+        , typeRepDataPA
+        , typeRepDatasPA
 
         -- * Constructors
         , emptyPA
@@ -51,7 +54,9 @@
 import Data.Vector                              (Vector)
 import qualified Data.Array.Parallel.Unlifted   as U
 import qualified Data.Vector                    as V
+import qualified Data.Typeable                  as T
 
+
 -- PRepr / PA -----------------------------------------------------------------
 -- | Family of Representable types. These are the types that we know how to
 --   represent generically. `PRepr` takes an arbitrary type and produces the
@@ -136,11 +141,27 @@
 
 
 {-# INLINE_PA pprpDataPA #-}
-pprpDataPA          :: PA a => PData a -> Doc
+pprpDataPA      :: PA a => PData a -> Doc
 pprpDataPA x
  = pprpDataPR (toArrPRepr x)
 
 
+{-# INLINE_PA typeRepPA #-}
+typeRepPA       :: PA a => a -> T.TypeRep
+typeRepPA x
+ = typeRepPR (toPRepr x)
+
+{-# INLINE_PA typeRepDataPA #-}
+typeRepDataPA    :: PA a => PData a -> T.TypeRep
+typeRepDataPA x
+ = typeRepDataPR (toArrPRepr x)
+
+{-# INLINE_PA typeRepDatasPA #-}
+typeRepDatasPA    :: PA a => PDatas a -> T.TypeRep
+typeRepDatasPA x
+ = typeRepDatasPR (toArrPReprs x)
+
+
 -- Constructors ---------------------------------
 {-# INLINE_PA emptyPA #-}
 emptyPA         :: PA a => PData a
@@ -170,11 +191,11 @@
 
 
 {-# INLINE_PA appendsPA #-}
-appendsPA       :: PA a => U.Segd -> U.Segd -> PData a -> U.Segd 
-                        -> PData a -> PData a
+appendsPA       :: PA a => U.Segd -> U.VSegd -> PDatas a -> U.VSegd 
+                        -> PDatas a -> PData a
 appendsPA segdResult segd1 xs segd2 ys
  = fromArrPRepr
- $ appendsPR segdResult segd1 (toArrPRepr xs) segd2 (toArrPRepr ys)
+ $ appendvsPR segdResult segd1 (toArrPReprs xs) segd2 (toArrPReprs ys)
 
 
 -- Projections ----------------------------------
diff --git a/Data/Array/Parallel/PArray/PRepr/Tuple.hs b/Data/Array/Parallel/PArray/PRepr/Tuple.hs
--- a/Data/Array/Parallel/PArray/PRepr/Tuple.hs
+++ b/Data/Array/Parallel/PArray/PRepr/Tuple.hs
@@ -15,6 +15,8 @@
 import Data.Array.Parallel.PArray.PData.Tuple3
 import Data.Array.Parallel.PArray.PData.Tuple4
 import Data.Array.Parallel.PArray.PData.Tuple5
+import Data.Array.Parallel.PArray.PData.Tuple6
+import Data.Array.Parallel.PArray.PData.Tuple7
 import Data.Array.Parallel.PArray.PData.Nested
 import Data.Array.Parallel.PArray.PData.Wrap
 
@@ -124,7 +126,7 @@
         = PTuple4s as bs cs ds
 
 
--- Tuple4 --------------------------------------------------------------------
+-- Tuple5 --------------------------------------------------------------------
 type instance PRepr (a, b, c, d, e)
         = (Wrap a, Wrap b, Wrap c, Wrap d, Wrap e)
 
@@ -154,3 +156,60 @@
         = PTuple5s as bs cs ds es
 
 
+-- Tuple6 --------------------------------------------------------------------
+type instance PRepr (a, b, c, d, e, f)
+        = (Wrap a, Wrap b, Wrap c, Wrap d, Wrap e, Wrap f)
+
+instance (PA a, PA b, PA c, PA d, PA e, PA f) => PA (a, b, c, d, e, f) where
+  {-# INLINE_PA toPRepr #-}
+  toPRepr (a, b, c, d, e, f)
+        = (Wrap a, Wrap b, Wrap c, Wrap d, Wrap e, Wrap f)
+
+  {-# INLINE_PA fromPRepr #-}
+  fromPRepr (Wrap a, Wrap b, Wrap c, Wrap d, Wrap e, Wrap f)
+        = (a, b, c, d, e, f)
+
+  {-# INLINE_PA toArrPRepr #-}
+  toArrPRepr (PTuple6 as bs cs ds es fs)
+        = PTuple6 (PWrap as) (PWrap bs) (PWrap cs) (PWrap ds) (PWrap es) (PWrap fs)
+
+  {-# INLINE_PA fromArrPRepr #-}
+  fromArrPRepr (PTuple6 (PWrap as) (PWrap bs) (PWrap cs) (PWrap ds) (PWrap es) (PWrap fs))
+        = PTuple6 as bs cs ds es fs
+
+  {-# INLINE_PA toArrPReprs #-}
+  toArrPReprs (PTuple6s as bs cs ds es fs)
+        = PTuple6s (PWraps as) (PWraps bs) (PWraps cs) (PWraps ds) (PWraps es) (PWraps fs) 
+
+  {-# INLINE_PA fromArrPReprs #-}
+  fromArrPReprs (PTuple6s (PWraps as) (PWraps bs) (PWraps cs) (PWraps ds) (PWraps es) (PWraps fs))
+        = PTuple6s as bs cs ds es fs
+
+-- Tuple7 --------------------------------------------------------------------
+type instance PRepr (a, b, c, d, e, f, g)
+        = (Wrap a, Wrap b, Wrap c, Wrap d, Wrap e, Wrap f, Wrap g)
+
+instance (PA a, PA b, PA c, PA d, PA e, PA f, PA g) => PA (a, b, c, d, e, f, g) where
+  {-# INLINE_PA toPRepr #-}
+  toPRepr (a, b, c, d, e, f, g)
+        = (Wrap a, Wrap b, Wrap c, Wrap d, Wrap e, Wrap f, Wrap g)
+
+  {-# INLINE_PA fromPRepr #-}
+  fromPRepr (Wrap a, Wrap b, Wrap c, Wrap d, Wrap e, Wrap f, Wrap g)
+        = (a, b, c, d, e, f, g)
+
+  {-# INLINE_PA toArrPRepr #-}
+  toArrPRepr (PTuple7 as bs cs ds es fs gs)
+        = PTuple7 (PWrap as) (PWrap bs) (PWrap cs) (PWrap ds) (PWrap es) (PWrap fs) (PWrap gs)
+
+  {-# INLINE_PA fromArrPRepr #-}
+  fromArrPRepr (PTuple7 (PWrap as) (PWrap bs) (PWrap cs) (PWrap ds) (PWrap es) (PWrap fs) (PWrap gs))
+        = PTuple7 as bs cs ds es fs gs
+
+  {-# INLINE_PA toArrPReprs #-}
+  toArrPReprs (PTuple7s as bs cs ds es fs gs)
+        = PTuple7s (PWraps as) (PWraps bs) (PWraps cs) (PWraps ds) (PWraps es) (PWraps fs)  (PWraps gs)
+
+  {-# INLINE_PA fromArrPReprs #-}
+  fromArrPReprs (PTuple7s (PWraps as) (PWraps bs) (PWraps cs) (PWraps ds) (PWraps es) (PWraps fs) (PWraps gs))
+        = PTuple7s as bs cs ds es fs gs
diff --git a/Data/Array/Parallel/PArray/Scalar.hs b/Data/Array/Parallel/PArray/Scalar.hs
--- a/Data/Array/Parallel/PArray/Scalar.hs
+++ b/Data/Array/Parallel/PArray/Scalar.hs
@@ -24,6 +24,11 @@
         , map
         , zipWith
         , zipWith3
+        , zipWith4
+        , zipWith5
+        , zipWith6
+        , zipWith7
+        , zipWith8
         
         -- * Folds
         , fold,         folds
@@ -200,6 +205,62 @@
 zipWith3 f (PArray len xs) (PArray _ ys) (PArray _ zs)
         = PArray len $ to $ U.zipWith3 f (from xs) (from ys) (from zs)
 
+-- | Zip four arrays, yielding a new array.
+{-# INLINE_PA zipWith4 #-}
+zipWith4
+        :: (Scalar a, Scalar b, Scalar c, Scalar d, Scalar e)
+        => (a -> b -> c -> d -> e) -> PArray a -> PArray b -> PArray c -> PArray d -> PArray e
+
+zipWith4 f (PArray len ws) (PArray _ xs) (PArray _ ys) (PArray _ zs)
+        = PArray len $ to $ U.zipWith4 f (from ws) (from xs) (from ys) (from zs)
+
+-- | Zip five arrays, yielding a new array.
+{-# INLINE_PA zipWith5 #-}
+zipWith5
+        :: (Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f)
+        => (a -> b -> c -> d -> e -> f) 
+        -> PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f
+
+zipWith5 f (PArray len vs)  (PArray _ ws) (PArray _ xs) (PArray _ ys) (PArray _ zs)
+        = PArray len $ to $ U.zipWith5 f (from vs) (from ws) (from xs) (from ys) (from zs)
+
+
+-- | Zip six arrays, yielding a new array.
+{-# INLINE_PA zipWith6 #-}
+zipWith6
+        :: (Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f, Scalar g)
+        => (a -> b -> c -> d -> e -> f -> g) 
+        -> PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> PArray g
+
+zipWith6 f (PArray len us)  (PArray _ vs)(PArray _ ws) (PArray _ xs) (PArray _ ys) (PArray _ zs)
+        = PArray len $ to $ U.zipWith6 f (from us) (from vs) (from ws) (from xs) (from ys) (from zs)
+
+
+-- | Zip seven arrays, yielding a new array.
+{-# INLINE_PA zipWith7 #-}
+zipWith7
+        :: (Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f, Scalar g, Scalar h)
+        => (a -> b -> c -> d -> e -> f -> g -> h) 
+        -> PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> PArray g
+        -> PArray h
+        
+zipWith7 f (PArray len ts) (PArray _ us)  (PArray _ vs)(PArray _ ws) (PArray _ xs) (PArray _ ys) (PArray _ zs)
+        = PArray len $ to $ U.zipWith7 f (from ts) (from us) (from vs) (from ws) (from xs) (from ys) (from zs)
+
+
+-- | Eight seven arrays, yielding a new array.
+{-# INLINE_PA zipWith8 #-}
+zipWith8
+        :: (Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f, Scalar g, Scalar h, Scalar i)
+        => (a -> b -> c -> d -> e -> f -> g -> h -> i) 
+        -> PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> PArray g
+        -> PArray h -> PArray i
+        
+zipWith8 f (PArray len ss) (PArray _ ts) (PArray _ us)  (PArray _ vs)(PArray _ ws) (PArray _ xs) (PArray _ ys) (PArray _ zs)
+        = PArray len $ to $ U.zipWith8 f (from ss) (from ts) (from us) (from vs) (from ws) (from xs) (from ys) (from zs)
+
+
+                
 
 -- Folds ----------------------------------------------------------------------
 -- | Left fold over an array.
diff --git a/Data/Array/Parallel/Prelude/Double.hs b/Data/Array/Parallel/Prelude/Double.hs
--- a/Data/Array/Parallel/Prelude/Double.hs
+++ b/Data/Array/Parallel/Prelude/Double.hs
@@ -142,13 +142,7 @@
 {-# VECTORISE SCALAR (-) #-}
 
 (*) = (P.*)
-{-# VECTORISE (*) = mulPP #-}
-
-mulPP :: Double :-> Double :-> Double
-mulPP   = L.closure2' (P.*) (SC.zipWith (P.*))
-{-# INLINE mulPP #-}
-{-# NOVECTORISE mulPP #-}
-
+{-# VECTORISE SCALAR (*) #-}
 
 (/) = (P./)
 {-# VECTORISE SCALAR (/) #-}
diff --git a/Data/Array/Parallel/Prelude/Tuple.hs b/Data/Array/Parallel/Prelude/Tuple.hs
--- a/Data/Array/Parallel/Prelude/Tuple.hs
+++ b/Data/Array/Parallel/Prelude/Tuple.hs
@@ -26,7 +26,7 @@
 {-# INLINE tup4 #-}
 
 
-tup5    :: (PA a, PA b, PA c, PA d)
+tup5    :: (PA a, PA b, PA c, PA d, PA e)
         =>  a :-> b :-> c :-> d :-> e :-> (a, b, c, d, e)
 tup5    = closure5' (,,,,) PA.zip5
 {-# INLINE tup5 #-}
diff --git a/Data/Array/Parallel/Prim.hs b/Data/Array/Parallel/Prim.hs
--- a/Data/Array/Parallel/Prim.hs
+++ b/Data/Array/Parallel/Prim.hs
@@ -19,6 +19,11 @@
         , scalar_map
         , scalar_zipWith
         , scalar_zipWith3
+        , scalar_zipWith4
+        , scalar_zipWith5
+        , scalar_zipWith6
+        , scalar_zipWith7
+        , scalar_zipWith8
 
         -- Types used in the generic representation
         , Void, void, fromVoid, pvoid, pvoids#
@@ -30,7 +35,8 @@
         , (:->)(..)
         , closure,              ($:)
         , liftedClosure,        liftedApply
-        , closure1, closure2, closure3
+        , closure1, closure2, closure3, closure4, closure5
+        , closure6, closure7, closure8
         
         -- Selectors
         , Sel2
@@ -172,6 +178,7 @@
          -> (a :-> b)
 closure1 fv fl
  = let  fl' :: Int -> PData a -> PData b
+        {-# INLINE_CLOSURE fl' #-}
         fl' (I# c#) pdata 
          = case fl (PArray c# pdata) of
                  PArray _ pdata' -> pdata'
@@ -186,6 +193,7 @@
          -> (a :-> b :-> c)
 closure2 fv fl
  = let  fl' :: Int -> PData a -> PData b -> PData c
+        {-# INLINE_CLOSURE fl' #-}
         fl' (I# c#) pdata1 pdata2
          = case fl (PArray c# pdata1) (PArray c# pdata2) of
                  PArray _ pdata' -> pdata'
@@ -200,6 +208,7 @@
          -> (a :-> b :-> c :-> d)
 closure3 fv fl
  = let  fl' :: Int -> PData a -> PData b -> PData c -> PData d
+        {-# INLINE_CLOSURE fl' #-}
         fl' (I# c#) pdata1 pdata2 pdata3
          = case fl (PArray c# pdata1) (PArray c# pdata2) (PArray c# pdata3) of
                  PArray _ pdata' -> pdata'
@@ -207,7 +216,81 @@
    in   C.closure3 fv fl'
 {-# INLINE_CLOSURE closure3 #-}
 
+{-# INLINE_CLOSURE closure4 #-}
+closure4 :: forall a b c d e.  (PA a, PA b, PA c)
+         => (a -> b -> c -> d -> e)
+         -> (PArray a -> PArray b -> PArray c -> PArray d -> PArray e)
+         -> (a :-> b :-> c :-> d :-> e)
+closure4 fv fl
+ = let  fl' :: Int -> PData a -> PData b -> PData c -> PData d -> PData e
+        {-# INLINE_CLOSURE fl' #-}
+        fl' (I# c#) pdata1 pdata2 pdata3 pdata4
+         = case fl (PArray c# pdata1) (PArray c# pdata2) (PArray c# pdata3) (PArray c# pdata4) of
+                 PArray _ pdata' -> pdata'
+                
+   in   C.closure4 fv fl'
 
+
+
+{-# INLINE_CLOSURE closure5 #-}
+closure5 :: forall a b c d e f.  (PA a, PA b, PA c, PA d)
+         => (a -> b -> c -> d -> e -> f)
+         -> (PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f)
+         -> (a :-> b :-> c :-> d :-> e :-> f)
+closure5 fv fl
+ = let  fl' :: Int -> PData a -> PData b -> PData c -> PData d -> PData e -> PData f
+        {-# INLINE_CLOSURE fl' #-}
+        fl' (I# c#) pdata1 pdata2 pdata3 pdata4 pdata5
+         = case fl (PArray c# pdata1) (PArray c# pdata2) (PArray c# pdata3) (PArray c# pdata4) (PArray c# pdata5) of
+                 PArray _ pdata' -> pdata'
+                
+   in   C.closure5 fv fl'
+
+{-# INLINE_CLOSURE closure6 #-}
+closure6 :: forall a b c d e f g.  (PA a, PA b, PA c, PA d, PA e)
+         => (a -> b -> c -> d -> e -> f -> g)
+         -> (PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> PArray g)
+         -> (a :-> b :-> c :-> d :-> e :-> f :-> g)
+closure6 fv fl
+ = let  fl' :: Int -> PData a -> PData b -> PData c -> PData d -> PData e -> PData f -> PData g
+        {-# INLINE_CLOSURE fl' #-}
+        fl' (I# c#) pdata1 pdata2 pdata3 pdata4 pdata5 pdata6
+         = case fl (PArray c# pdata1) (PArray c# pdata2) (PArray c# pdata3) (PArray c# pdata4) (PArray c# pdata5) (PArray c# pdata6) of
+                 PArray _ pdata' -> pdata'
+                
+   in   C.closure6 fv fl'
+   
+{-# INLINE_CLOSURE closure7 #-}
+closure7 :: forall a b c d e f g h.  (PA a, PA b, PA c, PA d, PA e, PA f, PA g)
+         => (a -> b -> c -> d -> e -> f -> g -> h)
+         -> (PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> PArray g -> PArray h)
+         -> (a :-> b :-> c :-> d :-> e :-> f :-> g :-> h)
+closure7 fv fl
+ = let  fl' :: Int -> PData a -> PData b -> PData c -> PData d -> PData e -> PData f -> PData g  -> PData h
+        {-# INLINE_CLOSURE fl' #-}
+        fl' (I# c#) pdata1 pdata2 pdata3 pdata4 pdata5 pdata6 pdata7
+         = case fl (PArray c# pdata1) (PArray c# pdata2) (PArray c# pdata3) (PArray c# pdata4) (PArray c# pdata5) (PArray c# pdata6) (PArray c# pdata7) of
+                 PArray _ pdata' -> pdata'
+                
+   in   C.closure7 fv fl'
+
+
+{-# INLINE_CLOSURE closure8 #-}
+closure8 :: forall a b c d e f g h i.  (PA a, PA b, PA c, PA d, PA e, PA f, PA g, PA h)
+         => (a -> b -> c -> d -> e -> f -> g -> h -> i)
+         -> (PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> PArray g -> PArray h -> PArray i)
+         -> (a :-> b :-> c :-> d :-> e :-> f :-> g :-> h :-> i)
+closure8 fv fl
+ = let  fl' :: Int -> PData a -> PData b -> PData c -> PData d -> PData e -> PData f -> PData g -> PData h  -> PData i
+        {-# INLINE_CLOSURE fl' #-}
+        fl' (I# c#) pdata1 pdata2 pdata3 pdata4 pdata5 pdata6 pdata7 pdata8 
+         = case fl (PArray c# pdata1) (PArray c# pdata2) (PArray c# pdata3) (PArray c# pdata4) 
+                   (PArray c# pdata5) (PArray c# pdata6) (PArray c# pdata7) (PArray c# pdata8) of
+                 PArray _ pdata' -> pdata'
+                
+   in   C.closure8 fv fl'   
+   
+   
 -- Selector functions ---------------------------------------------------------
 -- The vectoriser wants versions of these that take unboxed integers
 -- for some arguments.
@@ -281,6 +364,46 @@
 scalar_zipWith3 = Scalar.zipWith3
 {-# INLINE scalar_zipWith3 #-}
 
+{-# INLINE scalar_zipWith4 #-}
+scalar_zipWith4
+        :: (Scalar a, Scalar b, Scalar c, Scalar d, Scalar e)
+        => (a -> b -> c -> d -> e) -> PArray a -> PArray b -> PArray c -> PArray d -> PArray e
+
+scalar_zipWith4 = Scalar.zipWith4
+
+
+{-# INLINE scalar_zipWith5 #-}
+scalar_zipWith5
+        :: (Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f)
+        => (a -> b -> c -> d -> e -> f) 
+        -> PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f
+
+scalar_zipWith5 = Scalar.zipWith5
+
+{-# INLINE scalar_zipWith6 #-}
+scalar_zipWith6
+        :: (Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f, Scalar g)
+        => (a -> b -> c -> d -> e -> f -> g) 
+        -> PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> PArray g
+
+scalar_zipWith6 = Scalar.zipWith6
+
+{-# INLINE scalar_zipWith7 #-}
+scalar_zipWith7
+        :: (Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f, Scalar g, Scalar h)
+        => (a -> b -> c -> d -> e -> f -> g -> h) 
+        -> PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f -> PArray g -> PArray h
+
+scalar_zipWith7 = Scalar.zipWith7
+
+{-# INLINE scalar_zipWith8 #-}
+scalar_zipWith8
+        :: (Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f, Scalar g, Scalar h, Scalar i)
+        => (a -> b -> c -> d -> e -> f -> g -> h -> i) 
+        -> PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f     
+        -> PArray g -> PArray h -> PArray i
+
+scalar_zipWith8 = Scalar.zipWith8
 
 -- Int functions --------------------------------------------------------------
 type PArray_Int# = U.Array Int
diff --git a/Data/Array/Parallel/Trace.hs b/Data/Array/Parallel/Trace.hs
new file mode 100644
--- /dev/null
+++ b/Data/Array/Parallel/Trace.hs
@@ -0,0 +1,88 @@
+
+
+module Data.Array.Parallel.Trace
+        ( Trace (..)
+        , Op    (..)
+        , traceOp)
+where
+import Data.Typeable
+
+traceOp :: Op -> a -> a
+traceOp _op x = x
+--        = Debug.Trace.trace (Prelude.show op) x
+
+data Trace
+        = Trace Op
+        deriving Show
+
+data Op
+        -- Singleton
+        = OpSingleton           { traceElemType         :: TypeRep }
+
+        | OpSingletonL          { traceElemType         :: TypeRep
+                                , traceContext          :: Int }
+
+        | OpReplicate           { traceElemType         :: TypeRep
+                                , traceCount            :: Int }
+
+        -- Replicate
+        | OpReplicateL          { traceElemType         :: TypeRep
+                                , traceContext          :: Int }
+
+        | OpReplicateS          { traceElemType         :: TypeRep
+                                , traceCount            :: Int }
+
+        -- Append
+        | OpAppend              { traceElemType         :: TypeRep
+                                , traceSrc1Length       :: Int
+                                , traceSrc2Length       :: Int
+                                , traceDstLength        :: Int }
+
+        | OpAppendL             { traceElemType         :: TypeRep
+                                , traceContext          :: Int }
+
+
+        -- Concat
+        | OpConcat              { traceElemType         :: TypeRep
+                                , traceSrcLength        :: Int 
+                                , traceDstLength        :: Int }
+
+        | OpConcatL             { traceElemType         :: TypeRep
+                                , traceContext          :: Int }
+
+        -- Unconcat
+        | OpUnconcat            { traceElemType         :: TypeRep
+                                , traceCount            :: Int }
+
+        -- Length
+        | OpLength
+        | OpLengthL             { traceContext          :: Int }
+
+        -- Index
+        | OpIndex       
+        | OpIndexL              { traceContext          :: Int }
+
+        -- Extract
+        | OpExtract             { traceDstLength        :: Int }
+        | OpExtractS            { traceDstLength        :: Int }
+
+        -- Slice
+        | OpSlice               { traceDstLength        :: Int }
+        | OpSliceL              { traceContext          :: Int }
+
+        -- Pack
+        | OpPack                { traceDstLength        :: Int }
+        | OpPackL               { traceContext          :: Int }
+        | OpPackByTag           { traceDstLength        :: Int }
+
+        -- Combine
+        | OpCombine2            { traceDstLength        :: Int }
+
+        -- Zip
+        | OpZip                 { traceLength           :: Int }
+        | OpZipL                { traceLength           :: Int }
+
+        -- Unzip
+        | OpUnzip               { traceLength           :: Int }
+        | OpUnzipL              { traceLength           :: Int }
+        deriving Show
diff --git a/dph-lifted-vseg.cabal b/dph-lifted-vseg.cabal
--- a/dph-lifted-vseg.cabal
+++ b/dph-lifted-vseg.cabal
@@ -1,5 +1,5 @@
 Name:           dph-lifted-vseg
-Version:        0.6.1.2
+Version:        0.7.0.1
 License:        BSD3
 License-File:   LICENSE
 Author:         The DPH Team
@@ -23,22 +23,6 @@
         Data.Array.Parallel.Lifted.Closure
         Data.Array.Parallel.Lifted.Combinators
         Data.Array.Parallel.Lifted
-        Data.Array.Parallel.PArray.PData
-        Data.Array.Parallel.PArray.PRepr
-        Data.Array.Parallel.PArray.Scalar
-        Data.Array.Parallel.PArray
-        Data.Array.Parallel.Prelude.Base
-        Data.Array.Parallel.Prelude.Bool
-        Data.Array.Parallel.Prelude.Double
-        Data.Array.Parallel.Prelude.Int
-        Data.Array.Parallel.Prelude.Word8
-        Data.Array.Parallel.Prelude.Tuple
-        Data.Array.Parallel.Prelude.Ordering
-        Data.Array.Parallel.Prelude
-        Data.Array.Parallel
-        Data.Array.Parallel.Prim
-        
-  Other-Modules:
         Data.Array.Parallel.PArray.PData.Base
         Data.Array.Parallel.PArray.PData.Double
         Data.Array.Parallel.PArray.PData.Int
@@ -49,15 +33,31 @@
         Data.Array.Parallel.PArray.PData.Tuple3
         Data.Array.Parallel.PArray.PData.Tuple4
         Data.Array.Parallel.PArray.PData.Tuple5
+        Data.Array.Parallel.PArray.PData.Tuple6
+        Data.Array.Parallel.PArray.PData.Tuple7
         Data.Array.Parallel.PArray.PData.Unit
         Data.Array.Parallel.PArray.PData.Void
         Data.Array.Parallel.PArray.PData.Wrap
+        Data.Array.Parallel.PArray.PData
         Data.Array.Parallel.PArray.PRepr.Base
         Data.Array.Parallel.PArray.PRepr.Instances
         Data.Array.Parallel.PArray.PRepr.Nested
         Data.Array.Parallel.PArray.PRepr.Tuple
-  
-
+        Data.Array.Parallel.PArray.PRepr
+        Data.Array.Parallel.PArray.Scalar
+        Data.Array.Parallel.PArray
+        Data.Array.Parallel.Prelude.Base
+        Data.Array.Parallel.Prelude.Bool
+        Data.Array.Parallel.Prelude.Double
+        Data.Array.Parallel.Prelude.Int
+        Data.Array.Parallel.Prelude.Word8
+        Data.Array.Parallel.Prelude.Tuple
+        Data.Array.Parallel.Prelude.Ordering
+        Data.Array.Parallel.Prelude
+        Data.Array.Parallel.Trace
+        Data.Array.Parallel
+        Data.Array.Parallel.Prim
+        
   Exposed:
         False
 
@@ -83,7 +83,7 @@
         ExistentialQuantification,
         ScopedTypeVariables,
         PatternGuards,
-        PackageImports
+        DeriveDataTypeable
 
   GHC-Options:
         -Odph
@@ -93,14 +93,14 @@
         -fno-warn-orphans
 
   Build-Depends:  
-        base                    == 4.5.*,
+        base                    == 4.6.*,
         ghc                     == 7.*,
         array                   == 0.4.*,
         random                  == 1.0.*,
-        template-haskell        == 2.7.*,
-        vector                  == 0.9.*,
+        template-haskell        == 2.8.*,
+        dph-base                == 0.7.*,
+        dph-prim-par            == 0.7.*,
+        dph-lifted-base         == 0.7.*,
+        vector                  == 0.10.*,
         pretty                  == 1.1.*,
-        containers              == 0.4.*,
-        dph-base                == 0.6.1.*,
-        dph-prim-par            == 0.6.1.*,
-        dph-lifted-base         == 0.6.1.*
+        containers              == 0.5.*
