diff --git a/speedtest/Pointer.hs b/speedtest/Pointer.hs
--- a/speedtest/Pointer.hs
+++ b/speedtest/Pointer.hs
@@ -1,5 +1,5 @@
-{-# OPTIONS_GHC -funbox-strict-fields -ddump-simpl-stats -O2 #-}
-{-  -dverbose-core2core -}
+{-# OPTIONS_GHC -funbox-strict-fields -O2 #-}
+{-  -dverbose-core2core -ddump-simpl-stats -}
 module Main (main) where
 
 import qualified Data.StorableVector.Lazy as SV
diff --git a/speedtest/SpeedTestChorus.hs b/speedtest/SpeedTestChorus.hs
--- a/speedtest/SpeedTestChorus.hs
+++ b/speedtest/SpeedTestChorus.hs
@@ -1,5 +1,6 @@
-{-# OPTIONS_GHC -funbox-strict-fields -ddump-simpl -ddump-asm -O #-}
+{-# OPTIONS_GHC -funbox-strict-fields -O #-}
 {-# LANGUAGE ExistentialQuantification #-}
+{-  -ddump-simpl -ddump-asm -}
 {-  -dverbose-core2core -ddump-simpl-stats -}
 -- I use the dump options only in the main module and not in Cabal
 -- in order to get only code for the main module and not all modules
@@ -33,7 +34,7 @@
 -- import qualified Data.StorableVector.Private as SVP
 
 import qualified Control.Monad.ST.Strict as StrictST
-import Control.Monad.ST.Lazy (ST, runST, strictToLazyST, )
+import Control.Monad.ST.Lazy (strictToLazyST, )
 
 import Foreign.Storable (Storable, )
 import GHC.Float (float2Int, int2Float, double2Int, int2Double, )
@@ -290,8 +291,7 @@
 
 {-# INLINE runGeneratorMonolithic #-}
 runGeneratorMonolithic :: Storable a => Int -> Generator a -> SV.Vector a
-runGeneratorMonolithic size (Generator f s) =
-   fst $ SV.unfoldrN size f s
+runGeneratorMonolithic n (Generator f s) = fst $ SV.unfoldrN n f s
 
 {- SPECIALISE INLINE generator0Gen :: Float -> Float -> Generator Float -}
 {-# INLINE generator0Gen #-}
diff --git a/src/Data/StorableVector.hs b/src/Data/StorableVector.hs
--- a/src/Data/StorableVector.hs
+++ b/src/Data/StorableVector.hs
@@ -7,7 +7,7 @@
 --               (c) Don Stewart 2005-2006
 --               (c) Bjorn Bringert 2006
 --               (c) Spencer Janssen 2006
---               (c) Henning Thielemann 2008-2013
+--               (c) Henning Thielemann 2008-2017
 --
 --
 -- License     : BSD-style
@@ -68,6 +68,7 @@
 
         -- * Transforming 'Vector's
         map,
+        mapIndexed,
         reverse,
         intersperse,
         transpose,
@@ -83,6 +84,7 @@
         -- ** Special folds
         concat,
         concatMap,
+        foldMap,
         monoidConcatMap,
         any,
         all,
@@ -99,7 +101,8 @@
         -- ** Accumulating maps
         mapAccumL,
         mapAccumR,
-        mapIndexed,
+        crochetL,
+        crochetLResult,
 
         -- ** Unfolding 'Vector's
         replicate,
@@ -218,7 +221,6 @@
 import Data.Either (Either(Left, Right), )
 import Data.Maybe.HT (toMaybe, )
 import Data.Maybe (Maybe(Just, Nothing), maybe, fromMaybe, isJust, )
-import Data.Bool.HT (if', )
 import Data.Bool (Bool(False, True), not, otherwise, (&&), (||), )
 import Data.Ord (Ord, min, max, (<), (<=), (>), (>=), )
 import Data.Eq (Eq, (==), (/=), )
@@ -429,10 +431,7 @@
 
 -- | /O(n)/ Append two Vectors
 append :: (Storable a) => Vector a -> Vector a -> Vector a
-append xs ys =
-   if' (null xs) ys $
-   if' (null ys) xs $
-   concat [xs,ys]
+append xs ys = concat [xs,ys]
 {-# INLINE append #-}
 
 -- ---------------------------------------------------------------------
@@ -620,11 +619,19 @@
 -- ---------------------------------------------------------------------
 -- Special folds
 
+{-
+We filter out empty chunks in order to benefit from the special cases
+zero chunks and one chunk.
+In the other cases the preprocessing does not help much.
+-}
 -- | /O(n)/ Concatenate a list of 'Vector's.
 concat :: (Storable a) => [Vector a] -> Vector a
-concat []     = empty
-concat [ps]   = ps
-concat xs     = unsafeCreate len $ \ptr -> go ptr xs
+concat = concatCore . List.filter (not . null)
+
+concatCore :: (Storable a) => [Vector a] -> Vector a
+concatCore []     = empty
+concatCore [ps]   = ps
+concatCore xs     = unsafeCreate len $ \ptr -> go ptr xs
   where len = P.sum . P.map length $ xs
         go =
           Strict.arguments2 $ \ptr ->
@@ -639,11 +646,15 @@
 concatMap f = concat . unpackWith f
 {-# INLINE concatMap #-}
 
--- | This is like @foldMap@ or @mconcat . map f@,
+-- | This is like @mconcat . map f@,
 -- but in many cases the result of @f@ will not be storable.
+foldMap :: (Storable a, Monoid m) => (a -> m) -> Vector a -> m
+foldMap f = foldr (mappend . f) mempty
+{-# INLINE foldMap #-}
+
+{-# DEPRECATED monoidConcatMap "Use foldMap instead." #-}
 monoidConcatMap :: (Storable a, Monoid m) => (a -> m) -> Vector a -> m
-monoidConcatMap f =
-   foldr (mappend . f) mempty
+monoidConcatMap = foldMap
 {-# INLINE monoidConcatMap #-}
 
 -- | /O(n)/ Applied to a predicate and a 'Vector', 'any' determines if
@@ -732,6 +743,33 @@
    in  (acc2, bs)
 {-# INLINE mapAccumR #-}
 
+crochetLResult ::
+   (Storable x, Storable y) =>
+      (x -> acc -> Maybe (y, acc))
+   -> acc
+   -> Vector x
+   -> (Vector y, Maybe acc)
+crochetLResult f acc0 x0 =
+   mapSnd (fmap fst) $
+   unfoldrN
+      (length x0)
+      (\(acc,xt) ->
+         do (x,xs) <- viewL xt
+            (y,acc') <- f x acc
+            return (y, (acc',xs)))
+      (acc0, x0)
+{-# INLINE crochetLResult #-}
+
+crochetL ::
+   (Storable x, Storable y) =>
+      (x -> acc -> Maybe (y, acc))
+   -> acc
+   -> Vector x
+   -> Vector y
+crochetL f acc = fst . crochetLResult f acc
+{-# INLINE crochetL #-}
+
+
 -- | /O(n)/ map functions, provided with the index at each position
 mapIndexed :: (Storable a, Storable b) => (Int -> a -> b) -> Vector a -> Vector b
 mapIndexed f = snd . mapAccumL (\i e -> (i + 1, f i e)) 0
@@ -1400,7 +1438,14 @@
 
 -- | /O(l/n)/ 'sieve' selects every 'n'th element.
 sieve :: (Storable a) => Int -> Vector a -> Vector a
-sieve n (SV fp s l) =
+sieve n xs =
+   case P.compare n 1 of
+      P.LT -> error "sieve: non-positive step size"
+      P.EQ -> xs
+      P.GT -> sieveCore n xs
+
+sieveCore :: (Storable a) => Int -> Vector a -> Vector a
+sieveCore n (SV fp s l) =
    let end = s+l
    in  fst $
        unfoldrN (- div (-l) n)
@@ -1423,6 +1468,8 @@
 -- Restriction is that all input vector must have equal length.
 -- @interleave [pack "adgj", pack "behk", pack "cfil"] = pack ['a'..'l']@
 interleave :: (Storable a) => [Vector a] -> Vector a
+interleave [] = empty
+interleave [xs] = xs
 interleave vs =
    Unsafe.performIO $
    MC.runContT
diff --git a/src/Data/StorableVector/Lazy.hs b/src/Data/StorableVector/Lazy.hs
--- a/src/Data/StorableVector/Lazy.hs
+++ b/src/Data/StorableVector/Lazy.hs
@@ -1,5 +1,5 @@
 {- |
-Chunky signal stream build on StorableVector.
+Chunky signal stream built on StorableVector.
 
 Hints for fusion:
  - Higher order functions should always be inlined in the end
@@ -42,6 +42,7 @@
    foldl,
    foldl',
    foldr,
+   foldMap,
    monoidConcatMap,
    any,
    all,
@@ -69,6 +70,7 @@
    zipWith,
    zipWith3,
    zipWith4,
+   zipWithAppend,
    zipWithLastPattern,
    zipWithLastPattern3,
    zipWithLastPattern4,
@@ -79,6 +81,7 @@
    deinterleave,
    interleaveFirstPattern,
    pad,
+   compact,
    fromChunk,
    hGetContentsAsync,
    hGetContentsSync,
@@ -111,7 +114,7 @@
 
 import Data.Monoid (Monoid, mempty, mappend, mconcat, )
 -- import Control.Arrow ((***))
-import Control.Monad (liftM, liftM2, liftM3, liftM4, {- guard, -} )
+import Control.Monad (liftM, liftM2, liftM3, liftM4, mfilter, )
 
 
 import qualified System.IO as IO
@@ -124,7 +127,7 @@
 import qualified System.IO.Error as Exc
 import qualified System.Unsafe as Unsafe
 
-import Test.QuickCheck (Arbitrary(..))
+import qualified Test.QuickCheck as QC
 
 
 {-
@@ -137,7 +140,7 @@
 
 import Data.Either (Either(Left, Right), either, )
 import Data.Maybe (Maybe(Just, Nothing), maybe, )
-import Data.Function (const, flip, ($), (.), )
+import Data.Function (const, flip, id, ($), (.), )
 import Data.Tuple (fst, snd, uncurry, )
 import Data.Bool (Bool(True,False), not, (&&), )
 import Data.Ord (Ord, (<), (>), (<=), (>=), min, max, )
@@ -168,8 +171,8 @@
          (showString "VectorLazy.fromChunks " .
           showsPrec 10 (chunks xs))
 
-instance (Storable a, Arbitrary a) => Arbitrary (Vector a) where
-   arbitrary = liftM2 pack arbitrary arbitrary
+instance (Storable a, QC.Arbitrary a) => QC.Arbitrary (Vector a) where
+   arbitrary = liftM2 pack QC.arbitrary QC.arbitrary
 
 instance (Storable a) => NFData (Vector a) where
    rnf = rnf . List.map rnf . chunks
@@ -179,8 +182,8 @@
 newtype ChunkSize = ChunkSize Int
    deriving (Eq, Ord, Show)
 
-instance Arbitrary ChunkSize where
-   arbitrary = fmap (ChunkSize . max 1 . min 2048) arbitrary
+instance QC.Arbitrary ChunkSize where
+   arbitrary = fmap ChunkSize $ QC.choose (1,2048)
 
 {-
 ToDo:
@@ -236,10 +239,12 @@
 unpack = List.concatMap V.unpack . chunks
 
 
+{-# WARNING packWith "It seems to be used nowhere and might be removed." #-}
 {-# INLINE packWith #-}
 packWith :: (Storable b) => ChunkSize -> (a -> b) -> [a] -> Vector b
 packWith size f = unfoldr size (fmap (mapFst f) . ListHT.viewL)
 
+{-# WARNING unpackWith "It seems to be used nowhere and might be removed." #-}
 {-# INLINE unpackWith #-}
 unpackWith :: (Storable a) => (a -> b) -> Vector a -> [b]
 unpackWith f = List.concatMap (V.unpackWith f) . chunks
@@ -426,13 +431,14 @@
 foldr f x0 = List.foldr (flip (V.foldr f)) x0 . chunks
 
 
-{- |
-@foldMap@
--}
+{-# INLINE foldMap #-}
+foldMap :: (Storable a, Monoid m) => (a -> m) -> Vector a -> m
+foldMap f = List.foldr (mappend . V.foldMap f) mempty . chunks
+
+{-# DEPRECATED monoidConcatMap "Use foldMap instead." #-}
 {-# INLINE monoidConcatMap #-}
 monoidConcatMap :: (Storable a, Monoid m) => (a -> m) -> Vector a -> m
-monoidConcatMap f =
-   List.foldr (mappend . V.monoidConcatMap f) mempty . chunks
+monoidConcatMap = foldMap
 
 {-# INLINE any #-}
 any :: (Storable a) => (a -> Bool) -> Vector a -> Bool
@@ -442,17 +448,19 @@
 all :: (Storable a) => (a -> Bool) -> Vector a -> Bool
 all p = List.all (V.all p) . chunks
 
-maximum :: (Storable a, Ord a) => Vector a -> a
-maximum =
-   List.maximum . List.map V.maximum . chunks
---   List.foldl1' max . List.map V.maximum . chunks
+maximum, _maximum :: (Storable a, Ord a) => Vector a -> a
+maximum = List.maximum . List.map V.maximum . chunks
+_maximum = List.foldl1' max . List.map V.maximum . chunks
 
-minimum :: (Storable a, Ord a) => Vector a -> a
-minimum =
-   List.minimum . List.map V.minimum . chunks
---   List.foldl1' min . List.map V.minimum . chunks
+minimum, _minimum :: (Storable a, Ord a) => Vector a -> a
+minimum = List.minimum . List.map V.minimum . chunks
+_minimum = List.foldl1' min . List.map V.minimum . chunks
 
 {-
+It is not clear whether this implementation is good.
+Associativity depends on the chunk structure,
+but in principle chunks could be summed in parallel.
+
 sum :: (Storable a, Num a) => Vector a -> a
 sum =
    List.sum . List.map V.sum . chunks
@@ -538,21 +546,14 @@
    List.mapAccumR (V.mapAccumR f) start .
    chunks
 
+{-# DEPRECATED crochetLChunk "Use Storable.Vector.crochetLResult" #-}
 {-# INLINE crochetLChunk #-}
 crochetLChunk :: (Storable x, Storable y) =>
       (x -> acc -> Maybe (y, acc))
    -> acc
    -> V.Vector x
    -> (V.Vector y, Maybe acc)
-crochetLChunk f acc0 x0 =
-   mapSnd (fmap fst) $
-   V.unfoldrN
-      (V.length x0)
-      (\(acc,xt) ->
-         do (x,xs) <- V.viewL xt
-            (y,acc') <- f x acc
-            return (y, (acc',xs)))
-      (acc0, x0)
+crochetLChunk = V.crochetLResult
 
 {-# INLINE crochetL #-}
 crochetL :: (Storable x, Storable y) =>
@@ -564,7 +565,7 @@
    SV . List.unfoldr (\(xt,acc) ->
        do (x,xs) <- ListHT.viewL xt
           acc' <- acc
-          return $ mapSnd ((,) xs) $ crochetLChunk f acc' x) .
+          return $ mapSnd ((,) xs) $ V.crochetLResult f acc' x) .
    flip (,) (Just acc0) .
    chunks
 
@@ -676,7 +677,7 @@
 
 
 {-# INLINE span #-}
-span :: (Storable a) => (a -> Bool) -> Vector a -> (Vector a, Vector a)
+span, _span :: (Storable a) => (a -> Bool) -> Vector a -> (Vector a, Vector a)
 span p =
    let recourse [] = ([],[])
        recourse (x:xs) =
@@ -685,16 +686,17 @@
                 then mapFst (x:) (recourse xs)
                 else (chunks $ fromChunk y, (z:xs))
    in  mapPair (SV, SV) . recourse . chunks
-{-
-span _ (SV []) = (empty, empty)
-span p (SV (x:xs)) =
-   let (y,z) = V.span p x
-   in  if V.length y == 0
-         then mapFst (SV . (x:) . chunks) (span p (SV xs))
-         else (SV [y], SV (z:xs))
--}
 
+_span p =
+   let recourse (SV []) = (empty, empty)
+       recourse (SV (x:xs)) =
+         let (y,z) = V.span p x
+         in  if V.length y == 0
+               then mapFst (SV . (x:) . chunks) (recourse (SV xs))
+               else (SV [y], SV (z:xs))
+   in  recourse
 
+
 -- * other functions
 
 
@@ -714,15 +716,7 @@
    -> Vector a
    -> Vector b
    -> Vector c
-zipWith f as0 bs0 =
-   let recourse at@(a:_) bt@(b:_) =
-          let z = V.zipWith f a b
-              n = V.length z
-          in  z : recourse
-                     (chunks $ drop n $ fromChunks at)
-                     (chunks $ drop n $ fromChunks bt)
-       recourse _ _ = []
-   in  fromChunks $ recourse (chunks as0) (chunks bs0)
+zipWith = zipWithCont (const empty) (const empty)
 
 {-# INLINE zipWith3 #-}
 zipWith3 :: (Storable a, Storable b, Storable c, Storable d) =>
@@ -764,6 +758,34 @@
        recourse (chunks as0) (chunks bs0) (chunks cs0) (chunks ds0)
 
 
+{-# INLINE zipWithAppend #-}
+zipWithAppend :: (Storable a) =>
+      (a -> a -> a)
+   -> Vector a
+   -> Vector a
+   -> Vector a
+zipWithAppend = zipWithCont id id
+
+{-# INLINE zipWithCont #-}
+zipWithCont :: (Storable a, Storable b, Storable c) =>
+      (Vector a -> Vector c)
+   -> (Vector b -> Vector c)
+   -> (a -> b -> c)
+   -> Vector a
+   -> Vector b
+   -> Vector c
+zipWithCont ga gb f as0 bs0 =
+   let recourse at@(a:_) bt@(b:_) =
+          let z = V.zipWith f a b
+              n = V.length z
+          in  z : recourse
+                     (chunks $ drop n $ fromChunks at)
+                     (chunks $ drop n $ fromChunks bt)
+       recourse [] bs = chunks $ gb $ fromChunks bs
+       recourse as [] = chunks $ ga $ fromChunks as
+   in  fromChunks $ recourse (chunks as0) (chunks bs0)
+
+
 {- |
 Preserves chunk pattern of the last argument.
 -}
@@ -774,8 +796,7 @@
    -> Vector b
    -> Vector c
 zipWithLastPattern f =
-   crochetL (\y -> liftM (mapFst (flip f y)) . Ptr.viewL)
-    . pointer
+   crochetL (\y -> liftM (mapFst (flip f y)) . Ptr.viewL) . pointer
 
 {- |
 Preserves chunk pattern of the last argument.
@@ -834,8 +855,7 @@
 zipWithSize3 size f s0 s1 s2 =
    unfoldr size (\(xt,yt,zt) ->
       liftM3
-         (\(x,xs) (y,ys) (z,zs) ->
-             (f x y z, (xs,ys,zs)))
+         (\(x,xs) (y,ys) (z,zs) -> (f x y z, (xs,ys,zs)))
          (Ptr.viewL xt)
          (Ptr.viewL yt)
          (Ptr.viewL zt))
@@ -849,8 +869,7 @@
 zipWithSize4 size f s0 s1 s2 s3 =
    unfoldr size (\(xt,yt,zt,wt) ->
       liftM4
-         (\(x,xs) (y,ys) (z,zs) (w,ws) ->
-             (f x y z w, (xs,ys,zs,ws)))
+         (\(x,xs) (y,ys) (z,zs) (w,ws) -> (f x y z w, (xs,ys,zs,ws)))
          (Ptr.viewL xt)
          (Ptr.viewL yt)
          (Ptr.viewL zt)
@@ -881,7 +900,8 @@
 All input vectors must have the same length.
 -}
 {-# INLINE interleaveFirstPattern #-}
-interleaveFirstPattern :: (Storable a) => [Vector a] -> Vector a
+interleaveFirstPattern, _interleaveFirstPattern ::
+   (Storable a) => [Vector a] -> Vector a
 interleaveFirstPattern [] = empty
 interleaveFirstPattern vss@(vs:_) =
    let pattern = List.map V.length $ chunks vs
@@ -893,8 +913,8 @@
    in  fromChunks $ List.map V.interleave $
        List.transpose $ List.map split vss
 
-{-
-interleaveFirstPattern vss@(vs:_) =
+_interleaveFirstPattern [] = empty
+_interleaveFirstPattern vss@(vs:_) =
    fromChunks . snd .
    List.mapAccumL
       (\xss n ->
@@ -903,7 +923,6 @@
          List.unzip $ List.map (splitAt n) xss)
       vss .
    List.map V.length . chunks $ vs
--}
 
 
 
@@ -922,6 +941,7 @@
                  x:xs -> x : recourse (n - V.length x) xs
    in  SV . recourse n0 . chunks
 
+{-# WARNING padAlt "use 'pad' instead" #-}
 padAlt :: (Storable a) => ChunkSize -> a -> Int -> Vector a -> Vector a
 padAlt size x n xs =
    append xs
@@ -930,13 +950,32 @@
              then replicate size (n-m) x
              else empty)
 
+compact :: (Storable a) => ChunkSize -> Vector a -> Vector a
+compact size (SV xs) =
+   SV $ List.map V.concat $
+   compactGen
+      (\x y -> mfilter (<=size) $ Just $ mappend x y)
+      (ChunkSize . V.length) xs
 
+compactGen :: (b -> b -> Maybe b) -> (a -> b) -> [a] -> [[a]]
+compactGen _ _ [] = []
+compactGen plus measure (x0:xs0) =
+   uncurry (:) $ mapFst (x0:) $
+   List.foldr
+      (\y go s0 ->
+         let ym = measure y
+         in  case plus s0 ym of
+               Just s1 -> mapFst (y:) $ go s1
+               Nothing -> ([], uncurry (:) $ mapFst (y:) $ go ym))
+      (const ([], [])) xs0 (measure x0)
 
 
 
+
 -- * Helper functions for StorableVector
 
 
+{-# WARNING cancelNullVector "do not use it" #-}
 {-# INLINE cancelNullVector #-}
 cancelNullVector :: (V.Vector a, b) -> Maybe (V.Vector a, b)
 cancelNullVector y =
diff --git a/src/Data/StorableVector/Lazy/Typed.hs b/src/Data/StorableVector/Lazy/Typed.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/StorableVector/Lazy/Typed.hs
@@ -0,0 +1,707 @@
+{- |
+Like "Data.StorableVector.Lazy"
+but the maximum chunk size is encoded in a type parameter.
+This way, you do not need to pass a chunk size parameter at various places.
+The API becomes more like the one for lists and 'ByteString's.
+-}
+module Data.StorableVector.Lazy.Typed (
+   Vector,
+   DefaultVector,
+   Size,
+   ChunkSize,
+   chunkSize,
+   lazyChunkSize,
+   DefaultChunkSize,
+   Size1024,
+   empty,
+   singleton,
+   toVectorLazy,
+   fromVectorLazy,
+   chunks,
+   fromChunks,
+   pack,
+   unpack,
+   unfoldr,
+   unfoldrResult,
+   sample,
+   sampleN,
+   iterate,
+   repeat,
+   cycle,
+   replicate,
+   null,
+   length,
+   equal,
+   index,
+   cons,
+   append,
+   extendL,
+   concat,
+   sliceVertical,
+   snoc,
+   map,
+   reverse,
+   foldl,
+   foldl',
+   foldr,
+   foldMap,
+   any,
+   all,
+   maximum,
+   minimum,
+   viewL,
+   viewR,
+   switchL,
+   switchR,
+   scanl,
+   mapAccumL,
+   mapAccumR,
+   crochetL,
+   take,
+   takeEnd,
+   drop,
+   splitAt,
+   dropMarginRem,
+   dropMargin,
+   dropWhile,
+   takeWhile,
+   span,
+   filter,
+   zipWith,
+   zipWith3,
+   zipWith4,
+   zipWithAppend,
+   zipWithLastPattern,
+   zipWithLastPattern3,
+   zipWithLastPattern4,
+   zipWithSize,
+   zipWithSize3,
+   zipWithSize4,
+   sieve,
+   deinterleave,
+   interleaveFirstPattern,
+   pad,
+   hGetContentsAsync,
+   hGetContentsSync,
+   hPut,
+   readFileAsync,
+   writeFile,
+   appendFile,
+   interact,
+   ) where
+
+import qualified Data.StorableVector.Lazy as SVL
+import qualified Data.StorableVector as V
+import qualified Data.List as List
+
+import Foreign.Storable (Storable)
+import System.IO (IO, FilePath, Handle)
+import Test.QuickCheck (Arbitrary(arbitrary))
+
+import Control.DeepSeq (NFData, rnf)
+import Control.Monad (fmap)
+
+import Data.Function.HT (compose2)
+import Data.Tuple.HT (mapPair, mapFst, mapSnd)
+import Data.Maybe.HT (toMaybe)
+import Data.Monoid (Monoid, mempty, mappend, mconcat)
+import Data.Either (Either)
+import Data.Maybe (Maybe(Just))
+import Data.Function (flip, ($), (.))
+import Data.Tuple (fst)
+import Data.Bool (Bool)
+import Data.Ord (Ord, (<), (>=))
+import Data.Eq (Eq, (==))
+import Text.Show (Show, showsPrec, showParen, showString)
+import Prelude (IOError, Int, succ)
+
+
+{- |
+A @Vector size a@ represents a chunky storable vector
+with maximum chunk size expressed by type parameter @size@.
+-}
+newtype Vector size a = SV {plain :: SVL.Vector a}
+
+
+newtype ChunkSize size = ChunkSize Int
+
+lazyChunkSize :: ChunkSize size -> SVL.ChunkSize
+lazyChunkSize (ChunkSize size) = SVL.chunkSize size
+
+class Size size where
+   chunkSize :: ChunkSize size
+
+instance Size Size1024 where
+   chunkSize = ChunkSize 1024
+
+_dummySize :: Size1024
+_dummySize = Size1024
+
+type DefaultChunkSize = Size1024
+data Size1024 = Size1024
+
+type DefaultVector = Vector DefaultChunkSize
+
+
+withChunkSize ::
+   (Size size) => (ChunkSize size -> Vector size a) -> Vector size a
+withChunkSize f = f chunkSize
+
+withLazyChunkSize ::
+   (Size size) => (SVL.ChunkSize -> SVL.Vector a) -> Vector size a
+withLazyChunkSize f = withChunkSize $ lift0 . f . lazyChunkSize
+
+getChunkSize :: (Size size) => Vector size a -> ChunkSize size
+getChunkSize _ = chunkSize
+
+
+lift0 :: SVL.Vector a -> Vector size a
+lift0 = SV
+
+lift1 ::
+   (SVL.Vector a -> SVL.Vector b) ->
+   Vector size a -> Vector size b
+lift1 f (SV a) = SV (f a)
+
+lift2 ::
+   (SVL.Vector a -> SVL.Vector b -> SVL.Vector c) ->
+   Vector size a -> Vector size b -> Vector size c
+lift2 f (SV a) (SV b) = SV (f a b)
+
+lift3 ::
+   (SVL.Vector a -> SVL.Vector b -> SVL.Vector c -> SVL.Vector d) ->
+   Vector size a -> Vector size b -> Vector size c -> Vector size d
+lift3 f (SV a) (SV b) (SV c) = SV (f a b c)
+
+lift4 ::
+   (SVL.Vector a -> SVL.Vector b -> SVL.Vector c -> SVL.Vector d ->
+    SVL.Vector e) ->
+   Vector size a -> Vector size b -> Vector size c -> Vector size d ->
+   Vector size e
+lift4 f (SV a) (SV b) (SV c) (SV d) = SV (f a b c d)
+
+
+instance (Size size, Storable a) => Monoid (Vector size a) where
+    mempty  = empty
+    mappend = append
+    mconcat = concat
+
+instance (Size size, Storable a, Eq a) => Eq (Vector size a) where
+   (==) = equal
+
+instance (Size size, Storable a, Show a) => Show (Vector size a) where
+   showsPrec p xs =
+      showParen (p>=10)
+         (showString "VectorLazyTyped.fromChunks " .
+          showsPrec 10 (SVL.chunks $ plain xs))
+
+{- |
+This generates chunks of maximum size.
+If you want to have chunks of varying size, use
+
+> fromChunks <$> arbitrary
+
+instead.
+-}
+instance (Size size, Storable a, Arbitrary a) => Arbitrary (Vector size a) where
+   arbitrary = fmap pack arbitrary
+
+instance (Size size, Storable a) => NFData (Vector size a) where
+   rnf = rnf . plain
+
+
+-- * Introducing and eliminating 'Vector's
+
+{-# INLINE empty #-}
+empty :: (Storable a) => Vector size a
+empty = lift0 SVL.empty
+
+{-# INLINE singleton #-}
+singleton :: (Storable a) => a -> Vector size a
+singleton = lift0 . SVL.singleton
+
+toVectorLazy :: Vector size a -> SVL.Vector a
+toVectorLazy = plain
+
+{- |
+This will maintain all laziness breaks,
+but if chunks are too big, they will be split.
+-}
+fromVectorLazy :: (Size size, Storable a) => SVL.Vector a -> Vector size a
+fromVectorLazy = fromChunks . SVL.chunks
+
+chunks :: Vector size a -> [V.Vector a]
+chunks = SVL.chunks . plain
+
+fromChunks :: (Size size, Storable a) => [V.Vector a] -> Vector size a
+fromChunks xs =
+   withChunkSize $ \(ChunkSize size) ->
+      fromChunksUnchecked $ List.concatMap (V.sliceVertical size) xs
+
+fromChunksUnchecked :: (Storable a) => [V.Vector a] -> Vector size a
+fromChunksUnchecked = lift0 . SVL.fromChunks
+
+pack :: (Size size, Storable a) => [a] -> Vector size a
+pack xs = withLazyChunkSize $ \size -> SVL.pack size xs
+
+unpack :: (Storable a) => Vector size a -> [a]
+unpack = SVL.unpack . plain
+
+
+{-# INLINE unfoldr #-}
+unfoldr :: (Size size, Storable b) =>
+   (a -> Maybe (b,a)) ->
+   a ->
+   Vector size b
+unfoldr f a =
+   withLazyChunkSize $ \cs -> SVL.unfoldr cs f a
+
+{-# INLINE unfoldrResult #-}
+unfoldrResult :: (Size size, Storable b) =>
+   (a -> Either c (b, a)) ->
+   a ->
+   (Vector size b, c)
+unfoldrResult f a =
+   let x =
+         mapFst lift0 $
+         SVL.unfoldrResult (lazyChunkSize $ getChunkSize $ fst x) f a
+   in  x
+
+
+{-# INLINE sample #-}
+sample, _sample :: (Size size, Storable a) => (Int -> a) -> Vector size a
+sample f = withLazyChunkSize $ \cs -> SVL.sample cs f
+
+_sample f = unfoldr (\i -> Just (f i, succ i)) 0
+
+{-# INLINE sampleN #-}
+sampleN, _sampleN ::
+   (Size size, Storable a) => Int -> (Int -> a) -> Vector size a
+sampleN n f = withLazyChunkSize $ \cs -> SVL.sampleN cs n f
+
+_sampleN n f = unfoldr (\i -> toMaybe (i<n) (f i, succ i)) 0
+
+
+{-# INLINE iterate #-}
+iterate :: (Size size, Storable a) => (a -> a) -> a -> Vector size a
+iterate f a = withLazyChunkSize $ \cs -> SVL.iterate cs f a
+
+repeat :: (Size size, Storable a) => a -> Vector size a
+repeat a = withLazyChunkSize $ \cs -> SVL.repeat cs a
+
+cycle :: (Size size, Storable a) => Vector size a -> Vector size a
+cycle = lift1 SVL.cycle
+
+replicate :: (Size size, Storable a) => Int -> a -> Vector size a
+replicate n a = withLazyChunkSize $ \cs -> SVL.replicate cs n a
+
+
+
+-- * Basic interface
+
+{-# INLINE null #-}
+null :: (Size size, Storable a) => Vector size a -> Bool
+null = SVL.null . plain
+
+length :: Vector size a -> Int
+length = SVL.length . plain
+
+equal :: (Size size, Storable a, Eq a) => Vector size a -> Vector size a -> Bool
+equal = compose2 SVL.equal plain
+
+index :: (Size size, Storable a) => Vector size a -> Int -> a
+index (SV xs) = SVL.index xs
+
+
+{-# INLINE cons #-}
+cons :: (Size size, Storable a) => a -> Vector size a -> Vector size a
+cons x = lift1 (SVL.cons x)
+
+infixr 5 `append`
+
+{-# INLINE append #-}
+append ::
+   (Size size, Storable a) => Vector size a -> Vector size a -> Vector size a
+append = lift2 SVL.append
+
+
+{- |
+@extendL x y@
+prepends the chunk @x@ and merges it with the first chunk of @y@
+if the total size is at most @size@.
+This way you can prepend small chunks
+while asserting a reasonable average size for chunks.
+The prepended chunk must be smaller than the maximum chunk size in the Vector.
+This is not checked.
+-}
+extendL ::
+   (Size size, Storable a) => V.Vector a -> Vector size a -> Vector size a
+extendL x ys = withLazyChunkSize $ \cs -> SVL.extendL cs x (plain ys)
+
+
+concat :: (Size size, Storable a) => [Vector size a] -> Vector size a
+concat = lift0 . SVL.concat . List.map plain
+
+sliceVertical ::
+   (Size size, Storable a) => Int -> Vector size a -> [Vector size a]
+sliceVertical n = List.map lift0 . SVL.sliceVertical n . plain
+
+{-# INLINE snoc #-}
+snoc :: (Size size, Storable a) => Vector size a -> a -> Vector size a
+snoc = flip $ \x -> lift1 (flip SVL.snoc x)
+
+
+-- * Transformations
+
+{-# INLINE map #-}
+map :: (Size size, Storable x, Storable y) =>
+      (x -> y)
+   -> Vector size x
+   -> Vector size y
+map f = lift1 (SVL.map f)
+
+
+reverse :: (Size size, Storable a) => Vector size a -> Vector size a
+reverse = lift1 SVL.reverse
+
+
+-- * Reducing 'Vector's
+
+{-# INLINE foldl #-}
+foldl :: (Size size, Storable b) => (a -> b -> a) -> a -> Vector size b -> a
+foldl f x0 = SVL.foldl f x0 . plain
+
+{-# INLINE foldl' #-}
+foldl' :: (Size size, Storable b) => (a -> b -> a) -> a -> Vector size b -> a
+foldl' f x0 = SVL.foldl' f x0 . plain
+
+{-# INLINE foldr #-}
+foldr :: (Size size, Storable b) => (b -> a -> a) -> a -> Vector size b -> a
+foldr f x0 = SVL.foldr f x0 . plain
+
+
+{-# INLINE foldMap #-}
+foldMap ::
+   (Size size, Storable a, Monoid m) => (a -> m) -> Vector size a -> m
+foldMap f = SVL.foldMap f . plain
+
+{-# INLINE any #-}
+any :: (Size size, Storable a) => (a -> Bool) -> Vector size a -> Bool
+any p = SVL.any p . plain
+
+{-# INLINE all #-}
+all :: (Size size, Storable a) => (a -> Bool) -> Vector size a -> Bool
+all p = SVL.all p . plain
+
+maximum :: (Size size, Storable a, Ord a) => Vector size a -> a
+maximum = SVL.maximum . plain
+
+minimum :: (Size size, Storable a, Ord a) => Vector size a -> a
+minimum = SVL.minimum . plain
+
+
+-- * inspecting a vector
+
+{-# INLINE viewL #-}
+viewL :: (Size size, Storable a) => Vector size a -> Maybe (a, Vector size a)
+viewL = fmap (mapSnd lift0) . SVL.viewL . plain
+
+{-# INLINE viewR #-}
+viewR :: (Size size, Storable a) => Vector size a -> Maybe (Vector size a, a)
+viewR = fmap (mapFst lift0) . SVL.viewR . plain
+
+{-# INLINE switchL #-}
+switchL ::
+   (Size size, Storable a) =>
+   b -> (a -> Vector size a -> b) -> Vector size a -> b
+switchL n j = SVL.switchL n (\a -> j a . lift0) . plain
+
+{-# INLINE switchR #-}
+switchR ::
+   (Size size, Storable a) =>
+   b -> (Vector size a -> a -> b) -> Vector size a -> b
+switchR n j = SVL.switchR n (j . lift0) . plain
+
+
+{-# INLINE scanl #-}
+scanl :: (Size size, Storable a, Storable b) =>
+   (a -> b -> a) -> a -> Vector size b -> Vector size a
+scanl f start = lift1 $ SVL.scanl f start
+
+{-# INLINE mapAccumL #-}
+mapAccumL :: (Size size, Storable a, Storable b) =>
+   (acc -> a -> (acc, b)) -> acc -> Vector size a -> (acc, Vector size b)
+mapAccumL f start = mapSnd lift0 . SVL.mapAccumL f start . plain
+
+{-# INLINE mapAccumR #-}
+mapAccumR :: (Size size, Storable a, Storable b) =>
+   (acc -> a -> (acc, b)) -> acc -> Vector size a -> (acc, Vector size b)
+mapAccumR f start = mapSnd lift0 . SVL.mapAccumR f start . plain
+
+{-# INLINE crochetL #-}
+crochetL ::
+   (Size size, Storable x, Storable y) =>
+      (x -> acc -> Maybe (y, acc))
+   -> acc
+   -> Vector size x
+   -> Vector size y
+crochetL f acc0 = lift1 $ SVL.crochetL f acc0
+
+
+
+-- * sub-vectors
+
+{-# INLINE take #-}
+take :: (Size size, Storable a) => Int -> Vector size a -> Vector size a
+take n = lift1 $ SVL.take n
+
+{-# INLINE takeEnd #-}
+takeEnd :: (Size size, Storable a) => Int -> Vector size a -> Vector size a
+takeEnd n = lift1 $ SVL.takeEnd n
+
+{-# INLINE drop #-}
+drop :: (Size size, Storable a) => Int -> Vector size a -> Vector size a
+drop n = lift1 $ SVL.drop n
+
+{-# INLINE splitAt #-}
+splitAt ::
+   (Size size, Storable a) =>
+   Int -> Vector size a -> (Vector size a, Vector size a)
+splitAt n =
+   mapPair (lift0, lift0) . SVL.splitAt n . plain
+
+
+
+{-# INLINE dropMarginRem #-}
+dropMarginRem ::
+   (Size size, Storable a) =>
+   Int -> Int -> Vector size a -> (Int, Vector size a)
+dropMarginRem n m = mapSnd lift0 . SVL.dropMarginRem n m . plain
+
+{-# INLINE dropMargin #-}
+dropMargin ::
+   (Size size, Storable a) => Int -> Int -> Vector size a -> Vector size a
+dropMargin n m = lift1 $ SVL.dropMargin n m
+
+
+
+{-# INLINE dropWhile #-}
+dropWhile ::
+   (Size size, Storable a) => (a -> Bool) -> Vector size a -> Vector size a
+dropWhile p = lift1 $ SVL.dropWhile p
+
+{-# INLINE takeWhile #-}
+takeWhile ::
+   (Size size, Storable a) => (a -> Bool) -> Vector size a -> Vector size a
+takeWhile p = lift1 $ SVL.takeWhile p
+
+
+{-# INLINE span #-}
+span ::
+   (Size size, Storable a) =>
+   (a -> Bool) -> Vector size a -> (Vector size a, Vector size a)
+span p = mapPair (lift0, lift0) . SVL.span p . plain
+
+
+
+-- * other functions
+
+
+{-# INLINE filter #-}
+filter ::
+   (Size size, Storable a) => (a -> Bool) -> Vector size a -> Vector size a
+filter p = lift1 $ SVL.filter p
+
+
+{- |
+Generates laziness breaks
+wherever one of the input signals has a chunk boundary.
+-}
+{-# INLINE zipWith #-}
+zipWith :: (Size size, Storable a, Storable b, Storable c) =>
+      (a -> b -> c)
+   -> Vector size a
+   -> Vector size b
+   -> Vector size c
+zipWith f = lift2 $ SVL.zipWith f
+
+{-# INLINE zipWith3 #-}
+zipWith3 :: (Size size, Storable a, Storable b, Storable c, Storable d) =>
+      (a -> b -> c -> d)
+   -> Vector size a
+   -> Vector size b
+   -> Vector size c
+   -> Vector size d
+zipWith3 f = lift3 $ SVL.zipWith3 f
+
+{-# INLINE zipWith4 #-}
+zipWith4 ::
+   (Size size, Storable a, Storable b, Storable c, Storable d, Storable e) =>
+      (a -> b -> c -> d -> e)
+   -> Vector size a
+   -> Vector size b
+   -> Vector size c
+   -> Vector size d
+   -> Vector size e
+zipWith4 f = lift4 $ SVL.zipWith4 f
+
+
+{-# INLINE zipWithAppend #-}
+zipWithAppend :: (Size size, Storable a) =>
+      (a -> a -> a)
+   -> Vector size a
+   -> Vector size a
+   -> Vector size a
+zipWithAppend f = lift2 $ SVL.zipWithAppend f
+
+
+
+{- |
+Preserves chunk pattern of the last argument.
+-}
+{-# INLINE zipWithLastPattern #-}
+zipWithLastPattern :: (Size size, Storable a, Storable b, Storable c) =>
+      (a -> b -> c)
+   -> Vector size a
+   -> Vector size b
+   -> Vector size c
+zipWithLastPattern f = lift2 $ SVL.zipWithLastPattern f
+
+{- |
+Preserves chunk pattern of the last argument.
+-}
+{-# INLINE zipWithLastPattern3 #-}
+zipWithLastPattern3 ::
+   (Size size, Storable a, Storable b, Storable c, Storable d) =>
+   (a -> b -> c -> d) ->
+   (Vector size a -> Vector size b -> Vector size c -> Vector size d)
+zipWithLastPattern3 f = lift3 $ SVL.zipWithLastPattern3 f
+
+{- |
+Preserves chunk pattern of the last argument.
+-}
+{-# INLINE zipWithLastPattern4 #-}
+zipWithLastPattern4 ::
+   (Size size, Storable a, Storable b, Storable c, Storable d, Storable e) =>
+   (a -> b -> c -> d -> e) ->
+   (Vector size a -> Vector size b -> Vector size c -> Vector size d -> Vector size e)
+zipWithLastPattern4 f = lift4 $ SVL.zipWithLastPattern4 f
+
+
+{-# INLINE zipWithSize #-}
+zipWithSize :: (Size size, Storable a, Storable b, Storable c) =>
+      (a -> b -> c)
+   -> Vector size a
+   -> Vector size b
+   -> Vector size c
+zipWithSize f a b =
+   withLazyChunkSize $ \cs -> SVL.zipWithSize cs f (plain a) (plain b)
+
+{-# INLINE zipWithSize3 #-}
+zipWithSize3 ::
+   (Size size, Storable a, Storable b, Storable c, Storable d) =>
+   (a -> b -> c -> d) ->
+   (Vector size a -> Vector size b -> Vector size c -> Vector size d)
+zipWithSize3 f a b c =
+   withLazyChunkSize $ \cs ->
+      SVL.zipWithSize3 cs f (plain a) (plain b) (plain c)
+
+{-# INLINE zipWithSize4 #-}
+zipWithSize4 ::
+   (Size size, Storable a, Storable b, Storable c, Storable d, Storable e) =>
+   (a -> b -> c -> d -> e) ->
+   (Vector size a -> Vector size b -> Vector size c -> Vector size d -> Vector size e)
+zipWithSize4 f a b c d =
+   withLazyChunkSize $ \cs ->
+      SVL.zipWithSize4 cs f (plain a) (plain b) (plain c) (plain d)
+
+
+-- * interleaved vectors
+
+{-# INLINE sieve #-}
+sieve :: (Size size, Storable a) => Int -> Vector size a -> Vector size a
+sieve n = lift1 $ SVL.sieve n
+
+{-# INLINE deinterleave #-}
+deinterleave ::
+   (Size size, Storable a) => Int -> Vector size a -> [Vector size a]
+deinterleave n =
+   List.map lift0 . SVL.deinterleave n . plain
+
+{- |
+Interleave lazy vectors
+while maintaining the chunk pattern of the first vector.
+All input vectors must have the same length.
+-}
+{-# INLINE interleaveFirstPattern #-}
+interleaveFirstPattern ::
+   (Size size, Storable a) => [Vector size a] -> Vector size a
+interleaveFirstPattern = lift0 . SVL.interleaveFirstPattern . List.map plain
+
+
+
+{- |
+Ensure a minimal length of the list by appending pad values.
+-}
+{- disabled INLINE pad -}
+pad ::
+   (Size size, Storable a) =>
+   a -> Int -> Vector size a -> Vector size a
+pad y n xs = withLazyChunkSize $ \cs -> SVL.pad cs y n $ plain xs
+
+
+
+
+
+-- * IO
+
+withIOErrorChunkSize ::
+   (Size size) =>
+   (ChunkSize size -> IO (IOError, Vector size a)) ->
+   IO (IOError, Vector size a)
+withIOErrorChunkSize act = act chunkSize
+
+hGetContentsAsync :: (Size size, Storable a) =>
+   Handle -> IO (IOError, Vector size a)
+hGetContentsAsync h =
+   withIOErrorChunkSize $ \cs ->
+      fmap (mapSnd lift0) $ SVL.hGetContentsAsync (lazyChunkSize cs) h
+
+
+withIOChunkSize ::
+   (Size size) =>
+   (ChunkSize size -> IO (Vector size a)) ->
+   IO (Vector size a)
+withIOChunkSize act = act chunkSize
+
+hGetContentsSync ::
+   (Size size, Storable a) =>
+   Handle -> IO (Vector size a)
+hGetContentsSync h =
+   withIOChunkSize $ \cs ->
+      fmap lift0 $ SVL.hGetContentsSync (lazyChunkSize cs) h
+
+hPut :: (Size size, Storable a) => Handle -> Vector size a -> IO ()
+hPut h = SVL.hPut h . plain
+
+readFileAsync ::
+   (Size size, Storable a) => FilePath -> IO (IOError, Vector size a)
+readFileAsync path =
+   withIOErrorChunkSize $ \cs ->
+      fmap (mapSnd lift0) $ SVL.readFileAsync (lazyChunkSize cs) path
+
+writeFile :: (Size size, Storable a) => FilePath -> Vector size a -> IO ()
+writeFile path = SVL.writeFile path . plain
+
+appendFile :: (Size size, Storable a) => FilePath -> Vector size a -> IO ()
+appendFile path = SVL.appendFile path . plain
+
+interact ::
+   (Size size, Storable a) =>
+   (Vector size a -> Vector size a) -> IO ()
+interact = interactAux chunkSize
+
+interactAux ::
+   (Size size, Storable a) =>
+   ChunkSize size -> (Vector size a -> Vector size a) -> IO ()
+interactAux cs f = SVL.interact (lazyChunkSize cs) (plain . f . lift0)
diff --git a/storablevector.cabal b/storablevector.cabal
--- a/storablevector.cabal
+++ b/storablevector.cabal
@@ -1,5 +1,5 @@
 Name:                storablevector
-Version:             0.2.11
+Version:             0.2.12
 Category:            Data
 Synopsis:            Fast, packed, strict storable arrays with a list interface like ByteString
 Description:
@@ -48,7 +48,7 @@
 Source-Repository this
   type:     darcs
   location: http://code.haskell.org/storablevector/
-  tag:      0.2.11
+  tag:      0.2.12
 
 
 Library
@@ -71,7 +71,7 @@
       If flag(separateSYB)
         Build-Depends:
           base >=4 && <5,
-          syb >=0.1 && <0.7
+          syb >=0.1 && <0.8
       Else
         Build-Depends:
           base >=3 && <4
@@ -90,6 +90,7 @@
     Data.StorableVector.Lazy.Builder
     Data.StorableVector.Lazy.Pattern
     Data.StorableVector.Lazy.Pointer
+    Data.StorableVector.Lazy.Typed
     Data.StorableVector.ST.Strict
     Data.StorableVector.ST.Lazy
 
@@ -111,7 +112,11 @@
   Default-Language:    Haskell98
   Hs-Source-Dirs:      tests
   Main-Is:             Test.hs
-  Other-Modules:       Test.Utility
+  Other-Modules:
+    Alternative.Lazy
+    Test.Lazy
+    Test.Strict
+    Test.Utility
   Build-Depends:
     storablevector,
     bytestring >=0.9 && <0.11,
@@ -137,7 +142,7 @@
   Build-Depends:
     storablevector,
     sample-frame >=0.0.1 && <0.1,
-    deepseq >=1.1 && <1.4
+    deepseq
   If flag(splitBase)
     Build-Depends:   base >= 3 && <5
   Else
diff --git a/tests/Alternative/Lazy.hs b/tests/Alternative/Lazy.hs
new file mode 100644
--- /dev/null
+++ b/tests/Alternative/Lazy.hs
@@ -0,0 +1,71 @@
+{- |
+Alternative implementations for functions in "Data.StorableVector.Lazy".
+We want to use it for testing against the prefered implementations.
+-}
+module Alternative.Lazy where
+
+import qualified Data.List.Match as Match
+import qualified Data.List as List
+import Data.Tuple.HT (mapFst)
+import Data.Maybe.HT (toMaybe)
+
+
+-- compact0 2 [] = [[]] - bad
+-- compact0 2 [10] = [[],[10]] - bad
+compact0 :: Int -> [Int] -> [[Int]]
+compact0 maxS =
+   let go _ xs [] = [xs]
+       go s0 xs (y:ys) =
+         let s1 = s0+y
+         in  if s1<=maxS
+               then go s1 (xs++[y]) ys
+               else xs : go y [y] ys
+   in  go 0 []
+
+-- compact1 2 [] = [[]] - bad
+-- compact1 2 [10] = [[],[10]] - bad
+compact1 :: Int -> [Int] -> [[Int]]
+compact1 maxS =
+   let go _ [] = ([], [])
+       go s0 (y:ys) =
+         let s1 = s0+y
+         in  if s1<=maxS
+               then mapFst (y:) $ go s1 ys
+               else ([], uncurry (:) $ mapFst (y:) $ go y ys)
+   in  uncurry (:) . go 0
+
+compact2 :: Int -> [Int] -> [[Int]]
+compact2 maxS =
+   let go _ [] = ([], [])
+       go s0 (y:ys) =
+         let s1 = s0+y
+         in  if s1<=maxS
+               then mapFst (y:) $ go s1 ys
+               else ([], uncurry (:) $ mapFst (y:) $ go y ys)
+   in  (\(xs,xss) -> if List.null xs then xss else xs:xss) . go 0
+
+{- |
+This is the counterpart to the actual implementation in StorableVector.Lazy.
+-}
+compact3 :: Int -> [Int] -> [[Int]]
+compact3 maxS =
+   (\(xs,xss) -> if List.null xs then xss else xs:xss) .
+   (\xs ->
+      List.foldr
+         (\y go s0 ->
+            let s1 = s0+y
+            in  if s1<=maxS
+                  then mapFst (y:) $ go s1
+                  else ([], uncurry (:) $ mapFst (y:) $ go y))
+         (const ([], [])) xs 0)
+
+compact4 :: Int -> [Int] -> [[Int]]
+compact4 maxS =
+   List.unfoldr $ \xs -> toMaybe (not $ List.null xs) $
+      Match.splitAt
+         (minLength1 $ List.takeWhile (<= maxS) $
+          List.tail $ List.scanl (+) 0 xs)
+         xs
+
+minLength1 :: [Int] -> [Int]
+minLength1 = (0:) . List.drop 1
diff --git a/tests/Test.hs b/tests/Test.hs
--- a/tests/Test.hs
+++ b/tests/Test.hs
@@ -1,235 +1,15 @@
-import qualified Data.StorableVector as V
-import qualified Data.ByteString as P
-import qualified Data.List.HT as ListHT
-import Test.QuickCheck.Modifiers (Positive(Positive), )
-import Test.QuickCheck (Property, quickCheck, )
-import Test.Utility
-          (V, W, X, P, applyId, applyModel,
-           eq0, eq1, eq2, eqnotnull1, eqnotnull2, eqnotnull3, )
-import Text.Printf (printf)
-
-
--- * compare Data.StorableVector <=> ByteString
-
-limit :: Int -> Int
-limit = flip mod 10000
-
-prop_concatVP :: [V] -> Bool
-prop_nullVP :: V -> Bool
-prop_reverseVP :: V -> Bool
-prop_transposeVP :: [V] -> Bool
-prop_groupVP :: V -> Bool
-prop_initsVP :: V -> Bool
-prop_tailsVP :: V -> Bool
-prop_allVP :: (W -> Bool) -> V -> Bool
-prop_anyVP :: (W -> Bool) -> V -> Bool
-prop_appendVP :: V -> V -> Bool
-prop_breakVP :: (W -> Bool) -> V -> Bool
-prop_concatMapVP :: (W -> V) -> V -> Bool
-prop_consVP :: W -> V -> Bool
-prop_countVP :: W -> V -> Bool
-prop_dropVP :: X -> V -> Bool
-prop_dropWhileVP :: (W -> Bool) -> V -> Bool
-prop_filterVP :: (W -> Bool) -> V -> Bool
-prop_findVP :: (W -> Bool) -> V -> Bool
-prop_findIndexVP :: (W -> Bool) -> V -> Bool
-prop_findIndicesVP :: (W -> Bool) -> V -> Bool
-prop_isPrefixOfVP :: V -> V -> Bool
-prop_mapVP :: (W -> W) -> V -> Bool
-prop_replicateVP :: X -> W -> Bool
-prop_iterateVP :: X -> (W -> W) -> W -> Bool
-prop_snocVP :: V -> W -> Bool
-prop_spanVP :: (W -> Bool) -> V -> Bool
-prop_splitVP :: W -> V -> Bool
-prop_splitAtVP :: X -> V -> Bool
-prop_sieveVP :: Positive X -> V -> Bool
-prop_sliceVerticalVP :: Positive X -> V -> Bool
-prop_deinterleaveVP :: Positive X -> V -> Bool
-prop_interleaveVP :: Positive X -> V -> Bool
-prop_takeVP :: X -> V -> Bool
-prop_takeWhileVP :: (W -> Bool) -> V -> Bool
-prop_elemVP :: W -> V -> Bool
-prop_notElemVP :: W -> V -> Bool
-prop_elemIndexVP :: W -> V -> Bool
-prop_elemIndicesVP :: W -> V -> Bool
-prop_lengthVP :: V -> Bool
-prop_headVP :: V -> Property
-prop_initVP :: V -> Property
-prop_lastVP :: V -> Property
-prop_maximumVP :: V -> Property
-prop_minimumVP :: V -> Property
-prop_tailVP :: V -> Property
-prop_foldl1VP :: (W -> W -> W) -> V -> Property
-prop_foldl1VP' :: (W -> W -> W) -> V -> Property
-prop_foldr1VP :: (W -> W -> W) -> V -> Property
-prop_scanlVP :: (W -> W -> W) -> W -> V -> Property
-prop_scanrVP :: (W -> W -> W) -> W -> V -> Property
-prop_eqVP :: V -> V -> Bool
-prop_foldlVP :: (X -> W -> X) -> X -> V -> Bool
-prop_foldlVP' :: (X -> W -> X) -> X -> V -> Bool
-prop_foldrVP :: (W -> X -> X) -> X -> V -> Bool
-prop_mapAccumLVP :: (X -> W -> (X, W)) -> X -> V -> Bool
-prop_mapAccumRVP :: (X -> W -> (X, W)) -> X -> V -> Bool
-prop_zipWithVP :: (W -> W -> W) -> V -> V -> Bool
-
-prop_concatVP       = V.concat  `eq1`  P.concat
-prop_nullVP         = V.null  `eq1`  P.null
-prop_reverseVP      = V.reverse  `eq1`  P.reverse
-prop_transposeVP    = V.transpose  `eq1`  P.transpose
-prop_groupVP        = V.group  `eq1`  P.group
-prop_initsVP        = V.inits  `eq1`  P.inits
-prop_tailsVP        = V.tails  `eq1`  P.tails
-prop_allVP          = V.all  `eq2`  P.all
-prop_anyVP          = V.any  `eq2`  P.any
-prop_appendVP       = V.append  `eq2`  P.append
-prop_breakVP        = V.break  `eq2`  P.break
-prop_concatMapVP    = V.concatMap  `eq2`  P.concatMap
-prop_consVP         = V.cons  `eq2`  P.cons
-prop_countVP        = V.count  `eq2`  P.count
-prop_dropVP         = V.drop  `eq2`  P.drop
-prop_dropWhileVP    = V.dropWhile  `eq2`  P.dropWhile
-prop_filterVP       = V.filter  `eq2`  P.filter
-prop_findVP         = V.find  `eq2`  P.find
-prop_findIndexVP    = V.findIndex  `eq2`  P.findIndex
-prop_findIndicesVP  = V.findIndices  `eq2`  P.findIndices
-prop_isPrefixOfVP   = V.isPrefixOf  `eq2`  P.isPrefixOf
-prop_mapVP          = V.map  `eq2`  P.map
-prop_replicateVP    = (\n -> V.replicate n  `eq1`  P.replicate n) . limit
-prop_iterateVP      = (\n f -> V.iterateN n f  `eq1`  P.pack . take n . iterate f) . limit
-prop_snocVP         = V.snoc  `eq2`  P.snoc
-prop_spanVP         = V.span  `eq2`  P.span
-prop_splitVP        = V.split  `eq2`  P.split
-prop_splitAtVP      = V.splitAt  `eq2`  P.splitAt
-prop_takeVP         = V.take  `eq2`  P.take
-prop_takeWhileVP    = V.takeWhile  `eq2`  P.takeWhile
-prop_elemVP         = V.elem  `eq2`  P.elem
-prop_notElemVP      = V.notElem  `eq2`  P.notElem
-prop_elemIndexVP    = V.elemIndex  `eq2`  P.elemIndex
-prop_elemIndicesVP  = V.elemIndices  `eq2`  P.elemIndices
-prop_lengthVP       = V.length  `eq1`  P.length
-
-prop_headVP         = V.head  `eqnotnull1`  P.head
-prop_initVP         = V.init  `eqnotnull1`  P.init
-prop_lastVP         = V.last  `eqnotnull1`  P.last
-prop_maximumVP      = V.maximum  `eqnotnull1`  P.maximum
-prop_minimumVP      = V.minimum  `eqnotnull1`  P.minimum
-prop_tailVP         = V.tail  `eqnotnull1`  P.tail
-prop_foldl1VP       = V.foldl1  `eqnotnull2`  P.foldl1
-prop_foldl1VP'      = V.foldl1'  `eqnotnull2`  P.foldl1'
-prop_foldr1VP       = V.foldr1  `eqnotnull2`  P.foldr1
-prop_scanlVP        = V.scanl  `eqnotnull3`  P.scanl
-prop_scanrVP        = V.scanr  `eqnotnull3`  P.scanr
-
-prop_sliceVerticalVP (Positive n) =
-   V.sliceVertical n  `eq1`  (ListHT.sliceVertical n :: [W] -> [[W]])
-
-prop_sieveVP (Positive n) =
-   V.sieve n  `eq1`  (ListHT.sieve n :: [W] -> [W])
-
-prop_deinterleaveVP (Positive n) =
-   V.deinterleave n  `eq1`  (ListHT.sliceHorizontal n :: [W] -> [[W]])
-
-prop_interleaveVP (Positive n) xs =
-   let xss = ListHT.switchR [] const $ V.sliceVertical n xs
-   in  V.interleave xss  ==  V.concat (V.transpose xss)
-
-prop_eqVP =
-   eq2
-      ((==) :: V -> V -> Bool)
-      ((==) :: P -> P -> Bool)
-prop_foldlVP f b as =
-   uncurry eq0
-      ((V.foldl, P.foldl) `applyId` f `applyId` b `applyModel` as)
-prop_foldlVP' f b as =
-   uncurry eq0
-      ((V.foldl', P.foldl') `applyId` f `applyId` b `applyModel` as)
-prop_foldrVP f b as =
-   uncurry eq0
-      ((V.foldr, P.foldr) `applyId` f `applyId` b `applyModel` as)
-prop_mapAccumLVP f b as =
-   uncurry eq0
-      ((V.mapAccumL, P.mapAccumL) `applyId` f `applyId` b `applyModel` as)
-prop_mapAccumRVP f b as =
-   uncurry eq0
-      ((V.mapAccumR, P.mapAccumR) `applyId` f `applyId` b `applyModel` as)
-prop_zipWithVP f xs ys =
-   uncurry eq0
-      ((V.zipWith f, \x y -> P.pack (P.zipWith f x y)) `applyModel` xs `applyModel` ys)
+module Main (main) where
 
-prop_unfoldrVP :: Int -> (X -> Maybe (W, X)) -> X -> Bool
-prop_unfoldrVP n0 f =
-    let n = limit n0
-    in  eq1
-           (fst . V.unfoldrN n f)
-           (fst . P.unfoldrN n f)
+import qualified Test.Lazy as Lazy
+import qualified Test.Strict as Strict
+import Text.Printf (printf)
 
 
-vp_tests :: [(String, IO ())]
-vp_tests =
-   ("all",         quickCheck prop_allVP) :
-   ("any",         quickCheck prop_anyVP) :
-   ("append",      quickCheck prop_appendVP) :
-   ("concat",      quickCheck prop_concatVP) :
-   ("cons",        quickCheck prop_consVP) :
-   ("eq",          quickCheck prop_eqVP) :
-   ("filter",      quickCheck prop_filterVP) :
-   ("find",        quickCheck prop_findVP) :
-   ("findIndex",   quickCheck prop_findIndexVP) :
-   ("findIndices", quickCheck prop_findIndicesVP) :
-   ("foldl",       quickCheck prop_foldlVP) :
-   ("foldl'",      quickCheck prop_foldlVP') :
-   ("foldl1",      quickCheck prop_foldl1VP) :
-   ("foldl1'",     quickCheck prop_foldl1VP') :
-   ("foldr",       quickCheck prop_foldrVP) :
-   ("foldr1",      quickCheck prop_foldr1VP) :
-   ("mapAccumL",   quickCheck prop_mapAccumLVP) :
-   ("mapAccumR",   quickCheck prop_mapAccumRVP) :
-   ("zipWith",     quickCheck prop_zipWithVP) :
-   ("unfoldr",     quickCheck prop_unfoldrVP) :
-   ("head",        quickCheck prop_headVP) :
-   ("init",        quickCheck prop_initVP) :
-   ("isPrefixOf",  quickCheck prop_isPrefixOfVP) :
-   ("last",        quickCheck prop_lastVP) :
-   ("length",      quickCheck prop_lengthVP) :
-   ("map",         quickCheck prop_mapVP) :
-   ("maximum",     quickCheck prop_maximumVP) :
-   ("minimum",     quickCheck prop_minimumVP) :
-   ("null",        quickCheck prop_nullVP) :
-   ("reverse",     quickCheck prop_reverseVP) :
-   ("snoc",        quickCheck prop_snocVP) :
-   ("tail",        quickCheck prop_tailVP) :
-   ("scanl",       quickCheck prop_scanlVP) :
-   ("scanr",       quickCheck prop_scanrVP) :
-   ("transpose",   quickCheck prop_transposeVP) :
-   ("replicate",   quickCheck prop_replicateVP) :
-   ("iterateN",    quickCheck prop_iterateVP) :
-   ("take",        quickCheck prop_takeVP) :
-   ("drop",        quickCheck prop_dropVP) :
-   ("splitAt",     quickCheck prop_splitAtVP) :
-   ("takeWhile",   quickCheck prop_takeWhileVP) :
-   ("dropWhile",   quickCheck prop_dropWhileVP) :
-   ("break",       quickCheck prop_breakVP) :
-   ("span",        quickCheck prop_spanVP) :
-   ("split",       quickCheck prop_splitVP) :
-   ("count",       quickCheck prop_countVP) :
-   ("group",       quickCheck prop_groupVP) :
-   ("inits",       quickCheck prop_initsVP) :
-   ("tails",       quickCheck prop_tailsVP) :
-   ("elem",        quickCheck prop_elemVP) :
-   ("notElem",     quickCheck prop_notElemVP) :
-   ("elemIndex",   quickCheck prop_elemIndexVP) :
-   ("elemIndices", quickCheck prop_elemIndicesVP) :
-   ("concatMap",   quickCheck prop_concatMapVP) :
-   ("sieve",       quickCheck prop_sieveVP) :
-   ("sliceVertical", quickCheck prop_sliceVerticalVP) :
-   ("deinterleave",  quickCheck prop_deinterleaveVP) :
-   ("interleave",  quickCheck prop_interleaveVP) :
-   []
-
+run :: String -> [(String, IO ())] -> IO ()
+run prefix tests =
+   mapM_ (\(s,a) -> printf "%-25s: " (prefix ++ "." ++ s) >> a) tests
 
 main :: IO ()
-main = run vp_tests
-
-run :: [(String, IO ())] -> IO ()
-run tests = do
-    mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests
+main = do
+   run "SV" Strict.vp_tests
+   run "SVL" Lazy.tests
diff --git a/tests/Test/Lazy.hs b/tests/Test/Lazy.hs
new file mode 100644
--- /dev/null
+++ b/tests/Test/Lazy.hs
@@ -0,0 +1,61 @@
+module Test.Lazy (tests) where
+
+import qualified Alternative.Lazy as AltLazy
+
+import qualified Data.StorableVector.Lazy as VL
+import qualified Data.StorableVector as V
+import qualified Data.List.HT as ListHT
+import qualified Data.List as List
+import qualified Data.Word as Word
+
+import Foreign.Storable (Storable)
+
+import Test.QuickCheck (quickCheck)
+
+
+type W = Word.Word16
+
+compactEqual :: VL.ChunkSize -> [V.Vector W] -> Bool
+compactEqual chunkSize chunks =
+   let xs = VL.fromChunks chunks
+   in  VL.unpack xs == VL.unpack (VL.compact chunkSize xs)
+
+fromChunksLimited ::
+   (Storable a) => VL.ChunkSize -> [V.Vector a] -> VL.Vector a
+fromChunksLimited (VL.ChunkSize size) =
+   VL.fromChunks . List.concatMap (V.sliceVertical size)
+
+compactLimit :: VL.ChunkSize -> [V.Vector W] -> Bool
+compactLimit chunkSize =
+   all ((<=chunkSize) . VL.chunkSize . V.length) .
+   VL.chunks . VL.compact chunkSize . fromChunksLimited chunkSize
+
+compactMax :: VL.ChunkSize -> [V.Vector W] -> Bool
+compactMax chunkSize =
+   all ((>chunkSize) . VL.chunkSize) .
+   ListHT.mapAdjacent (+) . map V.length .
+   VL.chunks . VL.compact chunkSize . fromChunksLimited chunkSize
+
+compactAlt :: VL.ChunkSize -> [V.Vector W] -> Bool
+compactAlt chunkSize@(VL.ChunkSize size) chunks =
+   let xs = fromChunksLimited chunkSize chunks
+   in  (map sum $ AltLazy.compact3 size $ map V.length $ VL.chunks xs)
+       ==
+       (map V.length $ VL.chunks $ VL.compact chunkSize xs)
+
+compactAltLens ::
+   (Int -> [Int] -> [[Int]]) -> VL.ChunkSize -> [V.Vector W] -> Bool
+compactAltLens compactLens chunkSize@(VL.ChunkSize size) chunks =
+   let lens = map V.length $ VL.chunks $ fromChunksLimited chunkSize chunks
+   in  AltLazy.compact3 size lens  ==  compactLens size lens
+
+
+tests :: [(String, IO ())]
+tests =
+   ("compactEqual", quickCheck compactEqual) :
+   ("compactLimit", quickCheck compactLimit) :
+   ("compactMax", quickCheck compactMax) :
+   ("compactAlt", quickCheck compactAlt) :
+   ("compactAlt2", quickCheck $ compactAltLens AltLazy.compact2) :
+   ("compactAlt4", quickCheck $ compactAltLens AltLazy.compact4) :
+   []
diff --git a/tests/Test/Strict.hs b/tests/Test/Strict.hs
new file mode 100644
--- /dev/null
+++ b/tests/Test/Strict.hs
@@ -0,0 +1,232 @@
+module Test.Strict where
+
+import qualified Data.StorableVector as V
+import qualified Data.ByteString as P
+import qualified Data.List.HT as ListHT
+
+import qualified Test.QuickCheck as QC
+import Test.QuickCheck.Modifiers (Positive(Positive), )
+import Test.QuickCheck (Property, quickCheck, )
+import Test.Utility
+          (V, W, X, P, applyId, applyModel,
+           eq0, eq1, eq2, eqnotnull1, eqnotnull2, eqnotnull3, )
+
+
+-- * compare Data.StorableVector <=> ByteString
+
+newtype Size = Size {getSize :: Int}
+   deriving (Show)
+
+instance QC.Arbitrary Size where
+   arbitrary = fmap Size $ QC.choose (0,10000)
+
+prop_concatVP :: [V] -> Bool
+prop_nullVP :: V -> Bool
+prop_reverseVP :: V -> Bool
+prop_transposeVP :: [V] -> Bool
+prop_groupVP :: V -> Bool
+prop_initsVP :: V -> Bool
+prop_tailsVP :: V -> Bool
+prop_allVP :: (W -> Bool) -> V -> Bool
+prop_anyVP :: (W -> Bool) -> V -> Bool
+prop_appendVP :: V -> V -> Bool
+prop_breakVP :: (W -> Bool) -> V -> Bool
+prop_concatMapVP :: (W -> V) -> V -> Bool
+prop_consVP :: W -> V -> Bool
+prop_countVP :: W -> V -> Bool
+prop_dropVP :: X -> V -> Bool
+prop_dropWhileVP :: (W -> Bool) -> V -> Bool
+prop_filterVP :: (W -> Bool) -> V -> Bool
+prop_findVP :: (W -> Bool) -> V -> Bool
+prop_findIndexVP :: (W -> Bool) -> V -> Bool
+prop_findIndicesVP :: (W -> Bool) -> V -> Bool
+prop_isPrefixOfVP :: V -> V -> Bool
+prop_mapVP :: (W -> W) -> V -> Bool
+prop_replicateVP :: Size -> W -> Bool
+prop_iterateVP :: Size -> (W -> W) -> W -> Bool
+prop_snocVP :: V -> W -> Bool
+prop_spanVP :: (W -> Bool) -> V -> Bool
+prop_splitVP :: W -> V -> Bool
+prop_splitAtVP :: X -> V -> Bool
+prop_sieveVP :: Positive X -> V -> Bool
+prop_sliceVerticalVP :: Positive X -> V -> Bool
+prop_deinterleaveVP :: Positive X -> V -> Bool
+prop_interleaveVP :: Positive X -> V -> Bool
+prop_takeVP :: X -> V -> Bool
+prop_takeWhileVP :: (W -> Bool) -> V -> Bool
+prop_elemVP :: W -> V -> Bool
+prop_notElemVP :: W -> V -> Bool
+prop_elemIndexVP :: W -> V -> Bool
+prop_elemIndicesVP :: W -> V -> Bool
+prop_lengthVP :: V -> Bool
+prop_headVP :: V -> Property
+prop_initVP :: V -> Property
+prop_lastVP :: V -> Property
+prop_maximumVP :: V -> Property
+prop_minimumVP :: V -> Property
+prop_tailVP :: V -> Property
+prop_foldl1VP :: (W -> W -> W) -> V -> Property
+prop_foldl1VP' :: (W -> W -> W) -> V -> Property
+prop_foldr1VP :: (W -> W -> W) -> V -> Property
+prop_scanlVP :: (W -> W -> W) -> W -> V -> Property
+prop_scanrVP :: (W -> W -> W) -> W -> V -> Property
+prop_eqVP :: V -> V -> Bool
+prop_foldlVP :: (X -> W -> X) -> X -> V -> Bool
+prop_foldlVP' :: (X -> W -> X) -> X -> V -> Bool
+prop_foldrVP :: (W -> X -> X) -> X -> V -> Bool
+prop_mapAccumLVP :: (X -> W -> (X, W)) -> X -> V -> Bool
+prop_mapAccumRVP :: (X -> W -> (X, W)) -> X -> V -> Bool
+prop_zipWithVP :: (W -> W -> W) -> V -> V -> Bool
+
+prop_concatVP       = V.concat  `eq1`  P.concat
+prop_nullVP         = V.null  `eq1`  P.null
+prop_reverseVP      = V.reverse  `eq1`  P.reverse
+prop_transposeVP    = V.transpose  `eq1`  P.transpose
+prop_groupVP        = V.group  `eq1`  P.group
+prop_initsVP        = V.inits  `eq1`  P.inits
+prop_tailsVP        = V.tails  `eq1`  P.tails
+prop_allVP          = V.all  `eq2`  P.all
+prop_anyVP          = V.any  `eq2`  P.any
+prop_appendVP       = V.append  `eq2`  P.append
+prop_breakVP        = V.break  `eq2`  P.break
+prop_concatMapVP    = V.concatMap  `eq2`  P.concatMap
+prop_consVP         = V.cons  `eq2`  P.cons
+prop_countVP        = V.count  `eq2`  P.count
+prop_dropVP         = V.drop  `eq2`  P.drop
+prop_dropWhileVP    = V.dropWhile  `eq2`  P.dropWhile
+prop_filterVP       = V.filter  `eq2`  P.filter
+prop_findVP         = V.find  `eq2`  P.find
+prop_findIndexVP    = V.findIndex  `eq2`  P.findIndex
+prop_findIndicesVP  = V.findIndices  `eq2`  P.findIndices
+prop_isPrefixOfVP   = V.isPrefixOf  `eq2`  P.isPrefixOf
+prop_mapVP          = V.map  `eq2`  P.map
+prop_replicateVP    = (\n -> V.replicate n  `eq1`  P.replicate n) . getSize
+prop_iterateVP      = (\n f -> V.iterateN n f  `eq1`  P.pack . take n . iterate f) . getSize
+prop_snocVP         = V.snoc  `eq2`  P.snoc
+prop_spanVP         = V.span  `eq2`  P.span
+prop_splitVP        = V.split  `eq2`  P.split
+prop_splitAtVP      = V.splitAt  `eq2`  P.splitAt
+prop_takeVP         = V.take  `eq2`  P.take
+prop_takeWhileVP    = V.takeWhile  `eq2`  P.takeWhile
+prop_elemVP         = V.elem  `eq2`  P.elem
+prop_notElemVP      = V.notElem  `eq2`  P.notElem
+prop_elemIndexVP    = V.elemIndex  `eq2`  P.elemIndex
+prop_elemIndicesVP  = V.elemIndices  `eq2`  P.elemIndices
+prop_lengthVP       = V.length  `eq1`  P.length
+
+prop_headVP         = V.head  `eqnotnull1`  P.head
+prop_initVP         = V.init  `eqnotnull1`  P.init
+prop_lastVP         = V.last  `eqnotnull1`  P.last
+prop_maximumVP      = V.maximum  `eqnotnull1`  P.maximum
+prop_minimumVP      = V.minimum  `eqnotnull1`  P.minimum
+prop_tailVP         = V.tail  `eqnotnull1`  P.tail
+prop_foldl1VP       = V.foldl1  `eqnotnull2`  P.foldl1
+prop_foldl1VP'      = V.foldl1'  `eqnotnull2`  P.foldl1'
+prop_foldr1VP       = V.foldr1  `eqnotnull2`  P.foldr1
+prop_scanlVP        = V.scanl  `eqnotnull3`  P.scanl
+prop_scanrVP        = V.scanr  `eqnotnull3`  P.scanr
+
+prop_sliceVerticalVP (Positive n) =
+   V.sliceVertical n  `eq1`  (ListHT.sliceVertical n :: [W] -> [[W]])
+
+prop_sieveVP (Positive n) =
+   V.sieve n  `eq1`  (ListHT.sieve n :: [W] -> [W])
+
+prop_deinterleaveVP (Positive n) =
+   V.deinterleave n  `eq1`  (ListHT.sliceHorizontal n :: [W] -> [[W]])
+
+prop_interleaveVP (Positive n) xs =
+   let xss = ListHT.switchR [] const $ V.sliceVertical n xs
+   in  V.interleave xss  ==  V.concat (V.transpose xss)
+
+prop_eqVP =
+   eq2
+      ((==) :: V -> V -> Bool)
+      ((==) :: P -> P -> Bool)
+prop_foldlVP f b as =
+   uncurry eq0
+      ((V.foldl, P.foldl) `applyId` f `applyId` b `applyModel` as)
+prop_foldlVP' f b as =
+   uncurry eq0
+      ((V.foldl', P.foldl') `applyId` f `applyId` b `applyModel` as)
+prop_foldrVP f b as =
+   uncurry eq0
+      ((V.foldr, P.foldr) `applyId` f `applyId` b `applyModel` as)
+prop_mapAccumLVP f b as =
+   uncurry eq0
+      ((V.mapAccumL, P.mapAccumL) `applyId` f `applyId` b `applyModel` as)
+prop_mapAccumRVP f b as =
+   uncurry eq0
+      ((V.mapAccumR, P.mapAccumR) `applyId` f `applyId` b `applyModel` as)
+prop_zipWithVP f xs ys =
+   uncurry eq0
+      ((V.zipWith f, \x y -> P.pack (P.zipWith f x y)) `applyModel` xs `applyModel` ys)
+
+prop_unfoldrVP :: Size -> (X -> Maybe (W, X)) -> X -> Bool
+prop_unfoldrVP n f =
+   eq1
+      (V.unfoldrN (getSize n) f)
+      (P.unfoldrN (getSize n) f)
+
+
+vp_tests :: [(String, IO ())]
+vp_tests =
+   ("all",         quickCheck prop_allVP) :
+   ("any",         quickCheck prop_anyVP) :
+   ("append",      quickCheck prop_appendVP) :
+   ("concat",      quickCheck prop_concatVP) :
+   ("cons",        quickCheck prop_consVP) :
+   ("eq",          quickCheck prop_eqVP) :
+   ("filter",      quickCheck prop_filterVP) :
+   ("find",        quickCheck prop_findVP) :
+   ("findIndex",   quickCheck prop_findIndexVP) :
+   ("findIndices", quickCheck prop_findIndicesVP) :
+   ("foldl",       quickCheck prop_foldlVP) :
+   ("foldl'",      quickCheck prop_foldlVP') :
+   ("foldl1",      quickCheck prop_foldl1VP) :
+   ("foldl1'",     quickCheck prop_foldl1VP') :
+   ("foldr",       quickCheck prop_foldrVP) :
+   ("foldr1",      quickCheck prop_foldr1VP) :
+   ("mapAccumL",   quickCheck prop_mapAccumLVP) :
+   ("mapAccumR",   quickCheck prop_mapAccumRVP) :
+   ("zipWith",     quickCheck prop_zipWithVP) :
+   ("unfoldr",     quickCheck prop_unfoldrVP) :
+   ("head",        quickCheck prop_headVP) :
+   ("init",        quickCheck prop_initVP) :
+   ("isPrefixOf",  quickCheck prop_isPrefixOfVP) :
+   ("last",        quickCheck prop_lastVP) :
+   ("length",      quickCheck prop_lengthVP) :
+   ("map",         quickCheck prop_mapVP) :
+   ("maximum",     quickCheck prop_maximumVP) :
+   ("minimum",     quickCheck prop_minimumVP) :
+   ("null",        quickCheck prop_nullVP) :
+   ("reverse",     quickCheck prop_reverseVP) :
+   ("snoc",        quickCheck prop_snocVP) :
+   ("tail",        quickCheck prop_tailVP) :
+   ("scanl",       quickCheck prop_scanlVP) :
+   ("scanr",       quickCheck prop_scanrVP) :
+   ("transpose",   quickCheck prop_transposeVP) :
+   ("replicate",   quickCheck prop_replicateVP) :
+   ("iterateN",    quickCheck prop_iterateVP) :
+   ("take",        quickCheck prop_takeVP) :
+   ("drop",        quickCheck prop_dropVP) :
+   ("splitAt",     quickCheck prop_splitAtVP) :
+   ("takeWhile",   quickCheck prop_takeWhileVP) :
+   ("dropWhile",   quickCheck prop_dropWhileVP) :
+   ("break",       quickCheck prop_breakVP) :
+   ("span",        quickCheck prop_spanVP) :
+   ("split",       quickCheck prop_splitVP) :
+   ("count",       quickCheck prop_countVP) :
+   ("group",       quickCheck prop_groupVP) :
+   ("inits",       quickCheck prop_initsVP) :
+   ("tails",       quickCheck prop_tailsVP) :
+   ("elem",        quickCheck prop_elemVP) :
+   ("notElem",     quickCheck prop_notElemVP) :
+   ("elemIndex",   quickCheck prop_elemIndexVP) :
+   ("elemIndices", quickCheck prop_elemIndicesVP) :
+   ("concatMap",   quickCheck prop_concatMapVP) :
+   ("sieve",       quickCheck prop_sieveVP) :
+   ("sliceVertical", quickCheck prop_sliceVerticalVP) :
+   ("deinterleave",  quickCheck prop_deinterleaveVP) :
+   ("interleave",  quickCheck prop_interleaveVP) :
+   []
