diff --git a/Data/Array/Repa.hs b/Data/Array/Repa.hs
--- a/Data/Array/Repa.hs
+++ b/Data/Array/Repa.hs
@@ -80,9 +80,7 @@
 --  7. Repa writes to the GHC eventlog at the start and end of  each parallel computation.
 --     Use threadscope to see what your program is doing.
 --
---  8. Follow the advice on program structure in the comment for `deepSeqArrays`
---
---  9. When you're sure your program works, switch to the unsafe versions
+--  8. When you're sure your program works, switch to the unsafe versions
 --     of functions like `traverse`. These don't do bounds checks.
 -- 
 module Data.Array.Repa
diff --git a/Data/Array/Repa/Base.hs b/Data/Array/Repa/Base.hs
--- a/Data/Array/Repa/Base.hs
+++ b/Data/Array/Repa/Base.hs
@@ -58,7 +58,9 @@
 
 
 -- | Apply `deepSeqArray` to up to four arrays. 
---
+---
+--   NOTE: this shouldn't be needed anymore, as we've made all the shape fields strict.
+--      
 --   The implementation of this function has been hand-unwound to work for up to
 --   four arrays. Putting more in the list yields `error`.
 -- 
diff --git a/Data/Array/Repa/Eval/Chunked.hs b/Data/Array/Repa/Eval/Chunked.hs
--- a/Data/Array/Repa/Eval/Chunked.hs
+++ b/Data/Array/Repa/Eval/Chunked.hs
@@ -21,7 +21,7 @@
 	-> IO ()
 
 {-# INLINE [0] fillChunkedS #-}
-fillChunkedS !(I# len) !write !getElem
+fillChunkedS !(I# len) write getElem
  = fill 0#
  where	fill !ix
 	 | ix >=# len	= return ()
@@ -41,7 +41,7 @@
 	-> IO ()
 
 {-# INLINE [0] fillChunkedP #-}
-fillChunkedP !(I# len) !write !getElem
+fillChunkedP !(I# len) write getElem
  = 	gangIO theGang
 	 $  \(I# thread) -> 
               let !start   = splitIx thread
@@ -80,7 +80,7 @@
         -> IO ()
 
 {-# INLINE [0] fillChunkedIOP #-}
-fillChunkedIOP !(I# len) !write !mkGetElem
+fillChunkedIOP !(I# len) write mkGetElem
  = 	gangIO theGang
 	 $  \(I# thread) -> 
               let !start = splitIx thread
diff --git a/Data/Array/Repa/Eval/Cursored.hs b/Data/Array/Repa/Eval/Cursored.hs
--- a/Data/Array/Repa/Eval/Cursored.hs
+++ b/Data/Array/Repa/Eval/Cursored.hs
@@ -38,7 +38,7 @@
         -> IO ()
 
 {-# INLINE [0] fillBlock2P #-}
-fillBlock2P !write !getElem !imageWidth !x0 !y0 !w0 h0
+fillBlock2P write getElem !imageWidth !x0 !y0 !w0 h0
  = fillCursoredBlock2P 
         write id addDim getElem 
         imageWidth x0 y0 w0 h0
@@ -65,7 +65,7 @@
         -> IO ()
 
 {-# INLINE [0] fillBlock2S #-}
-fillBlock2S !write !getElem imageWidth x0 y0 w0 h0
+fillBlock2S write getElem !imageWidth !x0 !y0 !w0 !h0
  = fillCursoredBlock2S
         write id addDim getElem 
         imageWidth x0 y0 w0 h0
@@ -100,8 +100,8 @@
 
 {-# INLINE [0] fillCursoredBlock2P #-}
 fillCursoredBlock2P
-	!write
-	!makeCursorFCB !shiftCursorFCB !getElemFCB
+	write
+	makeCursorFCB shiftCursorFCB getElemFCB
 	!imageWidth !x0 !y0 !w0 !h0
  = 	gangIO theGang fillBlock
  where	
@@ -159,8 +159,8 @@
 
 {-# INLINE [0] fillCursoredBlock2S #-}
 fillCursoredBlock2S
-	!write
-	!makeCursor !shiftCursor !getElem
+	write
+	makeCursor shiftCursor getElem
 	!imageWidth !x0 !y0 !w0 h0
 
  = do   fillBlock y0
diff --git a/Data/Array/Repa/Eval/Reduction.hs b/Data/Array/Repa/Eval/Reduction.hs
--- a/Data/Array/Repa/Eval/Reduction.hs
+++ b/Data/Array/Repa/Eval/Reduction.hs
@@ -19,7 +19,7 @@
       -> Int#           -- ^ inner dimension (length to fold over)
       -> IO ()
 {-# INLINE [1] foldS #-}
-foldS vec !get !c !r !n
+foldS !vec get c !r !n
   = iter 0# 0#
   where
     !(I# end) = M.length vec
@@ -45,7 +45,7 @@
       -> Int            -- ^ inner dimension (length to fold over)
       -> IO ()
 {-# INLINE [1] foldP #-}
-foldP vec !f !c !r !(I# n)
+foldP vec f c !r (I# n)
   = gangIO theGang
   $ \(I# tid) -> fill (split tid) (split (tid +# 1#))
   where
@@ -82,7 +82,7 @@
          -> a
 
 {-# INLINE [1] foldAllS #-}
-foldAllS !f !c !r !len
+foldAllS f c !r !len
  = reduceAny (\i -> f i) c r 0# len 
 
 
@@ -103,7 +103,7 @@
          -> IO a
 {-# INLINE [1] foldAllP #-}
 
-foldAllP !f !c !r !len
+foldAllP f c !r !len
   | len == 0    = return r
   | otherwise   = do
       mvec <- M.unsafeNew chunks
@@ -136,14 +136,14 @@
         -> Int                  -- ^ Starting index in array.
         -> Int                  -- ^ Ending index in array.
         -> a                    -- ^ Result.
-reduce f c r (I# start) (I# end)
+reduce f c !r (I# start) (I# end)
  = reduceAny (\i -> f (I# i)) c r start end
 
 
 -- | Sequentially reduce values between the given indices
 {-# INLINE [0] reduceAny #-}
 reduceAny :: (Int# -> a) -> (a -> a -> a) -> a -> Int# -> Int# -> a
-reduceAny !f !c !r !start !end 
+reduceAny f c !r !start !end 
  = iter start r
  where
    {-# INLINE iter #-}
@@ -160,7 +160,7 @@
         -> Int# -> Int# 
         -> Int#
 
-reduceInt !f !c !r !start !end 
+reduceInt f c !r !start !end 
  = iter start r
  where
    {-# INLINE iter #-}
@@ -177,7 +177,7 @@
         -> Int# -> Int# 
         -> Float#
 
-reduceFloat !f !c !r !start !end 
+reduceFloat f c !r !start !end 
  = iter start r
  where
    {-# INLINE iter #-}
@@ -194,7 +194,7 @@
         -> Int# -> Int# 
         -> Double#
 
-reduceDouble !f !c !r !start !end 
+reduceDouble f c !r !start !end 
  = iter start r
  where
    {-# INLINE iter #-}
diff --git a/Data/Array/Repa/Eval/Selection.hs b/Data/Array/Repa/Eval/Selection.hs
--- a/Data/Array/Repa/Eval/Selection.hs
+++ b/Data/Array/Repa/Eval/Selection.hs
@@ -25,7 +25,7 @@
 	-> IO Int		-- ^ Number of elements written to destination array.
 
 {-# INLINE selectChunkedS #-}
-selectChunkedS !fnWrite !fnMatch !fnProduce !shSize
+selectChunkedS fnWrite fnMatch fnProduce !shSize
  = fill 0 0
  where	lenSrc	= size shSize
 
@@ -60,7 +60,7 @@
 	-> IO [IOVector a]	-- Chunks containing array elements.
 
 {-# INLINE selectChunkedP #-}
-selectChunkedP !fnMatch !fnProduce !len
+selectChunkedP fnMatch fnProduce !len
  = do
 	-- Make IORefs that the threads will write their result chunks to.
 	-- We start with a chunk size proportial to the number of threads we have,
diff --git a/Data/Array/Repa/Index.hs b/Data/Array/Repa/Index.hs
--- a/Data/Array/Repa/Index.hs
+++ b/Data/Array/Repa/Index.hs
@@ -18,13 +18,13 @@
 
 -- | An index of dimension zero
 data Z	= Z
-	deriving (Show, Eq, Ord)
+	deriving (Show, Read, Eq, Ord)
 
 -- | Our index type, used for both shapes and indices.
 infixl 3 :.
 data tail :. head
 	= !tail :. !head
-	deriving (Show, Eq, Ord)
+	deriving (Show, Read, Eq, Ord)
 
 -- Common dimensions
 type DIM0	= Z
diff --git a/Data/Array/Repa/Operators/Interleave.hs b/Data/Array/Repa/Operators/Interleave.hs
--- a/Data/Array/Repa/Operators/Interleave.hs
+++ b/Data/Array/Repa/Operators/Interleave.hs
@@ -31,8 +31,7 @@
 
 {-# INLINE [2] interleave2 #-}
 interleave2 arr1 arr2
- = arr1 `deepSeqArray` arr2 `deepSeqArray`
-   unsafeTraverse2 arr1 arr2 shapeFn elemFn
+ = unsafeTraverse2 arr1 arr2 shapeFn elemFn
  where
 	shapeFn dim1 dim2
 	 | dim1 == dim2
@@ -60,8 +59,7 @@
 
 {-# INLINE [2] interleave3 #-}
 interleave3 arr1 arr2 arr3
- = arr1 `deepSeqArray` arr2 `deepSeqArray` arr3 `deepSeqArray`
-   unsafeTraverse3 arr1 arr2 arr3 shapeFn elemFn
+ = unsafeTraverse3 arr1 arr2 arr3 shapeFn elemFn
  where
 	shapeFn dim1 dim2 dim3
 	 | dim1 == dim2
@@ -92,8 +90,7 @@
 
 {-# INLINE [2] interleave4 #-}
 interleave4 arr1 arr2 arr3 arr4
- = arr1 `deepSeqArray` arr2 `deepSeqArray` arr3 `deepSeqArray` arr4 `deepSeqArray`
-   unsafeTraverse4 arr1 arr2 arr3 arr4 shapeFn elemFn
+ = unsafeTraverse4 arr1 arr2 arr3 arr4 shapeFn elemFn
  where
 	shapeFn dim1 dim2 dim3 dim4
 	 | dim1 == dim2
diff --git a/Data/Array/Repa/Operators/Mapping.hs b/Data/Array/Repa/Operators/Mapping.hs
--- a/Data/Array/Repa/Operators/Mapping.hs
+++ b/Data/Array/Repa/Operators/Mapping.hs
@@ -28,10 +28,10 @@
 --
 map     :: (Shape sh, Repr r a)
         => (a -> b) -> Array r sh a -> Array D sh b
-{-# INLINE [3] map #-}
 map f arr
  = case delay arr of
         ADelayed sh g -> ADelayed sh (f . g)
+{-# INLINE [3] map #-}
 
 
 -- ZipWith --------------------------------------------------------------------
@@ -43,16 +43,14 @@
         => (a -> b -> c)
         -> Array r1 sh a -> Array r2 sh b
         -> Array D sh c
-{-# INLINE [2] zipWith #-}
 zipWith f arr1 arr2
- = arr1 `deepSeqArray` arr2 `deepSeqArray`
-   let 
-        {-# INLINE get #-}
+ = let  {-# INLINE get #-}
         get ix  = f (arr1 `unsafeIndex` ix) (arr2 `unsafeIndex` ix)
 
    in   fromFunction 
                 (intersectDim (extent arr1) (extent arr2)) 
                 get
+{-# INLINE [2] zipWith #-}
 
 
 {-# INLINE (+^) #-}
@@ -183,5 +181,3 @@
  cmap     _   (AUndefined sh) = AUndefined sh
  czipWith _ _ (AUndefined sh) = AUndefined sh
 
-
- 
diff --git a/Data/Array/Repa/Operators/Traversal.hs b/Data/Array/Repa/Operators/Traversal.hs
--- a/Data/Array/Repa/Operators/Traversal.hs
+++ b/Data/Array/Repa/Operators/Traversal.hs
@@ -21,13 +21,11 @@
 	-> Array D sh' b
 
 traverse arr transExtent newElem
- = arr `deepSeqArray` 
-   fromFunction (transExtent (extent arr)) (newElem (index arr))
+ = fromFunction (transExtent (extent arr)) (newElem (index arr))
 {-# INLINE [3] traverse #-}
 
 unsafeTraverse arr transExtent newElem
- = arr `deepSeqArray`
-   fromFunction (transExtent (extent arr)) (newElem (unsafeIndex arr))
+ = fromFunction (transExtent (extent arr)) (newElem (unsafeIndex arr))
 {-# INLINE [3] unsafeTraverse #-}
 
 
@@ -46,14 +44,12 @@
         -> Array D sh'' c
 
 traverse2 arrA arrB transExtent newElem
- = arrA `deepSeqArray` arrB `deepSeqArray`
-   fromFunction  (transExtent (extent arrA) (extent arrB))
+ = fromFunction  (transExtent (extent arrA) (extent arrB))
  	         (newElem     (index  arrA) (index  arrB))
 {-# INLINE [3] traverse2 #-}
 
 unsafeTraverse2 arrA arrB transExtent newElem
- = arrA `deepSeqArray` arrB `deepSeqArray`
-   fromFunction  (transExtent (extent arrA) (extent arrB))
+ = fromFunction  (transExtent (extent arrA) (extent arrB))
                  (newElem     (unsafeIndex arrA) (unsafeIndex arrB))
 {-# INLINE [3] unsafeTraverse2 #-}
 
@@ -75,14 +71,12 @@
         -> Array D sh4 d
 
 traverse3 arrA arrB arrC transExtent newElem
- = arrA `deepSeqArray` arrB `deepSeqArray` arrC `deepSeqArray`
-   fromFunction (transExtent (extent arrA) (extent arrB) (extent arrC))
+ = fromFunction (transExtent (extent arrA) (extent arrB) (extent arrC))
  	        (newElem     (index arrA)  (index arrB)  (index  arrC))
 {-# INLINE [3] traverse3 #-}
 
 unsafeTraverse3 arrA arrB arrC transExtent newElem
- = arrA `deepSeqArray` arrB `deepSeqArray` arrC `deepSeqArray`
-   fromFunction	(transExtent (extent arrA) (extent arrB) (extent arrC))
+ = fromFunction	(transExtent (extent arrA) (extent arrB) (extent arrC))
 	        (newElem     (unsafeIndex arrA) (unsafeIndex arrB) (unsafeIndex arrC))
 {-# INLINE [3] unsafeTraverse3 #-}
 
@@ -105,15 +99,13 @@
         -> Array D sh5 e
 
 traverse4 arrA arrB arrC arrD transExtent newElem
- = arrA `deepSeqArray` arrB `deepSeqArray` arrC `deepSeqArray` arrD `deepSeqArray`
-   fromFunction	(transExtent (extent arrA) (extent arrB) (extent arrC) (extent arrD))
+ = fromFunction	(transExtent (extent arrA) (extent arrB) (extent arrC) (extent arrD))
 		(newElem     (index  arrA) (index  arrB) (index  arrC) (index  arrD))
 {-# INLINE [3] traverse4 #-}
 
 
 unsafeTraverse4 arrA arrB arrC arrD transExtent newElem
- = arrA `deepSeqArray` arrB `deepSeqArray` arrC `deepSeqArray` arrD `deepSeqArray`
-   fromFunction (transExtent (extent arrA) (extent arrB) (extent arrC) (extent arrD))
+ = fromFunction (transExtent (extent arrA) (extent arrB) (extent arrC) (extent arrD))
 		(newElem     (unsafeIndex arrA) (unsafeIndex arrB) (unsafeIndex arrC) (unsafeIndex arrD))
 {-# INLINE [3] unsafeTraverse4 #-}
 
diff --git a/Data/Array/Repa/Repr/ByteString.hs b/Data/Array/Repa/Repr/ByteString.hs
--- a/Data/Array/Repa/Repr/ByteString.hs
+++ b/Data/Array/Repa/Repr/ByteString.hs
@@ -15,10 +15,17 @@
 -- | Strict ByteStrings arrays are represented as ForeignPtr buffers of Word8
 data B
 data instance Array B sh Word8
-        = AByteString sh !ByteString
+        = AByteString !sh !ByteString
         
 deriving instance Show sh
         => Show (Array B sh Word8)
+
+deriving instance Read sh
+        => Read (Array B sh Word8)
+
+-- | Sequential equality. The parallel version is `equalsP`.
+deriving instance Eq sh
+        => Eq (Array B sh Word8)
 
 
 -- Repr -----------------------------------------------------------------------
diff --git a/Data/Array/Repa/Repr/Cursored.hs b/Data/Array/Repa/Repr/Cursored.hs
--- a/Data/Array/Repa/Repr/Cursored.hs
+++ b/Data/Array/Repa/Repr/Cursored.hs
@@ -25,16 +25,16 @@
 
 data instance Array C sh e
         = forall cursor. ACursored
-        { cursoredExtent :: sh 
+        { cursoredExtent :: !sh 
                 
           -- | Make a cursor to a particular element.
-	, makeCursor    :: sh -> cursor
+	, makeCursor     :: sh -> cursor
 
 	  -- | Shift the cursor by an offset, to get to another element.
-	, shiftCursor   :: sh -> cursor -> cursor
+	, shiftCursor    :: sh -> cursor -> cursor
 
 	  -- | Load\/compute the element at the given cursor.
-	, loadCursor	:: cursor -> e }
+	, loadCursor	 :: cursor -> e }
 
 
 -- Repr -----------------------------------------------------------------------
diff --git a/Data/Array/Repa/Repr/Delayed.hs b/Data/Array/Repa/Repr/Delayed.hs
--- a/Data/Array/Repa/Repr/Delayed.hs
+++ b/Data/Array/Repa/Repr/Delayed.hs
@@ -21,7 +21,7 @@
 data D
 data instance Array D sh e
         = ADelayed  
-                sh 
+                !sh 
                 (sh -> e) 
 
 
diff --git a/Data/Array/Repa/Repr/Hint.hs b/Data/Array/Repa/Repr/Hint.hs
--- a/Data/Array/Repa/Repr/Hint.hs
+++ b/Data/Array/Repa/Repr/Hint.hs
@@ -14,6 +14,17 @@
 data instance Array (S r1) sh e
         = ASmall !(Array r1 sh e)
 
+deriving instance Show (Array r1 sh e) 
+        => Show (Array (S r1) sh e)
+
+deriving instance Read (Array r1 sh e) 
+        => Read (Array (S r1) sh e)
+
+-- | Sequential equality. The parallel version is `equalsP`.
+deriving instance Eq (Array r1 sh e)
+        => Eq (Array (S r1) sh e)
+
+
 -- | Wrap an array with a smallness hint.
 hintSmall :: Array r1 sh e -> Array (S r1) sh e
 hintSmall = ASmall
diff --git a/Data/Array/Repa/Repr/Partitioned.hs b/Data/Array/Repa/Repr/Partitioned.hs
--- a/Data/Array/Repa/Repr/Partitioned.hs
+++ b/Data/Array/Repa/Repr/Partitioned.hs
@@ -24,13 +24,13 @@
 data P r1 r2
 
 data instance Array (P r1 r2) sh e
-        = APart sh                         -- size of the whole array
-                (Range sh) (Array r1 sh e) -- if in range use this array
-                (Array r2 sh e)            -- otherwise use this array
+        = APart !sh                          -- size of the whole array
+                !(Range sh) !(Array r1 sh e) -- if in range use this array
+                !(Array r2 sh e)             -- otherwise use this array
 
 data Range sh
-        = Range sh sh                      -- indices defining the range
-                (sh -> Bool)               -- predicate to check whether were in range
+        = Range !sh !sh                      -- indices defining the range
+                (sh -> Bool)                 -- predicate to check whether were in range
 
 -- | Check whether an index is within the given range.
 inRange :: Range sh -> sh -> Bool
diff --git a/Data/Array/Repa/Repr/Unboxed.hs b/Data/Array/Repa/Repr/Unboxed.hs
--- a/Data/Array/Repa/Repr/Unboxed.hs
+++ b/Data/Array/Repa/Repr/Unboxed.hs
@@ -27,10 +27,18 @@
 --
 data U
 data instance U.Unbox e => Array U sh e
-        = AUnboxed sh !(U.Vector e)
+        = AUnboxed !sh !(U.Vector e)
         
 deriving instance (Show sh, Show e, U.Unbox e)
         => Show (Array U sh e)
+
+deriving instance (Read sh, Read e, U.Unbox e)
+        => Read (Array U sh e)
+
+-- | Sequential equality. The parallel version is `equalsP`.
+deriving instance (Eq sh, Eq e, U.Unbox e)
+        => Eq (Array U sh e)
+
 
 -- Repr -----------------------------------------------------------------------
 -- | Read elements from an unboxed vector array.
diff --git a/Data/Array/Repa/Repr/Undefined.hs b/Data/Array/Repa/Repr/Undefined.hs
--- a/Data/Array/Repa/Repr/Undefined.hs
+++ b/Data/Array/Repa/Repr/Undefined.hs
@@ -13,7 +13,13 @@
 --     as the previous partitions are expected to provide full coverage.
 data X
 data instance Array X sh e
-        = AUndefined sh
+        = AUndefined !sh
+
+deriving instance Show sh 
+        => Show (Array X sh e)
+
+deriving instance Read sh 
+        => Read (Array X sh e)
 
 
 -- | Undefined array elements. Inspecting them yields `error`.
diff --git a/Data/Array/Repa/Repr/Vector.hs b/Data/Array/Repa/Repr/Vector.hs
--- a/Data/Array/Repa/Repr/Vector.hs
+++ b/Data/Array/Repa/Repr/Vector.hs
@@ -20,10 +20,18 @@
 --   representation will be faster.
 data V
 data instance Array V sh e
-        = AVector sh !(V.Vector e)
+        = AVector !sh !(V.Vector e)
         
 deriving instance (Show sh, Show e)
         => Show (Array V sh e)
+
+deriving instance (Read sh, Read e)
+        => Read (Array V sh e)
+
+-- | Sequential equality. The parallel version is `equalsP`.
+deriving instance (Eq sh, Eq e)
+        => Eq (Array V sh e)
+
 
 -- Repr -----------------------------------------------------------------------
 -- | Read elements from a boxed vector array.
diff --git a/repa.cabal b/repa.cabal
--- a/repa.cabal
+++ b/repa.cabal
@@ -1,5 +1,5 @@
 Name:                repa
-Version:             3.1.2.1
+Version:             3.1.3.1
 License:             BSD3
 License-file:        LICENSE
 Author:              The DPH Team
@@ -68,7 +68,6 @@
         Data.Array.Repa.Repr.Vector
         Data.Array.Repa.Specialised.Dim2
         Data.Array.Repa.Stencil.Dim2
-        Data.Array.Repa.Stencil.Partition
         Data.Array.Repa.Eval
         Data.Array.Repa.Index
         Data.Array.Repa.Shape
@@ -86,5 +85,6 @@
         Data.Array.Repa.Eval.Selection
         Data.Array.Repa.Stencil.Base
         Data.Array.Repa.Stencil.Template
+        Data.Array.Repa.Stencil.Partition
         Data.Array.Repa.Base
         
