diff --git a/Data/Vector.hs b/Data/Vector.hs
--- a/Data/Vector.hs
+++ b/Data/Vector.hs
@@ -32,7 +32,7 @@
   length, null,
 
   -- ** Indexing
-  (!), head, last,
+  (!), (!?), head, last,
   unsafeIndex, unsafeHead, unsafeLast,
 
   -- ** Monadic indexing
@@ -58,7 +58,7 @@
   enumFromN, enumFromStepN, enumFromTo, enumFromThenTo,
 
   -- ** Concatenation
-  cons, snoc, (++),
+  cons, snoc, (++), concat,
 
   -- ** Restricting memory usage
   force,
@@ -136,8 +136,11 @@
   -- ** Lists
   toList, fromList, fromListN,
 
+  -- ** Other vector types
+  G.convert,
+
   -- ** Mutable vectors
-  copy, unsafeCopy
+  freeze, thaw, copy, unsafeFreeze, unsafeThaw, unsafeCopy
 ) where
 
 import qualified Data.Vector.Generic as G
@@ -150,7 +153,7 @@
 import Control.Monad.Primitive
 
 import Prelude hiding ( length, null,
-                        replicate, (++),
+                        replicate, (++), concat,
                         head, last,
                         init, tail, take, drop, reverse,
                         map, concatMap,
@@ -168,6 +171,8 @@
 import Data.Typeable ( Typeable )
 import Data.Data     ( Data(..) )
 
+import Data.Monoid   ( Monoid(..) )
+
 -- | Boxed vectors, supporting efficient slicing.
 data Vector a = Vector {-# UNPACK #-} !Int
                        {-# UNPACK #-} !Int
@@ -187,10 +192,14 @@
 type instance G.Mutable Vector = MVector
 
 instance G.Vector Vector a where
-  {-# INLINE unsafeFreeze #-}
-  unsafeFreeze (MVector i n marr)
+  {-# INLINE basicUnsafeFreeze #-}
+  basicUnsafeFreeze (MVector i n marr)
     = Vector i n `liftM` unsafeFreezeArray marr
 
+  {-# INLINE basicUnsafeThaw #-}
+  basicUnsafeThaw (Vector i n arr)
+    = MVector i n `liftM` unsafeThawArray arr
+
   {-# INLINE basicLength #-}
   basicLength (Vector _ n _) = n
 
@@ -225,6 +234,16 @@
   {-# INLINE (>=) #-}
   xs >= ys = Stream.cmp (G.stream xs) (G.stream ys) /= LT
 
+instance Monoid (Vector a) where
+  {-# INLINE mempty #-}
+  mempty = empty
+
+  {-# INLINE mappend #-}
+  mappend = (++)
+
+  {-# INLINE mconcat #-}
+  mconcat = concat
+
 -- Length information
 -- ------------------
 
@@ -246,6 +265,11 @@
 {-# INLINE (!) #-}
 (!) = (G.!)
 
+-- | O(1) Safe indexing
+(!?) :: Vector a -> Int -> Maybe a
+{-# INLINE (!?) #-}
+(!?) = (G.!?)
+
 -- | /O(1)/ First element
 head :: Vector a -> a
 {-# INLINE head #-}
@@ -496,6 +520,11 @@
 {-# INLINE (++) #-}
 (++) = (G.++)
 
+-- | /O(n)/ Concatenate all vectors in the list
+concat :: [Vector a] -> Vector a
+{-# INLINE concat #-}
+concat = G.concat
+
 -- Monadic initialisation
 -- ----------------------
 
@@ -689,7 +718,7 @@
 -- @
 modify :: (forall s. MVector s a -> ST s ()) -> Vector a -> Vector a
 {-# INLINE modify #-}
-modify = G.modify
+modify p = G.modify p
 
 -- Mapping
 -- -------
@@ -1278,14 +1307,36 @@
 -- Conversions - Mutable vectors
 -- -----------------------------
 
+-- | /O(1)/ Unsafe convert a mutable vector to an immutable one without
+-- copying. The mutable vector may not be used after this operation.
+unsafeFreeze :: PrimMonad m => MVector (PrimState m) a -> m (Vector a)
+{-# INLINE unsafeFreeze #-}
+unsafeFreeze = G.unsafeFreeze
+
+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one without
+-- copying. The immutable vector may not be used after this operation.
+unsafeThaw :: PrimMonad m => Vector a -> m (MVector (PrimState m) a)
+{-# INLINE unsafeThaw #-}
+unsafeThaw = G.unsafeThaw
+
+-- | /O(n)/ Yield a mutable copy of the immutable vector.
+thaw :: PrimMonad m => Vector a -> m (MVector (PrimState m) a)
+{-# INLINE thaw #-}
+thaw = G.thaw
+
+-- | /O(n)/ Yield an immutable copy of the mutable vector.
+freeze :: PrimMonad m => MVector (PrimState m) a -> m (Vector a)
+{-# INLINE freeze #-}
+freeze = G.freeze
+
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
--- have the same length.
+-- have the same length. This is not checked.
 unsafeCopy :: PrimMonad m => MVector (PrimState m) a -> Vector a -> m ()
 {-# INLINE unsafeCopy #-}
 unsafeCopy = G.unsafeCopy
            
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
--- have the same length. This is not checked.
+-- have the same length.
 copy :: PrimMonad m => MVector (PrimState m) a -> Vector a -> m ()
 {-# INLINE copy #-}
 copy = G.copy
diff --git a/Data/Vector/Fusion/Stream.hs b/Data/Vector/Fusion/Stream.hs
--- a/Data/Vector/Fusion/Stream.hs
+++ b/Data/Vector/Fusion/Stream.hs
@@ -35,7 +35,7 @@
   slice, init, tail, take, drop,
 
   -- * Mapping
-  map, concatMap, unbox,
+  map, concatMap, flatten, unbox,
   
   -- * Zipping
   indexed, indexedR,
@@ -613,4 +613,8 @@
 {-# INLINE unsafeFromList #-}
 unsafeFromList = M.unsafeFromList
 
+-- | Create a 'Stream' of values from a 'Stream' of streamable things
+flatten :: (a -> s) -> (s -> Step s b) -> Size -> Stream a -> Stream b
+{-# INLINE_STREAM flatten #-}
+flatten mk istep sz = M.flatten (return . mk) (return . istep) sz . liftStream
 
diff --git a/Data/Vector/Fusion/Stream/Monadic.hs b/Data/Vector/Fusion/Stream/Monadic.hs
--- a/Data/Vector/Fusion/Stream/Monadic.hs
+++ b/Data/Vector/Fusion/Stream/Monadic.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE ExistentialQuantification, Rank2Types #-}
+{-# LANGUAGE ExistentialQuantification, Rank2Types, BangPatterns #-}
 
 -- |
 -- Module      : Data.Vector.Fusion.Stream.Monadic
@@ -31,7 +31,7 @@
   slice, init, tail, take, drop,
 
   -- * Mapping
-  map, mapM, mapM_, trans, unbox, concatMap,
+  map, mapM, mapM_, trans, unbox, concatMap, flatten,
   
   -- * Zipping
   indexed, indexedR, zipWithM_,
@@ -223,7 +223,7 @@
 {-# INLINE_STREAM head #-}
 head (Stream step s _) = head_loop SPEC s
   where
-    head_loop SPEC s
+    head_loop !sPEC s
       = do
           r <- step s
           case r of
@@ -238,7 +238,7 @@
 {-# INLINE_STREAM last #-}
 last (Stream step s _) = last_loop0 SPEC s
   where
-    last_loop0 SPEC s
+    last_loop0 !sPEC s
       = do
           r <- step s
           case r of
@@ -246,7 +246,7 @@
             Skip    s' -> last_loop0 SPEC   s'
             Done       -> BOUNDS_ERROR(emptyStream) "last"
 
-    last_loop1 SPEC x s
+    last_loop1 !sPEC x s
       = do
           r <- step s
           case r of
@@ -260,7 +260,7 @@
 Stream step s _ !! i | i < 0     = BOUNDS_ERROR(error) "!!" "negative index"
                      | otherwise = index_loop SPEC s i
   where
-    index_loop SPEC s i
+    index_loop !sPEC s i
       = i `seq`
         do
           r <- step s
@@ -387,7 +387,7 @@
 {-# INLINE_STREAM consume #-}
 consume (Stream step s _) = consume_loop SPEC s
   where
-    consume_loop SPEC s
+    consume_loop !sPEC s
       = do
           r <- step s
           case r of
@@ -677,7 +677,7 @@
 {-# INLINE_STREAM elem #-}
 elem x (Stream step s _) = elem_loop SPEC s
   where
-    elem_loop SPEC s
+    elem_loop !sPEC s
       = do
           r <- step s
           case r of
@@ -704,7 +704,7 @@
 {-# INLINE_STREAM findM #-}
 findM f (Stream step s _) = find_loop SPEC s
   where
-    find_loop SPEC s
+    find_loop !sPEC s
       = do
           r <- step s
           case r of
@@ -727,7 +727,7 @@
 {-# INLINE_STREAM findIndexM #-}
 findIndexM f (Stream step s _) = findIndex_loop SPEC s 0
   where
-    findIndex_loop SPEC s i
+    findIndex_loop !sPEC s i
       = do
           r <- step s
           case r of
@@ -751,7 +751,7 @@
 {-# INLINE_STREAM foldlM #-}
 foldlM m z (Stream step s _) = foldlM_loop SPEC z s
   where
-    foldlM_loop SPEC z s
+    foldlM_loop !sPEC z s
       = do
           r <- step s
           case r of
@@ -774,7 +774,7 @@
 {-# INLINE_STREAM foldl1M #-}
 foldl1M f (Stream step s sz) = foldl1M_loop SPEC s
   where
-    foldl1M_loop SPEC s
+    foldl1M_loop !sPEC s
       = do
           r <- step s
           case r of
@@ -797,7 +797,7 @@
 {-# INLINE_STREAM foldlM' #-}
 foldlM' m z (Stream step s _) = foldlM'_loop SPEC z s
   where
-    foldlM'_loop SPEC z s
+    foldlM'_loop !sPEC z s
       = z `seq`
         do
           r <- step s
@@ -822,7 +822,7 @@
 {-# INLINE_STREAM foldl1M' #-}
 foldl1M' f (Stream step s sz) = foldl1M'_loop SPEC s
   where
-    foldl1M'_loop SPEC s
+    foldl1M'_loop !sPEC s
       = do
           r <- step s
           case r of
@@ -845,7 +845,7 @@
 {-# INLINE_STREAM foldrM #-}
 foldrM f z (Stream step s _) = foldrM_loop SPEC s
   where
-    foldrM_loop SPEC s
+    foldrM_loop !sPEC s
       = do
           r <- step s
           case r of
@@ -863,7 +863,7 @@
 {-# INLINE_STREAM foldr1M #-}
 foldr1M f (Stream step s _) = foldr1M_loop0 SPEC s
   where
-    foldr1M_loop0 SPEC s
+    foldr1M_loop0 !sPEC s
       = do
           r <- step s
           case r of
@@ -871,7 +871,7 @@
             Skip    s' -> foldr1M_loop0 SPEC   s'
             Done       -> BOUNDS_ERROR(emptyStream) "foldr1M"
 
-    foldr1M_loop1 SPEC x s
+    foldr1M_loop1 !sPEC x s
       = do
           r <- step s
           case r of
@@ -886,7 +886,7 @@
 {-# INLINE_STREAM and #-}
 and (Stream step s _) = and_loop SPEC s
   where
-    and_loop SPEC s
+    and_loop !sPEC s
       = do
           r <- step s
           case r of
@@ -899,7 +899,7 @@
 {-# INLINE_STREAM or #-}
 or (Stream step s _) = or_loop SPEC s
   where
-    or_loop SPEC s
+    or_loop !sPEC s
       = do
           r <- step s
           case r of
@@ -931,6 +931,30 @@
             Skip    inner_s' -> return $ Skip (Right (Stream inner_step inner_s' sz, s))
             Done             -> return $ Skip (Left s)
 
+-- | Create a 'Stream' of values from a 'Stream' of streamable things
+flatten :: Monad m => (a -> m s) -> (s -> m (Step s b)) -> Size
+                   -> Stream m a -> Stream m b
+{-# INLINE_STREAM flatten #-}
+flatten mk istep sz (Stream ostep t _) = Stream step (Left t) sz
+  where
+    {-# INLINE_INNER step #-}
+    step (Left t) = do
+                      r <- ostep t
+                      case r of
+                        Yield a t' -> do
+                                        s <- mk a
+                                        return $ Skip (Right (s,t'))
+                        Skip    t' -> return $ Skip (Left t')
+                        Done       -> return $ Done
+
+    
+    step (Right (s,t)) = do
+                           r <- istep s
+                           case r of
+                             Yield x s' -> return $ Yield x (Right (s',t))
+                             Skip    s' -> return $ Skip    (Right (s',t))
+                             Done       -> return $ Skip    (Left t)
+
 -- Unfolding
 -- ---------
 
@@ -1141,7 +1165,8 @@
 -- @x+y+y@ etc.
 enumFromStepN :: (Num a, Monad m) => a -> a -> Int -> Stream m a
 {-# INLINE_STREAM enumFromStepN #-}
-enumFromStepN x y n = n `seq` Stream step (x,n) (Exact (delay_inline max n 0))
+enumFromStepN x y n = x `seq` y `seq` n `seq`
+                      Stream step (x,n) (Exact (delay_inline max n 0))
   where
     {-# INLINE_INNER step #-}
     step (x,n) | n > 0     = return $ Yield x (x+y,n-1)
@@ -1161,7 +1186,7 @@
 -- FIXME: add "too large" test for Int
 enumFromTo_small :: (Integral a, Monad m) => a -> a -> Stream m a
 {-# INLINE_STREAM enumFromTo_small #-}
-enumFromTo_small x y = Stream step x (Exact n)
+enumFromTo_small x y = x `seq` y `seq` Stream step x (Exact n)
   where
     n = delay_inline max (fromIntegral y - fromIntegral x + 1) 0
 
@@ -1213,7 +1238,7 @@
 
 enumFromTo_int :: (Integral a, Monad m) => a -> a -> Stream m a
 {-# INLINE_STREAM enumFromTo_int #-}
-enumFromTo_int x y = Stream step x (Exact (len x y))
+enumFromTo_int x y = x `seq` y `seq` Stream step x (Exact (len x y))
   where
     {-# INLINE [0] len #-}
     len x y | x > y     = 0
@@ -1248,7 +1273,7 @@
 
 enumFromTo_big_word :: (Integral a, Monad m) => a -> a -> Stream m a
 {-# INLINE_STREAM enumFromTo_big_word #-}
-enumFromTo_big_word x y = Stream step x (Exact (len x y))
+enumFromTo_big_word x y = x `seq` y `seq` Stream step x (Exact (len x y))
   where
     {-# INLINE [0] len #-}
     len x y | x > y     = 0
@@ -1288,7 +1313,7 @@
 -- FIXME: the "too large" test is totally wrong
 enumFromTo_big_int :: (Integral a, Monad m) => a -> a -> Stream m a
 {-# INLINE_STREAM enumFromTo_big_int #-}
-enumFromTo_big_int x y = Stream step x (Exact (len x y))
+enumFromTo_big_int x y = x `seq` y `seq` Stream step x (Exact (len x y))
   where
     {-# INLINE [0] len #-}
     len x y | x > y     = 0
@@ -1315,7 +1340,7 @@
 
 enumFromTo_char :: Monad m => Char -> Char -> Stream m Char
 {-# INLINE_STREAM enumFromTo_char #-}
-enumFromTo_char x y = Stream step xn (Exact n)
+enumFromTo_char x y = x `seq` y `seq` Stream step xn (Exact n)
   where
     xn = ord x
     yn = ord y
@@ -1340,7 +1365,7 @@
 
 enumFromTo_double :: (Monad m, Ord a, RealFrac a) => a -> a -> Stream m a
 {-# INLINE_STREAM enumFromTo_double #-}
-enumFromTo_double n m = Stream step n (Max (len n m))
+enumFromTo_double n m = n `seq` m `seq` Stream step n (Max (len n m))
   where
     lim = m + 1/2 -- important to float out
 
diff --git a/Data/Vector/Generic.hs b/Data/Vector/Generic.hs
--- a/Data/Vector/Generic.hs
+++ b/Data/Vector/Generic.hs
@@ -22,7 +22,7 @@
   length, null,
 
   -- ** Indexing
-  (!), head, last,
+  (!), (!?), head, last,
   unsafeIndex, unsafeHead, unsafeLast,
 
   -- ** Monadic indexing
@@ -48,7 +48,7 @@
   enumFromN, enumFromStepN, enumFromTo, enumFromThenTo,
 
   -- ** Concatenation
-  cons, snoc, (++),
+  cons, snoc, (++), concat,
 
   -- ** Restricting memory usage
   force,
@@ -126,8 +126,11 @@
   -- ** Lists
   toList, fromList, fromListN,
 
+  -- ** Different vector types
+  convert,
+
   -- ** Mutable vectors
-  copy, unsafeCopy,
+  freeze, thaw, copy, unsafeFreeze, unsafeThaw, unsafeCopy,
 
   -- * Fusion support
 
@@ -155,7 +158,7 @@
 import           Data.Vector.Generic.New ( New )
 
 import qualified Data.Vector.Fusion.Stream as Stream
-import           Data.Vector.Fusion.Stream ( Stream, MStream, inplace )
+import           Data.Vector.Fusion.Stream ( Stream, MStream, inplace, liftStream )
 import qualified Data.Vector.Fusion.Stream.Monadic as MStream
 import           Data.Vector.Fusion.Stream.Size
 import           Data.Vector.Fusion.Util
@@ -163,11 +166,12 @@
 import Control.Monad.ST ( ST, runST )
 import Control.Monad.Primitive
 import qualified Control.Monad as Monad
+import qualified Data.List as List
 import Prelude hiding ( length, null,
-                        replicate, (++),
+                        replicate, (++), concat,
                         head, last,
                         init, tail, take, drop, reverse,
-                        map, concatMap,
+                        map, concat, concatMap,
                         zipWith, zipWith3, zip, zip3, unzip, unzip3,
                         filter, takeWhile, dropWhile, span, break,
                         elem, notElem,
@@ -218,6 +222,12 @@
 v ! i = BOUNDS_CHECK(checkIndex) "(!)" i (length v)
       $ unId (basicUnsafeIndexM v i)
 
+-- | O(1) Safe indexing
+(!?) :: Vector v a => v a -> Int -> Maybe a
+{-# INLINE_STREAM (!?) #-}
+v !? i | i < 0 || i >= length v = Nothing
+       | otherwise              = Just $ unsafeIndex v i
+
 -- | /O(1)/ First element
 head :: Vector v a => v a -> a
 {-# INLINE_STREAM head #-}
@@ -324,20 +334,28 @@
 {-# INLINE_STREAM unsafeLastM #-}
 unsafeLastM v = unsafeIndexM v (length v - 1)
 
--- FIXME: the rhs of these rules are lazy in the stream which is WRONG
-{- RULES
+{-# RULES
 
-"indexM/unstream [Vector]" forall v i s.
-  indexM (new' v (New.unstream s)) i = return (s Stream.!! i)
+"indexM/unstream [Vector]" forall s i.
+  indexM (new (New.unstream s)) i = liftStream s MStream.!! i
 
-"headM/unstream [Vector]" forall v s.
-  headM (new' v (New.unstream s)) = return (Stream.head s)
+"headM/unstream [Vector]" forall s.
+  headM (new (New.unstream s)) = MStream.head (liftStream s)
 
-"lastM/unstream [Vector]" forall v s.
-  lastM (new' v (New.unstream s)) = return (Stream.last s)
+"lastM/unstream [Vector]" forall s.
+  lastM (new (New.unstream s)) = MStream.last (liftStream s)
 
- -}
+"unsafeIndexM/unstream [Vector]" forall s i.
+  unsafeIndexM (new (New.unstream s)) i = liftStream s MStream.!! i
 
+"unsafeHeadM/unstream [Vector]" forall s.
+  unsafeHeadM (new (New.unstream s)) = MStream.head (liftStream s)
+
+"unsafeLastM/unstream [Vector]" forall s.
+  unsafeLastM (new (New.unstream s)) = MStream.last (liftStream s)
+
+  #-}
+
 -- Extracting subvectors (slicing)
 -- -------------------------------
 
@@ -490,6 +508,28 @@
 {-# INLINE unfoldrN #-}
 unfoldrN n f = unstream . Stream.unfoldrN n f
 
+{-
+construct :: Vector v a => Int -> (v a -> a) -> v a
+{-# INLINE construct #-}
+construct n f = runST (
+  do
+    v  <- M.new n
+    v' <- unsafeFreeze v
+    fill v' 0
+  )
+  where
+    fill v i | i < n = let x = f (unsafeTake i v)
+                       in
+                       elemseq v x $
+                       do
+                         v'  <- unsafeThaw v
+                         M.unsafeWrite v' i x
+                         v'' <- unsafeFreeze v'
+                         fill v'' (i-1)
+
+    fill v i = return v
+-}
+
 -- Enumeration
 -- -----------
 
@@ -552,6 +592,25 @@
 {-# INLINE (++) #-}
 v ++ w = unstream (stream v Stream.++ stream w)
 
+-- | /O(n)/ Concatenate all vectors in the list
+concat :: Vector v a => [v a] -> v a
+{-# INLINE concat #-}
+-- concat vs = create (thawMany vs)
+concat vs = unstream (Stream.flatten mk step (Exact n) (Stream.fromList vs))
+  where
+    n = List.foldl' (\k v -> k + length v) 0 vs
+
+    {-# INLINE_INNER step #-}
+    step (v,i,k)
+      | i < k = case unsafeIndexM v i of
+                  Box x -> Stream.Yield x (v,i+1,k)
+      | otherwise = Stream.Done
+
+    {-# INLINE mk #-}
+    mk v = let k = length v
+           in
+           k `seq` (v,0,k)
+
 -- Monadic initialisation
 -- ----------------------
 
@@ -761,20 +820,38 @@
 -- does not retain references to the original one even if it is lazy in its
 -- elements. This would not be the case if we simply used map (v!)
 backpermute v is = seq v
+                 $ seq n
                  $ unstream
                  $ Stream.unbox
-                 $ Stream.map (indexM v)
+                 $ Stream.map index
                  $ stream is
+  where
+    n = length v
 
+    {-# INLINE index #-}
+    -- NOTE: we do it this way to avoid triggering LiberateCase on n in
+    -- polymorphic code
+    index i = BOUNDS_CHECK(checkIndex) "backpermute" i n
+            $ basicUnsafeIndexM v i
+
 -- | Same as 'backpermute' but without bounds checking.
 unsafeBackpermute :: (Vector v a, Vector v Int) => v a -> v Int -> v a
 {-# INLINE unsafeBackpermute #-}
 unsafeBackpermute v is = seq v
+                       $ seq n
                        $ unstream
                        $ Stream.unbox
-                       $ Stream.map (unsafeIndexM v)
+                       $ Stream.map index
                        $ stream is
+  where
+    n = length v
 
+    {-# INLINE index #-}
+    -- NOTE: we do it this way to avoid triggering LiberateCase on n in
+    -- polymorphic code
+    index i = UNSAFE_CHECK(checkIndex) "unsafeBackpermute" i n
+            $ basicUnsafeIndexM v i
+
 -- Safe destructive updates
 -- ------------------------
 
@@ -814,7 +891,9 @@
 -- | Map a function over a vector and concatenate the results.
 concatMap :: (Vector v a, Vector v b) => (a -> v b) -> v a -> v b
 {-# INLINE concatMap #-}
-concatMap f = unstream . Stream.concatMap (stream . f) . stream
+-- NOTE: We can't fuse concatMap anyway so don't pretend we do.
+-- concatMap f = unstream . Stream.concatMap (stream . f) . stream
+concatMap f = concat . Stream.toList . Stream.map f . stream
 
 -- Monadic mapping
 -- ---------------
@@ -1522,9 +1601,67 @@
 {-# INLINE fromListN #-}
 fromListN n = unstream . Stream.fromListN n
 
+-- Conversions - Immutable vectors
+-- -------------------------------
+
+-- | /O(n)/ Convert different vector types
+convert :: (Vector v a, Vector w a) => v a -> w a
+{-# INLINE convert #-}
+convert = unstream . stream
+
 -- Conversions - Mutable vectors
 -- -----------------------------
 
+-- | /O(1)/ Unsafe convert a mutable vector to an immutable one without
+-- copying. The mutable vector may not be used after this operation.
+unsafeFreeze
+  :: (PrimMonad m, Vector v a) => Mutable v (PrimState m) a -> m (v a)
+{-# INLINE unsafeFreeze #-}
+unsafeFreeze = basicUnsafeFreeze
+
+
+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one without
+-- copying. The immutable vector may not be used after this operation.
+unsafeThaw :: (PrimMonad m, Vector v a) => v a -> m (Mutable v (PrimState m) a)
+{-# INLINE unsafeThaw #-}
+unsafeThaw = basicUnsafeThaw
+
+-- | /O(n)/ Yield a mutable copy of the immutable vector.
+thaw :: (PrimMonad m, Vector v a) => v a -> m (Mutable v (PrimState m) a)
+{-# INLINE_STREAM thaw #-}
+thaw v = do
+           mv <- M.unsafeNew (length v)
+           unsafeCopy mv v
+           return mv
+
+-- | /O(n)/ Yield an immutable copy of the mutable vector.
+freeze :: (PrimMonad m, Vector v a) => Mutable v (PrimState m) a -> m (v a)
+{-# INLINE freeze #-}
+freeze mv = unsafeFreeze =<< M.clone mv
+
+{-
+-- | /O(n)/ Yield a mutable vector containing copies of each vector in the
+-- list.
+thawMany :: (PrimMonad m, Vector v a) => [v a] -> m (Mutable v (PrimState m) a)
+{-# INLINE_STREAM thawMany #-}
+-- FIXME: add rule for (stream (new (New.create (thawMany vs))))
+-- NOTE: We don't try to consume the list lazily as this wouldn't significantly
+-- change the space requirements anyway.
+thawMany vs = do
+                mv <- M.new n
+                thaw_loop mv vs
+                return mv
+  where
+    n = List.foldl' (\k v -> k + length v) 0 vs
+
+    thaw_loop mv [] = mv `seq` return ()
+    thaw_loop mv (v:vs)
+      = do
+          let n = length v
+          unsafeCopy (M.unsafeTake n mv) v
+          thaw_loop (M.unsafeDrop n mv) vs
+-}
+
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
 -- have the same length.
 copy
@@ -1549,7 +1686,7 @@
 -- | /O(1)/ Convert a vector to a 'Stream'
 stream :: Vector v a => v a -> Stream a
 {-# INLINE_STREAM stream #-}
-stream v = v `seq` (Stream.unfoldr get 0 `Stream.sized` Exact n)
+stream v = v `seq` n `seq` (Stream.unfoldr get 0 `Stream.sized` Exact n)
   where
     n = length v
 
@@ -1588,7 +1725,7 @@
 -- | /O(1)/ Convert a vector to a 'Stream', proceeding from right to left
 streamR :: Vector v a => v a -> Stream a
 {-# INLINE_STREAM streamR #-}
-streamR v = v `seq` (Stream.unfoldr get n `Stream.sized` Exact n)
+streamR v = v `seq` n `seq` (Stream.unfoldr get n `Stream.sized` Exact n)
   where
     n = length v
 
diff --git a/Data/Vector/Generic/Base.hs b/Data/Vector/Generic/Base.hs
--- a/Data/Vector/Generic/Base.hs
+++ b/Data/Vector/Generic/Base.hs
@@ -1,5 +1,5 @@
 {-# LANGUAGE Rank2Types, MultiParamTypeClasses, FlexibleContexts,
-             TypeFamilies, ScopedTypeVariables #-}
+             TypeFamilies, ScopedTypeVariables, BangPatterns #-}
 {-# OPTIONS_HADDOCK hide #-}
 
 -- |
@@ -35,8 +35,10 @@
 --
 -- Minimum complete implementation:
 --
---   * 'unsafeFreeze'
+--   * 'basicUnsafeFreeze'
 --
+--   * 'basicUnsafeThaw'
+--
 --   * 'basicLength'
 --
 --   * 'basicUnsafeSlice'
@@ -44,15 +46,21 @@
 --   * 'basicUnsafeIndexM'
 --
 class MVector (Mutable v) a => Vector v a where
-  -- | /Assume complexity: O(1)/
+  -- | /Assumed complexity: O(1)/
   --
   -- Unsafely convert a mutable vector to its immutable version
   -- without copying. The mutable vector may not be used after
   -- this operation.
-  unsafeFreeze :: PrimMonad m => Mutable v (PrimState m) a -> m (v a)
+  basicUnsafeFreeze :: PrimMonad m => Mutable v (PrimState m) a -> m (v a)
 
   -- | /Assumed complexity: O(1)/
   --
+  -- Unsafely convert an immutable vector to its mutable version without
+  -- copying. The immutable vector may not be used after this operation.
+  basicUnsafeThaw :: PrimMonad m => v a -> m (Mutable v (PrimState m) a)
+
+  -- | /Assumed complexity: O(1)/
+  --
   -- Yield the length of the vector.
   basicLength      :: v a -> Int
 
@@ -104,9 +112,9 @@
   basicUnsafeCopy :: PrimMonad m => Mutable v (PrimState m) a -> v a -> m ()
 
   {-# INLINE basicUnsafeCopy #-}
-  basicUnsafeCopy dst src = do_copy 0
+  basicUnsafeCopy !dst !src = do_copy 0
     where
-      n = basicLength src
+      !n = basicLength src
 
       do_copy i | i < n = do
                             x <- basicUnsafeIndexM src i
diff --git a/Data/Vector/Generic/Mutable.hs b/Data/Vector/Generic/Mutable.hs
--- a/Data/Vector/Generic/Mutable.hs
+++ b/Data/Vector/Generic/Mutable.hs
@@ -15,33 +15,59 @@
   -- * Class of mutable vector types
   MVector(..),
 
-  -- * Operations on mutable vectors
-  length, overlaps, new, newWith, read, write, swap, clear, set, copy, grow,
+  -- * Accessors
 
-  slice, take, drop, init, tail,
-  unsafeSlice, unsafeInit, unsafeTail,
+  -- ** Length information
+  length, null,
 
-  -- * Unsafe operations
-  unsafeNew, unsafeNewWith, unsafeRead, unsafeWrite, unsafeSwap,
-  unsafeCopy, unsafeGrow,
+  -- ** Extracting subvectors
+  slice, init, tail, take, drop,
+  unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
 
+  -- ** Overlapping
+  overlaps,
+
+  -- * Construction
+
+  -- ** Initialisation
+  new, unsafeNew, replicate, clone,
+
+  -- ** Growing
+  grow, unsafeGrow,
+
+  -- ** Restricting memory usage
+  clear,
+
+  -- * Accessing individual elements
+  read, write, swap,
+  unsafeRead, unsafeWrite, unsafeSwap,
+
+  -- * Modifying vectors
+
+  -- ** Filling and copying
+  set, copy, unsafeCopy,
+
   -- * Internal operations
   unstream, unstreamR,
   munstream, munstreamR,
   transform, transformR,
   fill, fillR,
   unsafeAccum, accum, unsafeUpdate, update, reverse,
-  unstablePartition, unstablePartitionStream, partitionStream
+  unstablePartition, unstablePartitionStream, partitionStream,
+
+  -- * Deprecated operations
+  newWith, unsafeNewWith
 ) where
 
 import qualified Data.Vector.Fusion.Stream      as Stream
 import           Data.Vector.Fusion.Stream      ( Stream, MStream )
 import qualified Data.Vector.Fusion.Stream.Monadic as MStream
 import           Data.Vector.Fusion.Stream.Size
+import           Data.Vector.Fusion.Util        ( delay_inline )
 
 import Control.Monad.Primitive ( PrimMonad, PrimState )
 
-import Prelude hiding ( length, reverse, map, read,
+import Prelude hiding ( length, null, replicate, reverse, map, read,
                         take, drop, init, tail )
 
 #include "vector.h"
@@ -70,8 +96,8 @@
 
   -- | Create a mutable vector of the given length and fill it with an
   -- initial value. This method should not be called directly, use
-  -- 'unsafeNewWith' instead.
-  basicUnsafeNewWith :: PrimMonad m => Int -> a -> m (v (PrimState m) a)
+  -- 'replicate' instead.
+  basicUnsafeReplicate :: PrimMonad m => Int -> a -> m (v (PrimState m) a)
 
   -- | Yield the element at the given position. This method should not be
   -- called directly, use 'unsafeRead' instead.
@@ -101,6 +127,12 @@
   basicUnsafeGrow  :: PrimMonad m => v (PrimState m) a -> Int
                                                        -> m (v (PrimState m) a)
 
+  -- | /DEPRECATED/ in favour of 'basicUnsafeReplicate'
+  basicUnsafeNewWith :: PrimMonad m => Int -> a -> m (v (PrimState m) a)
+
+  {-# INLINE basicUnsafeReplicate #-}
+  basicUnsafeReplicate = basicUnsafeNewWith
+
   {-# INLINE basicUnsafeNewWith #-}
   basicUnsafeNewWith n x
     = do
@@ -112,9 +144,9 @@
   basicClear _ = return ()
 
   {-# INLINE basicSet #-}
-  basicSet v x = do_set 0
+  basicSet !v x = do_set 0
     where
-      n = basicLength v
+      !n = basicLength v
 
       do_set i | i < n = do
                            basicUnsafeWrite v i x
@@ -122,9 +154,9 @@
                 | otherwise = return ()
 
   {-# INLINE basicUnsafeCopy #-}
-  basicUnsafeCopy dst src = do_copy 0
+  basicUnsafeCopy !dst !src = do_copy 0
     where
-      n = basicLength src
+      !n = basicLength src
 
       do_copy i | i < n = do
                             x <- basicUnsafeRead src i
@@ -141,15 +173,12 @@
     where
       n = basicLength v
 
+{-# DEPRECATED basicUnsafeNewWith "define and use basicUnsafeReplicate instead" #-}
+
 -- ------------------
 -- Internal functions
 -- ------------------
 
--- Check whether two vectors overlap.
-overlaps :: MVector v a => v s a -> v s a -> Bool
-{-# INLINE overlaps #-}
-overlaps = basicOverlaps
-
 unsafeAppend1 :: (PrimMonad m, MVector v a)
         => v (PrimState m) a -> Int -> a -> m (v (PrimState m) a)
 {-# INLINE_INNER unsafeAppend1 #-}
@@ -184,7 +213,7 @@
 
 mstream :: (PrimMonad m, MVector v a) => v (PrimState m) a -> MStream m a
 {-# INLINE mstream #-}
-mstream v = v `seq` (MStream.unfoldrM get 0 `MStream.sized` Exact n)
+mstream v = v `seq` n `seq` (MStream.unfoldrM get 0 `MStream.sized` Exact n)
   where
     n = length v
 
@@ -213,7 +242,7 @@
 
 mstreamR :: (PrimMonad m, MVector v a) => v (PrimState m) a -> MStream m a
 {-# INLINE mstreamR #-}
-mstreamR v = v `seq` (MStream.unfoldrM get n `MStream.sized` Exact n)
+mstreamR v = v `seq` n `seq` (MStream.unfoldrM get n `MStream.sized` Exact n)
   where
     n = length v
 
@@ -362,36 +391,96 @@
 {-# INLINE null #-}
 null v = length v == 0
 
+-- Extracting subvectors
+-- ---------------------
 
--- Construction
--- ------------
+-- | Yield a part of the mutable vector without copying it.
+slice :: MVector v a => Int -> Int -> v s a -> v s a
+{-# INLINE slice #-}
+slice i n v = BOUNDS_CHECK(checkSlice) "slice" i n (length v)
+            $ unsafeSlice i n v
 
+take :: MVector v a => Int -> v s a -> v s a
+{-# INLINE take #-}
+take n v = unsafeSlice 0 (min (max n 0) (length v)) v
+
+drop :: MVector v a => Int -> v s a -> v s a
+{-# INLINE drop #-}
+drop n v = unsafeSlice (min m n') (max 0 (m - n')) v
+  where
+    n' = max n 0
+    m  = length v
+
+init :: MVector v a => v s a -> v s a
+{-# INLINE init #-}
+init v = slice 0 (length v - 1) v
+
+tail :: MVector v a => v s a -> v s a
+{-# INLINE tail #-}
+tail v = slice 1 (length v - 1) v
+
+-- | Yield a part of the mutable vector without copying it. No bounds checks
+-- are performed.
+unsafeSlice :: MVector v a => Int  -- ^ starting index
+                           -> Int  -- ^ length of the slice
+                           -> v s a
+                           -> v s a
+{-# INLINE unsafeSlice #-}
+unsafeSlice i n v = UNSAFE_CHECK(checkSlice) "unsafeSlice" i n (length v)
+                  $ basicUnsafeSlice i n v
+
+unsafeInit :: MVector v a => v s a -> v s a
+{-# INLINE unsafeInit #-}
+unsafeInit v = unsafeSlice 0 (length v - 1) v
+
+unsafeTail :: MVector v a => v s a -> v s a
+{-# INLINE unsafeTail #-}
+unsafeTail v = unsafeSlice 1 (length v - 1) v
+
+unsafeTake :: MVector v a => Int -> v s a -> v s a
+{-# INLINE unsafeTake #-}
+unsafeTake n v = unsafeSlice 0 n v
+
+unsafeDrop :: MVector v a => Int -> v s a -> v s a
+{-# INLINE unsafeDrop #-}
+unsafeDrop n v = unsafeSlice n (length v - n) v
+
+-- Overlapping
+-- -----------
+
+-- Check whether two vectors overlap.
+overlaps :: MVector v a => v s a -> v s a -> Bool
+{-# INLINE overlaps #-}
+overlaps = basicOverlaps
+
+-- Initialisation
+-- --------------
+
 -- | Create a mutable vector of the given length.
 new :: (PrimMonad m, MVector v a) => Int -> m (v (PrimState m) a)
 {-# INLINE new #-}
 new n = BOUNDS_CHECK(checkLength) "new" n
       $ unsafeNew n
 
--- | Create a mutable vector of the given length and fill it with an
--- initial value.
-newWith :: (PrimMonad m, MVector v a) => Int -> a -> m (v (PrimState m) a)
-{-# INLINE newWith #-}
-newWith n x = BOUNDS_CHECK(checkLength) "newWith" n
-            $ unsafeNewWith n x
-
 -- | Create a mutable vector of the given length. The length is not checked.
 unsafeNew :: (PrimMonad m, MVector v a) => Int -> m (v (PrimState m) a)
 {-# INLINE unsafeNew #-}
 unsafeNew n = UNSAFE_CHECK(checkLength) "unsafeNew" n
             $ basicUnsafeNew n
 
--- | Create a mutable vector of the given length and fill it with an
--- initial value. The length is not checked.
-unsafeNewWith :: (PrimMonad m, MVector v a) => Int -> a -> m (v (PrimState m) a)
-{-# INLINE unsafeNewWith #-}
-unsafeNewWith n x = UNSAFE_CHECK(checkLength) "unsafeNewWith" n
-                  $ basicUnsafeNewWith n x
+-- | Create a mutable vector of the given length (0 if the length is negative)
+-- and fill it with an initial value.
+replicate :: (PrimMonad m, MVector v a) => Int -> a -> m (v (PrimState m) a)
+{-# INLINE replicate #-}
+replicate n x = basicUnsafeReplicate (delay_inline max 0 n) x
 
+-- | Create a copy of a mutable vector.
+clone :: (PrimMonad m, MVector v a) => v (PrimState m) a -> m (v (PrimState m) a)
+{-# INLINE clone #-}
+clone v = do
+            v' <- unsafeNew (length v)
+            unsafeCopy v' v
+            return v'
 
 -- Growing
 -- -------
@@ -445,6 +534,15 @@
                          basicUnsafeCopy (basicUnsafeSlice by n v') v
                          return v'
 
+-- Restricting memory usage
+-- ------------------------
+
+-- | Reset all elements of the vector to some undefined value, clearing all
+-- references to external objects. This is usually a noop for unboxed vectors. 
+clear :: (PrimMonad m, MVector v a) => v (PrimState m) a -> m ()
+{-# INLINE clear #-}
+clear = basicClear
+
 -- Accessing individual elements
 -- -----------------------------
 
@@ -509,14 +607,8 @@
                          unsafeWrite v i x
                          return y
 
--- Block operations
--- ----------------
-
--- | Reset all elements of the vector to some undefined value, clearing all
--- references to external objects. This is usually a noop for unboxed vectors. 
-clear :: (PrimMonad m, MVector v a) => v (PrimState m) a -> m ()
-{-# INLINE clear #-}
-clear = basicClear
+-- Filling and copying
+-- -------------------
 
 -- | Set all elements of the vector to the given value.
 set :: (PrimMonad m, MVector v a) => v (PrimState m) a -> a -> m ()
@@ -546,60 +638,7 @@
                                          (not (dst `overlaps` src))
                    $ (dst `seq` src `seq` basicUnsafeCopy dst src)
 
--- Subvectors
--- ----------
 
--- | Yield a part of the mutable vector without copying it.
-slice :: MVector v a => Int -> Int -> v s a -> v s a
-{-# INLINE slice #-}
-slice i n v = BOUNDS_CHECK(checkSlice) "slice" i n (length v)
-            $ unsafeSlice i n v
-
-take :: MVector v a => Int -> v s a -> v s a
-{-# INLINE take #-}
-take n v = unsafeSlice 0 (min (max n 0) (length v)) v
-
-drop :: MVector v a => Int -> v s a -> v s a
-{-# INLINE drop #-}
-drop n v = unsafeSlice (min m n') (max 0 (m - n')) v
-  where
-    n' = max n 0
-    m  = length v
-
-init :: MVector v a => v s a -> v s a
-{-# INLINE init #-}
-init v = slice 0 (length v - 1) v
-
-tail :: MVector v a => v s a -> v s a
-{-# INLINE tail #-}
-tail v = slice 1 (length v - 1) v
-
--- | Yield a part of the mutable vector without copying it. No bounds checks
--- are performed.
-unsafeSlice :: MVector v a => Int  -- ^ starting index
-                           -> Int  -- ^ length of the slice
-                           -> v s a
-                           -> v s a
-{-# INLINE unsafeSlice #-}
-unsafeSlice i n v = UNSAFE_CHECK(checkSlice) "unsafeSlice" i n (length v)
-                  $ basicUnsafeSlice i n v
-
-unsafeInit :: MVector v a => v s a -> v s a
-{-# INLINE unsafeInit #-}
-unsafeInit v = unsafeSlice 0 (length v - 1) v
-
-unsafeTail :: MVector v a => v s a -> v s a
-{-# INLINE unsafeTail #-}
-unsafeTail v = unsafeSlice 1 (length v - 1) v
-
-unsafeTake :: MVector v a => Int -> v s a -> v s a
-{-# INLINE unsafeTake #-}
-unsafeTake n v = unsafeSlice 0 n v
-
-unsafeDrop :: MVector v a => Int -> v s a -> v s a
-{-# INLINE unsafeDrop #-}
-unsafeDrop n v = unsafeSlice n (length v - n) v
-
 -- Permutations
 -- ------------
 
@@ -610,19 +649,23 @@
   where
     {-# INLINE_INNER upd #-}
     upd (i,b) = do
-                  a <- BOUNDS_CHECK(checkIndex) "accum" i (length v)
+                  a <- BOUNDS_CHECK(checkIndex) "accum" i n
                      $ unsafeRead v i
                   unsafeWrite v i (f a b)
 
+    !n = length v
+
 update :: (PrimMonad m, MVector v a)
                         => v (PrimState m) a -> Stream (Int, a) -> m ()
 {-# INLINE update #-}
 update !v s = Stream.mapM_ upd s
   where
     {-# INLINE_INNER upd #-}
-    upd (i,b) = BOUNDS_CHECK(checkIndex) "update" i (length v)
+    upd (i,b) = BOUNDS_CHECK(checkIndex) "update" i n
               $ unsafeWrite v i b
 
+    !n = length v
+
 unsafeAccum :: (PrimMonad m, MVector v a)
             => (a -> b -> a) -> v (PrimState m) a -> Stream (Int, b) -> m ()
 {-# INLINE unsafeAccum #-}
@@ -630,19 +673,23 @@
   where
     {-# INLINE_INNER upd #-}
     upd (i,b) = do
-                  a <- UNSAFE_CHECK(checkIndex) "accum" i (length v)
+                  a <- UNSAFE_CHECK(checkIndex) "accum" i n
                      $ unsafeRead v i
                   unsafeWrite v i (f a b)
 
+    !n = length v
+
 unsafeUpdate :: (PrimMonad m, MVector v a)
                         => v (PrimState m) a -> Stream (Int, a) -> m ()
 {-# INLINE unsafeUpdate #-}
 unsafeUpdate !v s = Stream.mapM_ upd s
   where
     {-# INLINE_INNER upd #-}
-    upd (i,b) = UNSAFE_CHECK(checkIndex) "accum" i (length v)
+    upd (i,b) = UNSAFE_CHECK(checkIndex) "accum" i n
                   $ unsafeWrite v i b
 
+    !n = length v
+
 reverse :: (PrimMonad m, MVector v a) => v (PrimState m) a -> m ()
 {-# INLINE reverse #-}
 reverse !v = reverse_loop 0 (length v - 1)
@@ -768,4 +815,19 @@
       | otherwise = do
                       v2' <- unsafeAppend1 v2 i2 x
                       return (v1, i1, v2', i2+1)
+
+-- Deprecated functions
+-- --------------------
+
+-- | /DEPRECATED/ Use 'replicate' instead
+newWith :: (PrimMonad m, MVector v a) => Int -> a -> m (v (PrimState m) a)
+{-# INLINE newWith #-}
+newWith = replicate
+
+-- | /DEPRECATED/ Use 'replicate' instead
+unsafeNewWith :: (PrimMonad m, MVector v a) => Int -> a -> m (v (PrimState m) a)
+{-# INLINE unsafeNewWith #-}
+unsafeNewWith = replicate
+
+{-# DEPRECATED newWith, unsafeNewWith "Use replicate instead" #-}
 
diff --git a/Data/Vector/Generic/New.hs b/Data/Vector/Generic/New.hs
--- a/Data/Vector/Generic/New.hs
+++ b/Data/Vector/Generic/New.hs
@@ -37,7 +37,7 @@
 
 create :: (forall s. ST s (Mutable v s a)) -> New v a
 {-# INLINE create #-}
-create = New
+create p = New p
 
 run :: New v a -> ST s (Mutable v s a)
 {-# INLINE run #-}
diff --git a/Data/Vector/Mutable.hs b/Data/Vector/Mutable.hs
--- a/Data/Vector/Mutable.hs
+++ b/Data/Vector/Mutable.hs
@@ -16,20 +16,48 @@
   -- * Mutable boxed vectors
   MVector(..), IOVector, STVector,
 
-  -- * Operations on mutable vectors
-  length, overlaps, slice, new, newWith, read, write, swap,
-  clear, set, copy, grow,
+  -- * Accessors
 
-  -- * Unsafe operations
-  unsafeSlice, unsafeNew, unsafeNewWith, unsafeRead, unsafeWrite,
-  unsafeCopy, unsafeGrow
+  -- ** Length information
+  length, null,
+
+  -- ** Extracting subvectors
+  slice, init, tail, take, drop,
+  unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
+
+  -- ** Overlapping
+  overlaps,
+
+  -- * Construction
+
+  -- ** Initialisation
+  new, unsafeNew, replicate, clone,
+
+  -- ** Growing
+  grow, unsafeGrow,
+
+  -- ** Restricting memory usage
+  clear,
+
+  -- * Accessing individual elements
+  read, write, swap,
+  unsafeRead, unsafeWrite, unsafeSwap,
+
+  -- * Modifying vectors
+
+  -- ** Filling and copying
+  set, copy, unsafeCopy,
+
+  -- * Deprecated operations
+  newWith, unsafeNewWith
 ) where
 
 import qualified Data.Vector.Generic.Mutable as G
 import           Data.Primitive.Array
 import           Control.Monad.Primitive
 
-import Prelude hiding ( length, read )
+import Prelude hiding ( length, null, replicate, reverse, map, read,
+                        take, drop, init, tail )
 
 import Data.Typeable ( Typeable )
 
@@ -64,8 +92,8 @@
         arr <- newArray n uninitialised
         return (MVector 0 n arr)
 
-  {-# INLINE basicUnsafeNewWith #-}
-  basicUnsafeNewWith n x
+  {-# INLINE basicUnsafeReplicate #-}
+  basicUnsafeReplicate n x
     = do
         arr <- newArray n x
         return (MVector 0 n arr)
@@ -82,7 +110,43 @@
 uninitialised :: a
 uninitialised = error "Data.Vector.Mutable: uninitialised element"
 
+-- Length information
+-- ------------------
 
+-- | Length of the mutable vector.
+length :: MVector s a -> Int
+{-# INLINE length #-}
+length = G.length
+
+-- | Check whether the vector is empty
+null :: MVector s a -> Bool
+{-# INLINE null #-}
+null = G.null
+
+-- Extracting subvectors
+-- ---------------------
+
+-- | Yield a part of the mutable vector without copying it.
+slice :: Int -> Int -> MVector s a -> MVector s a
+{-# INLINE slice #-}
+slice = G.slice
+
+take :: Int -> MVector s a -> MVector s a
+{-# INLINE take #-}
+take = G.take
+
+drop :: Int -> MVector s a -> MVector s a
+{-# INLINE drop #-}
+drop = G.drop
+
+init :: MVector s a -> MVector s a
+{-# INLINE init #-}
+init = G.init
+
+tail :: MVector s a -> MVector s a
+{-# INLINE tail #-}
+tail = G.tail
+
 -- | Yield a part of the mutable vector without copying it. No bounds checks
 -- are performed.
 unsafeSlice :: Int  -- ^ starting index
@@ -92,39 +156,63 @@
 {-# INLINE unsafeSlice #-}
 unsafeSlice = G.unsafeSlice
 
+unsafeTake :: Int -> MVector s a -> MVector s a
+{-# INLINE unsafeTake #-}
+unsafeTake = G.unsafeTake
+
+unsafeDrop :: Int -> MVector s a -> MVector s a
+{-# INLINE unsafeDrop #-}
+unsafeDrop = G.unsafeDrop
+
+unsafeInit :: MVector s a -> MVector s a
+{-# INLINE unsafeInit #-}
+unsafeInit = G.unsafeInit
+
+unsafeTail :: MVector s a -> MVector s a
+{-# INLINE unsafeTail #-}
+unsafeTail = G.unsafeTail
+
+-- Overlapping
+-- -----------
+
+-- Check whether two vectors overlap.
+overlaps :: MVector s a -> MVector s a -> Bool
+{-# INLINE overlaps #-}
+overlaps = G.overlaps
+
+-- Initialisation
+-- --------------
+
+-- | Create a mutable vector of the given length.
+new :: PrimMonad m => Int -> m (MVector (PrimState m) a)
+{-# INLINE new #-}
+new = G.new
+
 -- | Create a mutable vector of the given length. The length is not checked.
 unsafeNew :: PrimMonad m => Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeNew #-}
 unsafeNew = G.unsafeNew
 
--- | Create a mutable vector of the given length and fill it with an
--- initial value. The length is not checked.
-unsafeNewWith :: PrimMonad m => Int -> a -> m (MVector (PrimState m) a)
-{-# INLINE unsafeNewWith #-}
-unsafeNewWith = G.unsafeNewWith
-
--- | Yield the element at the given position. No bounds checks are performed.
-unsafeRead :: PrimMonad m => MVector (PrimState m) a -> Int -> m a
-{-# INLINE unsafeRead #-}
-unsafeRead = G.unsafeRead
+-- | Create a mutable vector of the given length (0 if the length is negative)
+-- and fill it with an initial value.
+replicate :: PrimMonad m => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE replicate #-}
+replicate = G.replicate
 
--- | Replace the element at the given position. No bounds checks are performed.
-unsafeWrite :: PrimMonad m => MVector (PrimState m) a -> Int -> a -> m ()
-{-# INLINE unsafeWrite #-}
-unsafeWrite = G.unsafeWrite
+-- | Create a copy of a mutable vector.
+clone :: PrimMonad m => MVector (PrimState m) a -> m (MVector (PrimState m) a)
+{-# INLINE clone #-}
+clone = G.clone
 
--- | Swap the elements at the given positions. No bounds checks are performed.
-unsafeSwap :: PrimMonad m => MVector (PrimState m) a -> Int -> Int -> m ()
-{-# INLINE unsafeSwap #-}
-unsafeSwap = G.unsafeSwap
+-- Growing
+-- -------
 
--- | Copy a vector. The two vectors must have the same length and may not
--- overlap. This is not checked.
-unsafeCopy :: PrimMonad m => MVector (PrimState m) a   -- ^ target
-                          -> MVector (PrimState m) a   -- ^ source
-                          -> m ()
-{-# INLINE unsafeCopy #-}
-unsafeCopy = G.unsafeCopy
+-- | Grow a vector by the given number of elements. The number must be
+-- positive.
+grow :: PrimMonad m
+              => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
+{-# INLINE grow #-}
+grow = G.grow
 
 -- | Grow a vector by the given number of elements. The number must be
 -- positive but this is not checked.
@@ -133,31 +221,17 @@
 {-# INLINE unsafeGrow #-}
 unsafeGrow = G.unsafeGrow
 
--- | Length of the mutable vector.
-length :: MVector s a -> Int
-{-# INLINE length #-}
-length = G.length
-
--- Check whether two vectors overlap.
-overlaps :: MVector s a -> MVector s a -> Bool
-{-# INLINE overlaps #-}
-overlaps = G.overlaps
-
--- | Yield a part of the mutable vector without copying it.
-slice :: Int -> Int -> MVector s a -> MVector s a
-{-# INLINE slice #-}
-slice = G.slice
+-- Restricting memory usage
+-- ------------------------
 
--- | Create a mutable vector of the given length.
-new :: PrimMonad m => Int -> m (MVector (PrimState m) a)
-{-# INLINE new #-}
-new = G.new
+-- | Reset all elements of the vector to some undefined value, clearing all
+-- references to external objects. This is usually a noop for unboxed vectors. 
+clear :: PrimMonad m => MVector (PrimState m) a -> m ()
+{-# INLINE clear #-}
+clear = G.clear
 
--- | Create a mutable vector of the given length and fill it with an
--- initial value.
-newWith :: PrimMonad m => Int -> a -> m (MVector (PrimState m) a)
-{-# INLINE newWith #-}
-newWith = G.newWith
+-- Accessing individual elements
+-- -----------------------------
 
 -- | Yield the element at the given position.
 read :: PrimMonad m => MVector (PrimState m) a -> Int -> m a
@@ -174,12 +248,25 @@
 {-# INLINE swap #-}
 swap = G.swap
 
--- | Reset all elements of the vector to some undefined value, clearing all
--- references to external objects. This is usually a noop for unboxed vectors. 
-clear :: PrimMonad m => MVector (PrimState m) a -> m ()
-{-# INLINE clear #-}
-clear = G.clear
 
+-- | Yield the element at the given position. No bounds checks are performed.
+unsafeRead :: PrimMonad m => MVector (PrimState m) a -> Int -> m a
+{-# INLINE unsafeRead #-}
+unsafeRead = G.unsafeRead
+
+-- | Replace the element at the given position. No bounds checks are performed.
+unsafeWrite :: PrimMonad m => MVector (PrimState m) a -> Int -> a -> m ()
+{-# INLINE unsafeWrite #-}
+unsafeWrite = G.unsafeWrite
+
+-- | Swap the elements at the given positions. No bounds checks are performed.
+unsafeSwap :: PrimMonad m => MVector (PrimState m) a -> Int -> Int -> m ()
+{-# INLINE unsafeSwap #-}
+unsafeSwap = G.unsafeSwap
+
+-- Filling and copying
+-- -------------------
+
 -- | Set all elements of the vector to the given value.
 set :: PrimMonad m => MVector (PrimState m) a -> a -> m ()
 {-# INLINE set #-}
@@ -192,10 +279,26 @@
 {-# INLINE copy #-}
 copy = G.copy
 
--- | Grow a vector by the given number of elements. The number must be
--- positive.
-grow :: PrimMonad m
-              => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
-{-# INLINE grow #-}
-grow = G.grow
+-- | Copy a vector. The two vectors must have the same length and may not
+-- overlap. This is not checked.
+unsafeCopy :: PrimMonad m => MVector (PrimState m) a   -- ^ target
+                          -> MVector (PrimState m) a   -- ^ source
+                          -> m ()
+{-# INLINE unsafeCopy #-}
+unsafeCopy = G.unsafeCopy
+
+-- Deprecated functions
+-- --------------------
+
+-- | /DEPRECATED/ Use 'replicate' instead
+newWith :: PrimMonad m => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE newWith #-}
+newWith = G.replicate
+
+-- | /DEPRECATED/ Use 'replicate' instead
+unsafeNewWith :: PrimMonad m => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE unsafeNewWith #-}
+unsafeNewWith = G.replicate
+
+{-# DEPRECATED newWith, unsafeNewWith "Use replicate instead" #-}
 
diff --git a/Data/Vector/Primitive.hs b/Data/Vector/Primitive.hs
--- a/Data/Vector/Primitive.hs
+++ b/Data/Vector/Primitive.hs
@@ -25,7 +25,7 @@
   length, null,
 
   -- ** Indexing
-  (!), head, last,
+  (!), (!?), head, last,
   unsafeIndex, unsafeHead, unsafeLast,
 
   -- ** Monadic indexing
@@ -51,7 +51,7 @@
   enumFromN, enumFromStepN, enumFromTo, enumFromThenTo,
 
   -- ** Concatenation
-  cons, snoc, (++),
+  cons, snoc, (++), concat,
 
   -- ** Restricting memory usage
   force,
@@ -125,8 +125,11 @@
   -- ** Lists
   toList, fromList, fromListN,
 
+  -- ** Other vector types
+  G.convert,
+
   -- ** Mutable vectors
-  copy, unsafeCopy
+  freeze, thaw, copy, unsafeFreeze, unsafeThaw, unsafeCopy
 ) where
 
 import qualified Data.Vector.Generic           as G
@@ -140,7 +143,7 @@
 import Control.Monad.Primitive
 
 import Prelude hiding ( length, null,
-                        replicate, (++),
+                        replicate, (++), concat,
                         head, last,
                         init, tail, take, drop, reverse,
                         map, concatMap,
@@ -158,6 +161,8 @@
 import Data.Typeable ( Typeable )
 import Data.Data     ( Data(..) )
 
+import Data.Monoid   ( Monoid(..) )
+
 -- | Unboxed vectors of primitive types
 data Vector a = Vector {-# UNPACK #-} !Int
                        {-# UNPACK #-} !Int
@@ -178,10 +183,14 @@
 type instance G.Mutable Vector = MVector
 
 instance Prim a => G.Vector Vector a where
-  {-# INLINE unsafeFreeze #-}
-  unsafeFreeze (MVector i n marr)
+  {-# INLINE basicUnsafeFreeze #-}
+  basicUnsafeFreeze (MVector i n marr)
     = Vector i n `liftM` unsafeFreezeByteArray marr
 
+  {-# INLINE basicUnsafeThaw #-}
+  basicUnsafeThaw (Vector i n arr)
+    = MVector i n `liftM` unsafeThawByteArray arr
+
   {-# INLINE basicLength #-}
   basicLength (Vector _ n _) = n
 
@@ -225,6 +234,16 @@
   {-# INLINE (>=) #-}
   xs >= ys = Stream.cmp (G.stream xs) (G.stream ys) /= LT
 
+instance Prim a => Monoid (Vector a) where
+  {-# INLINE mempty #-}
+  mempty = empty
+
+  {-# INLINE mappend #-}
+  mappend = (++)
+
+  {-# INLINE mconcat #-}
+  mconcat = concat
+
 -- Length
 -- ------
 
@@ -246,6 +265,11 @@
 {-# INLINE (!) #-}
 (!) = (G.!)
 
+-- | O(1) Safe indexing
+(!?) :: Prim a => Vector a -> Int -> Maybe a
+{-# INLINE (!?) #-}
+(!?) = (G.!?)
+
 -- | /O(1)/ First element
 head :: Prim a => Vector a -> a
 {-# INLINE head #-}
@@ -497,6 +521,11 @@
 {-# INLINE (++) #-}
 (++) = (G.++)
 
+-- | /O(n)/ Concatenate all vectors in the list
+concat :: Prim a => [Vector a] -> Vector a
+{-# INLINE concat #-}
+concat = G.concat
+
 -- Monadic initialisation
 -- ----------------------
 
@@ -647,7 +676,7 @@
 -- @
 modify :: Prim a => (forall s. MVector s a -> ST s ()) -> Vector a -> Vector a
 {-# INLINE modify #-}
-modify = G.modify
+modify p = G.modify p
 
 -- Mapping
 -- -------
@@ -1191,15 +1220,37 @@
 -- Conversions - Mutable vectors
 -- -----------------------------
 
+-- | /O(1)/ Unsafe convert a mutable vector to an immutable one without
+-- copying. The mutable vector may not be used after this operation.
+unsafeFreeze :: (Prim a, PrimMonad m) => MVector (PrimState m) a -> m (Vector a)
+{-# INLINE unsafeFreeze #-}
+unsafeFreeze = G.unsafeFreeze
+
+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one without
+-- copying. The immutable vector may not be used after this operation.
+unsafeThaw :: (Prim a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a)
+{-# INLINE unsafeThaw #-}
+unsafeThaw = G.unsafeThaw
+
+-- | /O(n)/ Yield a mutable copy of the immutable vector.
+thaw :: (Prim a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a)
+{-# INLINE thaw #-}
+thaw = G.thaw
+
+-- | /O(n)/ Yield an immutable copy of the mutable vector.
+freeze :: (Prim a, PrimMonad m) => MVector (PrimState m) a -> m (Vector a)
+{-# INLINE freeze #-}
+freeze = G.freeze
+
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
--- have the same length.
+-- have the same length. This is not checked.
 unsafeCopy
   :: (Prim a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m ()
 {-# INLINE unsafeCopy #-}
 unsafeCopy = G.unsafeCopy
            
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
--- have the same length. This is not checked.
+-- have the same length.
 copy :: (Prim a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m ()
 {-# INLINE copy #-}
 copy = G.copy
diff --git a/Data/Vector/Primitive/Mutable.hs b/Data/Vector/Primitive/Mutable.hs
--- a/Data/Vector/Primitive/Mutable.hs
+++ b/Data/Vector/Primitive/Mutable.hs
@@ -16,13 +16,40 @@
   -- * Mutable vectors of primitive types
   MVector(..), IOVector, STVector, Prim,
 
-  -- * Operations on mutable vectors
-  length, overlaps, slice, new, newWith, read, write, swap,
-  clear, set, copy, grow,
+  -- * Accessors
 
-  -- * Unsafe operations
-  unsafeSlice, unsafeNew, unsafeNewWith, unsafeRead, unsafeWrite, unsafeSwap,
-  unsafeCopy, unsafeGrow
+  -- ** Length information
+  length, null,
+
+  -- ** Extracting subvectors
+  slice, init, tail, take, drop,
+  unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
+
+  -- ** Overlapping
+  overlaps,
+
+  -- * Construction
+
+  -- ** Initialisation
+  new, unsafeNew, replicate, clone,
+
+  -- ** Growing
+  grow, unsafeGrow,
+
+  -- ** Restricting memory usage
+  clear,
+
+  -- * Accessing individual elements
+  read, write, swap,
+  unsafeRead, unsafeWrite, unsafeSwap,
+
+  -- * Modifying vectors
+
+  -- ** Filling and copying
+  set, copy, unsafeCopy,
+
+  -- * Deprecated operations
+  newWith, unsafeNewWith
 ) where
 
 import qualified Data.Vector.Generic.Mutable as G
@@ -31,7 +58,8 @@
 import           Control.Monad.Primitive
 import           Control.Monad ( liftM )
 
-import Prelude hiding( length, read )
+import Prelude hiding ( length, null, replicate, reverse, map, read,
+                        take, drop, init, tail )
 
 import Data.Typeable ( Typeable )
 
@@ -74,52 +102,111 @@
     where
       sz = sizeOf (undefined :: a)
 
+-- Length information
+-- ------------------
+
+-- | Length of the mutable vector.
+length :: Prim a => MVector s a -> Int
+{-# INLINE length #-}
+length = G.length
+
+-- | Check whether the vector is empty
+null :: Prim a => MVector s a -> Bool
+{-# INLINE null #-}
+null = G.null
+
+-- Extracting subvectors
+-- ---------------------
+
+-- | Yield a part of the mutable vector without copying it.
+slice :: Prim a => Int -> Int -> MVector s a -> MVector s a
+{-# INLINE slice #-}
+slice = G.slice
+
+take :: Prim a => Int -> MVector s a -> MVector s a
+{-# INLINE take #-}
+take = G.take
+
+drop :: Prim a => Int -> MVector s a -> MVector s a
+{-# INLINE drop #-}
+drop = G.drop
+
+init :: Prim a => MVector s a -> MVector s a
+{-# INLINE init #-}
+init = G.init
+
+tail :: Prim a => MVector s a -> MVector s a
+{-# INLINE tail #-}
+tail = G.tail
+
 -- | Yield a part of the mutable vector without copying it. No bounds checks
 -- are performed.
-unsafeSlice :: Prim a => Int  -- ^ starting index
-                      -> Int  -- ^ length of the slice
-                      -> MVector s a   
-                      -> MVector s a
+unsafeSlice :: Prim a
+            => Int  -- ^ starting index
+            -> Int  -- ^ length of the slice
+            -> MVector s a
+            -> MVector s a
 {-# INLINE unsafeSlice #-}
 unsafeSlice = G.unsafeSlice
 
+unsafeTake :: Prim a => Int -> MVector s a -> MVector s a
+{-# INLINE unsafeTake #-}
+unsafeTake = G.unsafeTake
 
+unsafeDrop :: Prim a => Int -> MVector s a -> MVector s a
+{-# INLINE unsafeDrop #-}
+unsafeDrop = G.unsafeDrop
+
+unsafeInit :: Prim a => MVector s a -> MVector s a
+{-# INLINE unsafeInit #-}
+unsafeInit = G.unsafeInit
+
+unsafeTail :: Prim a => MVector s a -> MVector s a
+{-# INLINE unsafeTail #-}
+unsafeTail = G.unsafeTail
+
+-- Overlapping
+-- -----------
+
+-- Check whether two vectors overlap.
+overlaps :: Prim a => MVector s a -> MVector s a -> Bool
+{-# INLINE overlaps #-}
+overlaps = G.overlaps
+
+-- Initialisation
+-- --------------
+
+-- | Create a mutable vector of the given length.
+new :: (PrimMonad m, Prim a) => Int -> m (MVector (PrimState m) a)
+{-# INLINE new #-}
+new = G.new
+
 -- | Create a mutable vector of the given length. The length is not checked.
 unsafeNew :: (PrimMonad m, Prim a) => Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeNew #-}
 unsafeNew = G.unsafeNew
 
--- | Create a mutable vector of the given length and fill it with an
--- initial value. The length is not checked.
-unsafeNewWith :: (PrimMonad m, Prim a)
-                                => Int -> a -> m (MVector (PrimState m) a)
-{-# INLINE unsafeNewWith #-}
-unsafeNewWith = G.unsafeNewWith
-
--- | Yield the element at the given position. No bounds checks are performed.
-unsafeRead :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> Int -> m a
-{-# INLINE unsafeRead #-}
-unsafeRead = G.unsafeRead
+-- | Create a mutable vector of the given length (0 if the length is negative)
+-- and fill it with an initial value.
+replicate :: (PrimMonad m, Prim a) => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE replicate #-}
+replicate = G.replicate
 
--- | Replace the element at the given position. No bounds checks are performed.
-unsafeWrite :: (PrimMonad m, Prim a)
-                                => MVector (PrimState m) a -> Int -> a -> m ()
-{-# INLINE unsafeWrite #-}
-unsafeWrite = G.unsafeWrite
+-- | Create a copy of a mutable vector.
+clone :: (PrimMonad m, Prim a)
+      => MVector (PrimState m) a -> m (MVector (PrimState m) a)
+{-# INLINE clone #-}
+clone = G.clone
 
--- | Swap the elements at the given positions. No bounds checks are performed.
-unsafeSwap :: (PrimMonad m, Prim a)
-                => MVector (PrimState m) a -> Int -> Int -> m ()
-{-# INLINE unsafeSwap #-}
-unsafeSwap = G.unsafeSwap
+-- Growing
+-- -------
 
--- | Copy a vector. The two vectors must have the same length and may not
--- overlap. This is not checked.
-unsafeCopy :: (PrimMonad m, Prim a) => MVector (PrimState m) a   -- ^ target
-                                    -> MVector (PrimState m) a   -- ^ source
-                                    -> m ()
-{-# INLINE unsafeCopy #-}
-unsafeCopy = G.unsafeCopy
+-- | Grow a vector by the given number of elements. The number must be
+-- positive.
+grow :: (PrimMonad m, Prim a)  
+              => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
+{-# INLINE grow #-}
+grow = G.grow
 
 -- | Grow a vector by the given number of elements. The number must be
 -- positive but this is not checked.
@@ -128,31 +215,17 @@
 {-# INLINE unsafeGrow #-}
 unsafeGrow = G.unsafeGrow
 
--- | Length of the mutable vector.
-length :: Prim a => MVector s a -> Int
-{-# INLINE length #-}
-length = G.length
-
--- Check whether two vectors overlap.
-overlaps :: Prim a => MVector s a -> MVector s a -> Bool
-{-# INLINE overlaps #-}
-overlaps = G.overlaps
-
--- | Yield a part of the mutable vector without copying it.
-slice :: Prim a => Int -> Int -> MVector s a -> MVector s a
-{-# INLINE slice #-}
-slice = G.slice
+-- Restricting memory usage
+-- ------------------------
 
--- | Create a mutable vector of the given length.
-new :: (PrimMonad m, Prim a) => Int -> m (MVector (PrimState m) a)
-{-# INLINE new #-}
-new = G.new
+-- | Reset all elements of the vector to some undefined value, clearing all
+-- references to external objects. This is usually a noop for unboxed vectors. 
+clear :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> m ()
+{-# INLINE clear #-}
+clear = G.clear
 
--- | Create a mutable vector of the given length and fill it with an
--- initial value.
-newWith :: (PrimMonad m, Prim a) => Int -> a -> m (MVector (PrimState m) a)
-{-# INLINE newWith #-}
-newWith = G.newWith
+-- Accessing individual elements
+-- -----------------------------
 
 -- | Yield the element at the given position.
 read :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> Int -> m a
@@ -165,17 +238,31 @@
 write = G.write
 
 -- | Swap the elements at the given positions.
-swap :: (PrimMonad m, Prim a)
-                => MVector (PrimState m) a -> Int -> Int -> m ()
+swap :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> Int -> Int -> m ()
 {-# INLINE swap #-}
 swap = G.swap
 
--- | Reset all elements of the vector to some undefined value, clearing all
--- references to external objects. This is usually a noop for unboxed vectors. 
-clear :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> m ()
-{-# INLINE clear #-}
-clear = G.clear
 
+-- | Yield the element at the given position. No bounds checks are performed.
+unsafeRead :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> Int -> m a
+{-# INLINE unsafeRead #-}
+unsafeRead = G.unsafeRead
+
+-- | Replace the element at the given position. No bounds checks are performed.
+unsafeWrite
+    :: (PrimMonad m, Prim a) =>  MVector (PrimState m) a -> Int -> a -> m ()
+{-# INLINE unsafeWrite #-}
+unsafeWrite = G.unsafeWrite
+
+-- | Swap the elements at the given positions. No bounds checks are performed.
+unsafeSwap
+    :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> Int -> Int -> m ()
+{-# INLINE unsafeSwap #-}
+unsafeSwap = G.unsafeSwap
+
+-- Filling and copying
+-- -------------------
+
 -- | Set all elements of the vector to the given value.
 set :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> a -> m ()
 {-# INLINE set #-}
@@ -183,15 +270,32 @@
 
 -- | Copy a vector. The two vectors must have the same length and may not
 -- overlap.
-copy :: (PrimMonad m, Prim a)
-                => MVector (PrimState m) a -> MVector (PrimState m) a -> m ()
+copy :: (PrimMonad m, Prim a) 
+                 => MVector (PrimState m) a -> MVector (PrimState m) a -> m ()
 {-# INLINE copy #-}
 copy = G.copy
 
--- | Grow a vector by the given number of elements. The number must be
--- positive.
-grow :: (PrimMonad m, Prim a)
-              => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
-{-# INLINE grow #-}
-grow = G.grow
+-- | Copy a vector. The two vectors must have the same length and may not
+-- overlap. This is not checked.
+unsafeCopy :: (PrimMonad m, Prim a)
+           => MVector (PrimState m) a   -- ^ target
+           -> MVector (PrimState m) a   -- ^ source
+           -> m ()
+{-# INLINE unsafeCopy #-}
+unsafeCopy = G.unsafeCopy
+
+-- Deprecated functions
+-- --------------------
+
+-- | /DEPRECATED/ Use 'replicate' instead
+newWith :: (PrimMonad m, Prim a) => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE newWith #-}
+newWith = G.replicate
+
+-- | /DEPRECATED/ Use 'replicate' instead
+unsafeNewWith :: (PrimMonad m, Prim a) => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE unsafeNewWith #-}
+unsafeNewWith = G.replicate
+
+{-# DEPRECATED newWith, unsafeNewWith "Use replicate instead" #-}
 
diff --git a/Data/Vector/Storable.hs b/Data/Vector/Storable.hs
--- a/Data/Vector/Storable.hs
+++ b/Data/Vector/Storable.hs
@@ -22,7 +22,7 @@
   length, null,
 
   -- ** Indexing
-  (!), head, last,
+  (!), (!?), head, last,
   unsafeIndex, unsafeHead, unsafeLast,
 
   -- ** Monadic indexing
@@ -48,7 +48,7 @@
   enumFromN, enumFromStepN, enumFromTo, enumFromThenTo,
 
   -- ** Concatenation
-  cons, snoc, (++),
+  cons, snoc, (++), concat,
 
   -- ** Restricting memory usage
   force,
@@ -122,8 +122,11 @@
   -- ** Lists
   toList, fromList, fromListN,
 
+  -- ** Other vector types
+  G.convert,
+
   -- ** Mutable vectors
-  copy, unsafeCopy,
+  freeze, thaw, copy, unsafeFreeze, unsafeThaw, unsafeCopy,
 
   -- * Raw pointers
   unsafeFromForeignPtr, unsafeToForeignPtr, unsafeWith
@@ -143,7 +146,7 @@
 import Control.Monad.Primitive
 
 import Prelude hiding ( length, null,
-                        replicate, (++),
+                        replicate, (++), concat,
                         head, last,
                         init, tail, take, drop, reverse,
                         map, concatMap,
@@ -161,6 +164,8 @@
 import Data.Typeable ( Typeable )
 import Data.Data     ( Data(..) )
 
+import Data.Monoid   ( Monoid(..) )
+
 #include "vector.h"
 
 -- | 'Storable'-based vectors
@@ -185,9 +190,12 @@
 type instance G.Mutable Vector = MVector
 
 instance Storable a => G.Vector Vector a where
-  {-# INLINE unsafeFreeze #-}
-  unsafeFreeze (MVector p n fp) = return $ Vector p n fp
+  {-# INLINE basicUnsafeFreeze #-}
+  basicUnsafeFreeze (MVector p n fp) = return $ Vector p n fp
 
+  {-# INLINE basicUnsafeThaw #-}
+  basicUnsafeThaw (Vector p n fp) = return $ MVector p n fp
+
   {-# INLINE basicLength #-}
   basicLength (Vector _ n _) = n
 
@@ -235,27 +243,15 @@
   {-# INLINE (>=) #-}
   xs >= ys = Stream.cmp (G.stream xs) (G.stream ys) /= LT
 
-{-
-eq_memcmp :: forall a. Storable a => Vector a -> Vector a -> Bool
-{-# INLINE_STREAM eq_memcmp #-}
-eq_memcmp (Vector i m p) (Vector j n q)
-  = m == n && inlinePerformIO
-              (withForeignPtr p $ \p' ->
-               withForeignPtr q $ \q' ->
-               return $
-               memcmp (p' `plusPtr` i) (q' `plusPtr` j)
-                      (fromIntegral $ sizeOf (undefined :: a) * m) == 0)
-
-foreign import ccall unsafe "string.h memcmp" memcmp
-        :: Ptr a -> Ptr a -> CSize -> CInt
-
-{-# RULES
+instance Storable a => Monoid (Vector a) where
+  {-# INLINE mempty #-}
+  mempty = empty
 
-"(==) [Vector.Storable Int]"
-  G.eq = eq_memcmp :: Vector Int -> Vector Int -> Bool
- #-}
--}
+  {-# INLINE mappend #-}
+  mappend = (++)
 
+  {-# INLINE mconcat #-}
+  mconcat = concat
 
 -- Length
 -- ------
@@ -278,6 +274,11 @@
 {-# INLINE (!) #-}
 (!) = (G.!)
 
+-- | O(1) Safe indexing
+(!?) :: Storable a => Vector a -> Int -> Maybe a
+{-# INLINE (!?) #-}
+(!?) = (G.!?)
+
 -- | /O(1)/ First element
 head :: Storable a => Vector a -> a
 {-# INLINE head #-}
@@ -529,6 +530,11 @@
 {-# INLINE (++) #-}
 (++) = (G.++)
 
+-- | /O(n)/ Concatenate all vectors in the list
+concat :: Storable a => [Vector a] -> Vector a
+{-# INLINE concat #-}
+concat = G.concat
+
 -- Monadic initialisation
 -- ----------------------
 
@@ -679,7 +685,7 @@
 -- @
 modify :: Storable a => (forall s. MVector s a -> ST s ()) -> Vector a -> Vector a
 {-# INLINE modify #-}
-modify = G.modify
+modify p = G.modify p
 
 -- Mapping
 -- -------
@@ -1233,15 +1239,39 @@
 -- Conversions - Mutable vectors
 -- -----------------------------
 
+-- | /O(1)/ Unsafe convert a mutable vector to an immutable one without
+-- copying. The mutable vector may not be used after this operation.
+unsafeFreeze
+        :: (Storable a, PrimMonad m) => MVector (PrimState m) a -> m (Vector a)
+{-# INLINE unsafeFreeze #-}
+unsafeFreeze = G.unsafeFreeze
+
+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one without
+-- copying. The immutable vector may not be used after this operation.
+unsafeThaw
+        :: (Storable a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a)
+{-# INLINE unsafeThaw #-}
+unsafeThaw = G.unsafeThaw
+
+-- | /O(n)/ Yield a mutable copy of the immutable vector.
+thaw :: (Storable a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a)
+{-# INLINE thaw #-}
+thaw = G.thaw
+
+-- | /O(n)/ Yield an immutable copy of the mutable vector.
+freeze :: (Storable a, PrimMonad m) => MVector (PrimState m) a -> m (Vector a)
+{-# INLINE freeze #-}
+freeze = G.freeze
+
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
--- have the same length.
+-- have the same length. This is not checked.
 unsafeCopy
   :: (Storable a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m ()
 {-# INLINE unsafeCopy #-}
 unsafeCopy = G.unsafeCopy
            
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
--- have the same length. This is not checked.
+-- have the same length.
 copy :: (Storable a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m ()
 {-# INLINE copy #-}
 copy = G.copy
diff --git a/Data/Vector/Storable/Internal.hs b/Data/Vector/Storable/Internal.hs
--- a/Data/Vector/Storable/Internal.hs
+++ b/Data/Vector/Storable/Internal.hs
@@ -30,7 +30,7 @@
 ptrToOffset :: Storable a => ForeignPtr a -> Ptr a -> Int
 {-# INLINE ptrToOffset #-}
 ptrToOffset fp q = unsafeInlineIO
-                 $ withForeignPtr fp $ \p -> return (distance p q)
+                 $ withForeignPtr fp $ \p -> return (distance q p)
 
 offsetToPtr :: Storable a => ForeignPtr a -> Int -> Ptr a
 {-# INLINE offsetToPtr #-}
diff --git a/Data/Vector/Storable/Mutable.hs b/Data/Vector/Storable/Mutable.hs
--- a/Data/Vector/Storable/Mutable.hs
+++ b/Data/Vector/Storable/Mutable.hs
@@ -16,16 +16,43 @@
   -- * Mutable vectors of 'Storable' types
   MVector(..), IOVector, STVector, Storable,
 
-  -- * Operations on mutable vectors
-  length, overlaps, slice, new, newWith, read, write, swap,
-  clear, set, copy, grow,
+  -- * Accessors
 
-  -- * Unsafe operations
-  unsafeSlice, unsafeNew, unsafeNewWith, unsafeRead, unsafeWrite, unsafeSwap,
-  unsafeCopy, unsafeGrow,
+  -- ** Length information
+  length, null,
 
-  -- * Accessing the underlying memory
-  unsafeFromForeignPtr, unsafeToForeignPtr, unsafeWith
+  -- ** Extracting subvectors
+  slice, init, tail, take, drop,
+  unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
+
+  -- ** Overlapping
+  overlaps,
+
+  -- * Construction
+
+  -- ** Initialisation
+  new, unsafeNew, replicate, clone,
+
+  -- ** Growing
+  grow, unsafeGrow,
+
+  -- ** Restricting memory usage
+  clear,
+
+  -- * Accessing individual elements
+  read, write, swap,
+  unsafeRead, unsafeWrite, unsafeSwap,
+
+  -- * Modifying vectors
+
+  -- ** Filling and copying
+  set, copy, unsafeCopy,
+
+  -- * Raw pointers
+  unsafeFromForeignPtr, unsafeToForeignPtr, unsafeWith,
+
+  -- * Deprecated operations
+  newWith, unsafeNewWith
 ) where
 
 import qualified Data.Vector.Generic.Mutable as G
@@ -39,7 +66,8 @@
 
 import Control.Monad.Primitive
 
-import Prelude hiding( length, read )
+import Prelude hiding ( length, null, replicate, reverse, map, read,
+                        take, drop, init, tail )
 
 import Data.Typeable ( Typeable )
 
@@ -92,78 +120,111 @@
       withForeignPtr fq $ \_ ->
       copyArray p q n
 
--- | Create a mutable vector from a 'ForeignPtr' with an offset and a length.
--- Modifying data through the 'ForeignPtr' afterwards is unsafe if the vector
--- could have been frozen before the modification.
-unsafeFromForeignPtr :: Storable a
-                     => ForeignPtr a    -- ^ pointer
-                     -> Int             -- ^ offset
-                     -> Int             -- ^ length
-                     -> MVector s a
-{-# INLINE unsafeFromForeignPtr #-}
-unsafeFromForeignPtr fp i n = MVector (offsetToPtr fp i) n fp
+-- Length information
+-- ------------------
 
--- | Yield the underlying 'ForeignPtr' together with the offset to the data
--- and its length. Modifying the data through the 'ForeignPtr' is
--- unsafe if the vector could have frozen before the modification.
-unsafeToForeignPtr :: Storable a => MVector s a -> (ForeignPtr a, Int, Int)
-{-# INLINE unsafeToForeignPtr #-}
-unsafeToForeignPtr (MVector p n fp) = (fp, ptrToOffset fp p, n)
+-- | Length of the mutable vector.
+length :: Storable a => MVector s a -> Int
+{-# INLINE length #-}
+length = G.length
 
--- | Pass a pointer to the vector's data to the IO action. Modifying data
--- through the pointer is unsafe if the vector could have been frozen before
--- the modification.
-unsafeWith :: Storable a => IOVector a -> (Ptr a -> IO b) -> IO b
-{-# INLINE unsafeWith #-}
-unsafeWith (MVector p n fp) m = withForeignPtr fp $ \_ -> m p
+-- | Check whether the vector is empty
+null :: Storable a => MVector s a -> Bool
+{-# INLINE null #-}
+null = G.null
 
+-- Extracting subvectors
+-- ---------------------
+
+-- | Yield a part of the mutable vector without copying it.
+slice :: Storable a => Int -> Int -> MVector s a -> MVector s a
+{-# INLINE slice #-}
+slice = G.slice
+
+take :: Storable a => Int -> MVector s a -> MVector s a
+{-# INLINE take #-}
+take = G.take
+
+drop :: Storable a => Int -> MVector s a -> MVector s a
+{-# INLINE drop #-}
+drop = G.drop
+
+init :: Storable a => MVector s a -> MVector s a
+{-# INLINE init #-}
+init = G.init
+
+tail :: Storable a => MVector s a -> MVector s a
+{-# INLINE tail #-}
+tail = G.tail
+
 -- | Yield a part of the mutable vector without copying it. No bounds checks
 -- are performed.
-unsafeSlice :: Storable a => Int  -- ^ starting index
-                          -> Int  -- ^ length of the slice
-                          -> MVector s a
-                          -> MVector s a
+unsafeSlice :: Storable a
+            => Int  -- ^ starting index
+            -> Int  -- ^ length of the slice
+            -> MVector s a
+            -> MVector s a
 {-# INLINE unsafeSlice #-}
 unsafeSlice = G.unsafeSlice
 
+unsafeTake :: Storable a => Int -> MVector s a -> MVector s a
+{-# INLINE unsafeTake #-}
+unsafeTake = G.unsafeTake
+
+unsafeDrop :: Storable a => Int -> MVector s a -> MVector s a
+{-# INLINE unsafeDrop #-}
+unsafeDrop = G.unsafeDrop
+
+unsafeInit :: Storable a => MVector s a -> MVector s a
+{-# INLINE unsafeInit #-}
+unsafeInit = G.unsafeInit
+
+unsafeTail :: Storable a => MVector s a -> MVector s a
+{-# INLINE unsafeTail #-}
+unsafeTail = G.unsafeTail
+
+-- Overlapping
+-- -----------
+
+-- Check whether two vectors overlap.
+overlaps :: Storable a => MVector s a -> MVector s a -> Bool
+{-# INLINE overlaps #-}
+overlaps = G.overlaps
+
+-- Initialisation
+-- --------------
+
+-- | Create a mutable vector of the given length.
+new :: (PrimMonad m, Storable a) => Int -> m (MVector (PrimState m) a)
+{-# INLINE new #-}
+new = G.new
+
 -- | Create a mutable vector of the given length. The length is not checked.
 unsafeNew :: (PrimMonad m, Storable a) => Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeNew #-}
 unsafeNew = G.unsafeNew
 
--- | Create a mutable vector of the given length and fill it with an
--- initial value. The length is not checked.
-unsafeNewWith :: (PrimMonad m, Storable a)
-                                => Int -> a -> m (MVector (PrimState m) a)
-{-# INLINE unsafeNewWith #-}
-unsafeNewWith = G.unsafeNewWith
-
--- | Yield the element at the given position. No bounds checks are performed.
-unsafeRead :: (PrimMonad m, Storable a)
-                                => MVector (PrimState m) a -> Int -> m a
-{-# INLINE unsafeRead #-}
-unsafeRead = G.unsafeRead
+-- | Create a mutable vector of the given length (0 if the length is negative)
+-- and fill it with an initial value.
+replicate :: (PrimMonad m, Storable a) => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE replicate #-}
+replicate = G.replicate
 
--- | Replace the element at the given position. No bounds checks are performed.
-unsafeWrite :: (PrimMonad m, Storable a)
-                                => MVector (PrimState m) a -> Int -> a -> m ()
-{-# INLINE unsafeWrite #-}
-unsafeWrite = G.unsafeWrite
+-- | Create a copy of a mutable vector.
+clone :: (PrimMonad m, Storable a)
+      => MVector (PrimState m) a -> m (MVector (PrimState m) a)
+{-# INLINE clone #-}
+clone = G.clone
 
--- | Swap the elements at the given positions. No bounds checks are performed.
-unsafeSwap :: (PrimMonad m, Storable a)
-                => MVector (PrimState m) a -> Int -> Int -> m ()
-{-# INLINE unsafeSwap #-}
-unsafeSwap = G.unsafeSwap
+-- Growing
+-- -------
 
--- | Copy a vector. The two vectors must have the same length and may not
--- overlap. This is not checked.
-unsafeCopy :: (PrimMonad m, Storable a)
-                                => MVector (PrimState m) a   -- ^ target
-                                -> MVector (PrimState m) a   -- ^ source
-                                -> m ()
-{-# INLINE unsafeCopy #-}
-unsafeCopy = G.unsafeCopy
+-- | Grow a vector by the given number of elements. The number must be
+-- positive.
+grow :: (PrimMonad m, Storable a)  
+              => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
+{-# INLINE grow #-}
+grow = G.grow
 
 -- | Grow a vector by the given number of elements. The number must be
 -- positive but this is not checked.
@@ -172,31 +233,17 @@
 {-# INLINE unsafeGrow #-}
 unsafeGrow = G.unsafeGrow
 
--- | Length of the mutable vector.
-length :: Storable a => MVector s a -> Int
-{-# INLINE length #-}
-length = G.length
-
--- Check whether two vectors overlap.
-overlaps :: Storable a => MVector s a -> MVector s a -> Bool
-{-# INLINE overlaps #-}
-overlaps = G.overlaps
-
--- | Yield a part of the mutable vector without copying it.
-slice :: Storable a => Int -> Int -> MVector s a -> MVector s a
-{-# INLINE slice #-}
-slice = G.slice
+-- Restricting memory usage
+-- ------------------------
 
--- | Create a mutable vector of the given length.
-new :: (PrimMonad m, Storable a) => Int -> m (MVector (PrimState m) a)
-{-# INLINE new #-}
-new = G.new
+-- | Reset all elements of the vector to some undefined value, clearing all
+-- references to external objects. This is usually a noop for unboxed vectors. 
+clear :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> m ()
+{-# INLINE clear #-}
+clear = G.clear
 
--- | Create a mutable vector of the given length and fill it with an
--- initial value.
-newWith :: (PrimMonad m, Storable a) => Int -> a -> m (MVector (PrimState m) a)
-{-# INLINE newWith #-}
-newWith = G.newWith
+-- Accessing individual elements
+-- -----------------------------
 
 -- | Yield the element at the given position.
 read :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> Int -> m a
@@ -204,23 +251,38 @@
 read = G.read
 
 -- | Replace the element at the given position.
-write :: (PrimMonad m, Storable a)
-                                => MVector (PrimState m) a -> Int -> a -> m ()
+write
+    :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> Int -> a -> m ()
 {-# INLINE write #-}
 write = G.write
 
 -- | Swap the elements at the given positions.
-swap :: (PrimMonad m, Storable a)
-                => MVector (PrimState m) a -> Int -> Int -> m ()
+swap
+    :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> Int -> Int -> m ()
 {-# INLINE swap #-}
 swap = G.swap
 
--- | Reset all elements of the vector to some undefined value, clearing all
--- references to external objects. This is usually a noop for unboxed vectors. 
-clear :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> m ()
-{-# INLINE clear #-}
-clear = G.clear
 
+-- | Yield the element at the given position. No bounds checks are performed.
+unsafeRead :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> Int -> m a
+{-# INLINE unsafeRead #-}
+unsafeRead = G.unsafeRead
+
+-- | Replace the element at the given position. No bounds checks are performed.
+unsafeWrite
+    :: (PrimMonad m, Storable a) =>  MVector (PrimState m) a -> Int -> a -> m ()
+{-# INLINE unsafeWrite #-}
+unsafeWrite = G.unsafeWrite
+
+-- | Swap the elements at the given positions. No bounds checks are performed.
+unsafeSwap
+    :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> Int -> Int -> m ()
+{-# INLINE unsafeSwap #-}
+unsafeSwap = G.unsafeSwap
+
+-- Filling and copying
+-- -------------------
+
 -- | Set all elements of the vector to the given value.
 set :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> a -> m ()
 {-# INLINE set #-}
@@ -228,15 +290,60 @@
 
 -- | Copy a vector. The two vectors must have the same length and may not
 -- overlap.
-copy :: (PrimMonad m, Storable a)
-                => MVector (PrimState m) a -> MVector (PrimState m) a -> m ()
+copy :: (PrimMonad m, Storable a) 
+                 => MVector (PrimState m) a -> MVector (PrimState m) a -> m ()
 {-# INLINE copy #-}
 copy = G.copy
 
--- | Grow a vector by the given number of elements. The number must be
--- positive.
-grow :: (PrimMonad m, Storable a)
-              => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
-{-# INLINE grow #-}
-grow = G.grow
+-- | Copy a vector. The two vectors must have the same length and may not
+-- overlap. This is not checked.
+unsafeCopy :: (PrimMonad m, Storable a)
+           => MVector (PrimState m) a   -- ^ target
+           -> MVector (PrimState m) a   -- ^ source
+           -> m ()
+{-# INLINE unsafeCopy #-}
+unsafeCopy = G.unsafeCopy
+
+-- Raw pointers
+-- ------------
+
+-- | Create a mutable vector from a 'ForeignPtr' with an offset and a length.
+-- Modifying data through the 'ForeignPtr' afterwards is unsafe if the vector
+-- could have been frozen before the modification.
+unsafeFromForeignPtr :: Storable a
+                     => ForeignPtr a    -- ^ pointer
+                     -> Int             -- ^ offset
+                     -> Int             -- ^ length
+                     -> MVector s a
+{-# INLINE unsafeFromForeignPtr #-}
+unsafeFromForeignPtr fp i n = MVector (offsetToPtr fp i) n fp
+
+-- | Yield the underlying 'ForeignPtr' together with the offset to the data
+-- and its length. Modifying the data through the 'ForeignPtr' is
+-- unsafe if the vector could have frozen before the modification.
+unsafeToForeignPtr :: Storable a => MVector s a -> (ForeignPtr a, Int, Int)
+{-# INLINE unsafeToForeignPtr #-}
+unsafeToForeignPtr (MVector p n fp) = (fp, ptrToOffset fp p, n)
+
+-- | Pass a pointer to the vector's data to the IO action. Modifying data
+-- through the pointer is unsafe if the vector could have been frozen before
+-- the modification.
+unsafeWith :: Storable a => IOVector a -> (Ptr a -> IO b) -> IO b
+{-# INLINE unsafeWith #-}
+unsafeWith (MVector p n fp) m = withForeignPtr fp $ \_ -> m p
+
+-- Deprecated functions
+-- --------------------
+
+-- | /DEPRECATED/ Use 'replicate' instead
+newWith :: (PrimMonad m, Storable a) => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE newWith #-}
+newWith = G.replicate
+
+-- | /DEPRECATED/ Use 'replicate' instead
+unsafeNewWith :: (PrimMonad m, Storable a) => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE unsafeNewWith #-}
+unsafeNewWith = G.replicate
+
+{-# DEPRECATED newWith, unsafeNewWith "Use replicate instead" #-}
 
diff --git a/Data/Vector/Unboxed.hs b/Data/Vector/Unboxed.hs
--- a/Data/Vector/Unboxed.hs
+++ b/Data/Vector/Unboxed.hs
@@ -45,7 +45,7 @@
   length, null,
 
   -- ** Indexing
-  (!), head, last,
+  (!), (!?), head, last,
   unsafeIndex, unsafeHead, unsafeLast,
 
   -- ** Monadic indexing
@@ -71,7 +71,7 @@
   enumFromN, enumFromStepN, enumFromTo, enumFromThenTo,
 
   -- ** Concatenation
-  cons, snoc, (++),
+  cons, snoc, (++), concat,
 
   -- ** Restricting memory usage
   force,
@@ -149,8 +149,11 @@
   -- ** Lists
   toList, fromList, fromListN,
 
+  -- ** Other vector types
+  G.convert,
+
   -- ** Mutable vectors
-  copy, unsafeCopy
+  freeze, thaw, copy, unsafeFreeze, unsafeThaw, unsafeCopy
 ) where
 
 import Data.Vector.Unboxed.Base
@@ -161,7 +164,7 @@
 import Control.Monad.Primitive
 
 import Prelude hiding ( length, null,
-                        replicate, (++),
+                        replicate, (++), concat,
                         head, last,
                         init, tail, take, drop, reverse,
                         map, concatMap,
@@ -175,6 +178,8 @@
                         mapM, mapM_ )
 import qualified Prelude
 
+import Data.Monoid   ( Monoid(..) )
+
 #include "vector.h"
 
 -- See http://trac.haskell.org/vector/ticket/12
@@ -202,6 +207,16 @@
   {-# INLINE (>=) #-}
   xs >= ys = Stream.cmp (G.stream xs) (G.stream ys) /= LT
 
+instance Unbox a => Monoid (Vector a) where
+  {-# INLINE mempty #-}
+  mempty = empty
+
+  {-# INLINE mappend #-}
+  mappend = (++)
+
+  {-# INLINE mconcat #-}
+  mconcat = concat
+
 instance (Show a, Unbox a) => Show (Vector a) where
     show = (Prelude.++ " :: Data.Vector.Unboxed.Vector") . ("fromList " Prelude.++) . show . toList
 
@@ -226,6 +241,11 @@
 {-# INLINE (!) #-}
 (!) = (G.!)
 
+-- | O(1) Safe indexing
+(!?) :: Unbox a => Vector a -> Int -> Maybe a
+{-# INLINE (!?) #-}
+(!?) = (G.!?)
+
 -- | /O(1)/ First element
 head :: Unbox a => Vector a -> a
 {-# INLINE head #-}
@@ -476,6 +496,11 @@
 {-# INLINE (++) #-}
 (++) = (G.++)
 
+-- | /O(n)/ Concatenate all vectors in the list
+concat :: Unbox a => [Vector a] -> Vector a
+{-# INLINE concat #-}
+concat = G.concat
+
 -- Monadic initialisation
 -- ----------------------
 
@@ -673,7 +698,7 @@
 -- @
 modify :: Unbox a => (forall s. MVector s a -> ST s ()) -> Vector a -> Vector a
 {-# INLINE modify #-}
-modify = G.modify
+modify p = G.modify p
 
 -- Mapping
 -- -------
@@ -1223,15 +1248,37 @@
 -- Conversions - Mutable vectors
 -- -----------------------------
 
+-- | /O(1)/ Unsafe convert a mutable vector to an immutable one without
+-- copying. The mutable vector may not be used after this operation.
+unsafeFreeze :: (Unbox a, PrimMonad m) => MVector (PrimState m) a -> m (Vector a)
+{-# INLINE unsafeFreeze #-}
+unsafeFreeze = G.unsafeFreeze
+
+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one without
+-- copying. The immutable vector may not be used after this operation.
+unsafeThaw :: (Unbox a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a)
+{-# INLINE unsafeThaw #-}
+unsafeThaw = G.unsafeThaw
+
+-- | /O(n)/ Yield a mutable copy of the immutable vector.
+thaw :: (Unbox a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a)
+{-# INLINE thaw #-}
+thaw = G.thaw
+
+-- | /O(n)/ Yield an immutable copy of the mutable vector.
+freeze :: (Unbox a, PrimMonad m) => MVector (PrimState m) a -> m (Vector a)
+{-# INLINE freeze #-}
+freeze = G.freeze
+
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
--- have the same length.
+-- have the same length. This is not checked.
 unsafeCopy
   :: (Unbox a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m ()
 {-# INLINE unsafeCopy #-}
 unsafeCopy = G.unsafeCopy
            
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
--- have the same length. This is not checked.
+-- have the same length.
 copy :: (Unbox a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m ()
 {-# INLINE copy #-}
 copy = G.copy
diff --git a/Data/Vector/Unboxed/Base.hs b/Data/Vector/Unboxed/Base.hs
--- a/Data/Vector/Unboxed/Base.hs
+++ b/Data/Vector/Unboxed/Base.hs
@@ -106,9 +106,12 @@
   basicUnsafeGrow (MV_Unit n) m = return $ MV_Unit (n+m)
 
 instance G.Vector Vector () where
-  {-# INLINE unsafeFreeze #-}
-  unsafeFreeze (MV_Unit n) = return $ V_Unit n
+  {-# INLINE basicUnsafeFreeze #-}
+  basicUnsafeFreeze (MV_Unit n) = return $ V_Unit n
 
+  {-# INLINE basicUnsafeThaw #-}
+  basicUnsafeThaw (V_Unit n) = return $ MV_Unit n
+
   {-# INLINE basicLength #-}
   basicLength (V_Unit n) = n
 
@@ -135,7 +138,7 @@
 ; {-# INLINE basicUnsafeSlice #-}                                       \
 ; {-# INLINE basicOverlaps #-}                                          \
 ; {-# INLINE basicUnsafeNew #-}                                         \
-; {-# INLINE basicUnsafeNewWith #-}                                     \
+; {-# INLINE basicUnsafeReplicate #-}                                   \
 ; {-# INLINE basicUnsafeRead #-}                                        \
 ; {-# INLINE basicUnsafeWrite #-}                                       \
 ; {-# INLINE basicClear #-}                                             \
@@ -146,7 +149,7 @@
 ; basicUnsafeSlice i n (con v) = con $ M.basicUnsafeSlice i n v         \
 ; basicOverlaps (con v1) (con v2) = M.basicOverlaps v1 v2               \
 ; basicUnsafeNew n = con `liftM` M.basicUnsafeNew n                     \
-; basicUnsafeNewWith n x = con `liftM` M.basicUnsafeNewWith n x         \
+; basicUnsafeReplicate n x = con `liftM` M.basicUnsafeReplicate n x     \
 ; basicUnsafeRead (con v) i = M.basicUnsafeRead v i                     \
 ; basicUnsafeWrite (con v) i x = M.basicUnsafeWrite v i x               \
 ; basicClear (con v) = M.basicClear v                                   \
@@ -156,12 +159,14 @@
 
 #define primVector(ty,con,mcon)                                         \
 instance G.Vector Vector ty where {                                     \
-  {-# INLINE unsafeFreeze #-}                                           \
+  {-# INLINE basicUnsafeFreeze #-}                                      \
+; {-# INLINE basicUnsafeThaw #-}                                        \
 ; {-# INLINE basicLength #-}                                            \
 ; {-# INLINE basicUnsafeSlice #-}                                       \
 ; {-# INLINE basicUnsafeIndexM #-}                                      \
 ; {-# INLINE elemseq #-}                                                \
-; unsafeFreeze (mcon v) = con `liftM` G.unsafeFreeze v                  \
+; basicUnsafeFreeze (mcon v) = con `liftM` G.basicUnsafeFreeze v        \
+; basicUnsafeThaw (con v) = mcon `liftM` G.basicUnsafeThaw v            \
 ; basicLength (con v) = G.basicLength v                                 \
 ; basicUnsafeSlice i n (con v) = con $ G.basicUnsafeSlice i n v         \
 ; basicUnsafeIndexM (con v) i = G.basicUnsafeIndexM v i                 \
@@ -273,7 +278,7 @@
   {-# INLINE basicUnsafeSlice #-}
   {-# INLINE basicOverlaps #-}
   {-# INLINE basicUnsafeNew #-}
-  {-# INLINE basicUnsafeNewWith #-}
+  {-# INLINE basicUnsafeReplicate #-}
   {-# INLINE basicUnsafeRead #-}
   {-# INLINE basicUnsafeWrite #-}
   {-# INLINE basicClear #-}
@@ -284,7 +289,7 @@
   basicUnsafeSlice i n (MV_Bool v) = MV_Bool $ M.basicUnsafeSlice i n v
   basicOverlaps (MV_Bool v1) (MV_Bool v2) = M.basicOverlaps v1 v2
   basicUnsafeNew n = MV_Bool `liftM` M.basicUnsafeNew n
-  basicUnsafeNewWith n x = MV_Bool `liftM` M.basicUnsafeNewWith n (fromBool x)
+  basicUnsafeReplicate n x = MV_Bool `liftM` M.basicUnsafeReplicate n (fromBool x)
   basicUnsafeRead (MV_Bool v) i = toBool `liftM` M.basicUnsafeRead v i
   basicUnsafeWrite (MV_Bool v) i x = M.basicUnsafeWrite v i (fromBool x)
   basicClear (MV_Bool v) = M.basicClear v
@@ -293,12 +298,14 @@
   basicUnsafeGrow (MV_Bool v) n = MV_Bool `liftM` M.basicUnsafeGrow v n
 
 instance G.Vector Vector Bool where
-  {-# INLINE unsafeFreeze #-}
+  {-# INLINE basicUnsafeFreeze #-}
+  {-# INLINE basicUnsafeThaw #-}
   {-# INLINE basicLength #-}
   {-# INLINE basicUnsafeSlice #-}
   {-# INLINE basicUnsafeIndexM #-}
   {-# INLINE elemseq #-}
-  unsafeFreeze (MV_Bool v) = V_Bool `liftM` G.unsafeFreeze v
+  basicUnsafeFreeze (MV_Bool v) = V_Bool `liftM` G.basicUnsafeFreeze v
+  basicUnsafeThaw (V_Bool v) = MV_Bool `liftM` G.basicUnsafeThaw v
   basicLength (V_Bool v) = G.basicLength v
   basicUnsafeSlice i n (V_Bool v) = V_Bool $ G.basicUnsafeSlice i n v
   basicUnsafeIndexM (V_Bool v) i = toBool `liftM` G.basicUnsafeIndexM v i
@@ -319,7 +326,7 @@
   {-# INLINE basicUnsafeSlice #-}
   {-# INLINE basicOverlaps #-}
   {-# INLINE basicUnsafeNew #-}
-  {-# INLINE basicUnsafeNewWith #-}
+  {-# INLINE basicUnsafeReplicate #-}
   {-# INLINE basicUnsafeRead #-}
   {-# INLINE basicUnsafeWrite #-}
   {-# INLINE basicClear #-}
@@ -330,7 +337,7 @@
   basicUnsafeSlice i n (MV_Complex v) = MV_Complex $ M.basicUnsafeSlice i n v
   basicOverlaps (MV_Complex v1) (MV_Complex v2) = M.basicOverlaps v1 v2
   basicUnsafeNew n = MV_Complex `liftM` M.basicUnsafeNew n
-  basicUnsafeNewWith n (x :+ y) = MV_Complex `liftM` M.basicUnsafeNewWith n (x,y)
+  basicUnsafeReplicate n (x :+ y) = MV_Complex `liftM` M.basicUnsafeReplicate n (x,y)
   basicUnsafeRead (MV_Complex v) i = uncurry (:+) `liftM` M.basicUnsafeRead v i
   basicUnsafeWrite (MV_Complex v) i (x :+ y) = M.basicUnsafeWrite v i (x,y)
   basicClear (MV_Complex v) = M.basicClear v
@@ -339,12 +346,14 @@
   basicUnsafeGrow (MV_Complex v) n = MV_Complex `liftM` M.basicUnsafeGrow v n
 
 instance (RealFloat a, Unbox a) => G.Vector Vector (Complex a) where
-  {-# INLINE unsafeFreeze #-}
+  {-# INLINE basicUnsafeFreeze #-}
+  {-# INLINE basicUnsafeThaw #-}
   {-# INLINE basicLength #-}
   {-# INLINE basicUnsafeSlice #-}
   {-# INLINE basicUnsafeIndexM #-}
   {-# INLINE elemseq #-}
-  unsafeFreeze (MV_Complex v) = V_Complex `liftM` G.unsafeFreeze v
+  basicUnsafeFreeze (MV_Complex v) = V_Complex `liftM` G.basicUnsafeFreeze v
+  basicUnsafeThaw (V_Complex v) = MV_Complex `liftM` G.basicUnsafeThaw v
   basicLength (V_Complex v) = G.basicLength v
   basicUnsafeSlice i n (V_Complex v) = V_Complex $ G.basicUnsafeSlice i n v
   basicUnsafeIndexM (V_Complex v) i
diff --git a/Data/Vector/Unboxed/Mutable.hs b/Data/Vector/Unboxed/Mutable.hs
--- a/Data/Vector/Unboxed/Mutable.hs
+++ b/Data/Vector/Unboxed/Mutable.hs
@@ -14,70 +14,162 @@
   -- * Mutable vectors of primitive types
   MVector(..), IOVector, STVector, Unbox,
 
-  -- * Operations on mutable vectors
-  length, overlaps, slice, new, newWith, read, write, swap,
-  clear, set, copy, grow,
+  -- * Accessors
+
+  -- ** Length information
+  length, null,
+
+  -- ** Extracting subvectors
+  slice, init, tail, take, drop,
+  unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
+
+  -- ** Overlapping
+  overlaps,
+
+  -- * Construction
+
+  -- ** Initialisation
+  new, unsafeNew, replicate, clone,
+
+  -- ** Growing
+  grow, unsafeGrow,
+
+  -- ** Restricting memory usage
+  clear,
+
+  -- * Zipping and unzipping
   zip, zip3, zip4, zip5, zip6,
   unzip, unzip3, unzip4, unzip5, unzip6,
 
-  -- * Unsafe operations
-  unsafeSlice, unsafeNew, unsafeNewWith, unsafeRead, unsafeWrite, unsafeSwap,
-  unsafeCopy, unsafeGrow
+  -- * Accessing individual elements
+  read, write, swap,
+  unsafeRead, unsafeWrite, unsafeSwap,
+
+  -- * Modifying vectors
+
+  -- ** Filling and copying
+  set, copy, unsafeCopy,
+
+  -- * Deprecated operations
+  newWith, unsafeNewWith
+
 ) where
 
 import Data.Vector.Unboxed.Base
 import qualified Data.Vector.Generic.Mutable as G
 import Control.Monad.Primitive
 
-import Prelude hiding ( zip, zip3, unzip, unzip3, length, read )
+import Prelude hiding ( length, null, replicate, reverse, map, read,
+                        take, drop, init, tail,
+                        zip, zip3, unzip, unzip3 )
 
 #include "vector.h"
 
+-- Length information
+-- ------------------
+
+-- | Length of the mutable vector.
+length :: Unbox a => MVector s a -> Int
+{-# INLINE length #-}
+length = G.length
+
+-- | Check whether the vector is empty
+null :: Unbox a => MVector s a -> Bool
+{-# INLINE null #-}
+null = G.null
+
+-- Extracting subvectors
+-- ---------------------
+
+-- | Yield a part of the mutable vector without copying it.
+slice :: Unbox a => Int -> Int -> MVector s a -> MVector s a
+{-# INLINE slice #-}
+slice = G.slice
+
+take :: Unbox a => Int -> MVector s a -> MVector s a
+{-# INLINE take #-}
+take = G.take
+
+drop :: Unbox a => Int -> MVector s a -> MVector s a
+{-# INLINE drop #-}
+drop = G.drop
+
+init :: Unbox a => MVector s a -> MVector s a
+{-# INLINE init #-}
+init = G.init
+
+tail :: Unbox a => MVector s a -> MVector s a
+{-# INLINE tail #-}
+tail = G.tail
+
 -- | Yield a part of the mutable vector without copying it. No bounds checks
 -- are performed.
-unsafeSlice :: Unbox a => Int  -- ^ starting index
-                       -> Int  -- ^ length of the slice
-                       -> MVector s a
-                       -> MVector s a
+unsafeSlice :: Unbox a
+            => Int  -- ^ starting index
+            -> Int  -- ^ length of the slice
+            -> MVector s a
+            -> MVector s a
 {-# INLINE unsafeSlice #-}
 unsafeSlice = G.unsafeSlice
 
+unsafeTake :: Unbox a => Int -> MVector s a -> MVector s a
+{-# INLINE unsafeTake #-}
+unsafeTake = G.unsafeTake
+
+unsafeDrop :: Unbox a => Int -> MVector s a -> MVector s a
+{-# INLINE unsafeDrop #-}
+unsafeDrop = G.unsafeDrop
+
+unsafeInit :: Unbox a => MVector s a -> MVector s a
+{-# INLINE unsafeInit #-}
+unsafeInit = G.unsafeInit
+
+unsafeTail :: Unbox a => MVector s a -> MVector s a
+{-# INLINE unsafeTail #-}
+unsafeTail = G.unsafeTail
+
+-- Overlapping
+-- -----------
+
+-- Check whether two vectors overlap.
+overlaps :: Unbox a => MVector s a -> MVector s a -> Bool
+{-# INLINE overlaps #-}
+overlaps = G.overlaps
+
+-- Initialisation
+-- --------------
+
+-- | Create a mutable vector of the given length.
+new :: (PrimMonad m, Unbox a) => Int -> m (MVector (PrimState m) a)
+{-# INLINE new #-}
+new = G.new
+
 -- | Create a mutable vector of the given length. The length is not checked.
 unsafeNew :: (PrimMonad m, Unbox a) => Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeNew #-}
 unsafeNew = G.unsafeNew
 
--- | Create a mutable vector of the given length and fill it with an
--- initial value. The length is not checked.
-unsafeNewWith :: (PrimMonad m, Unbox a)
-                                => Int -> a -> m (MVector (PrimState m) a)
-{-# INLINE unsafeNewWith #-}
-unsafeNewWith = G.unsafeNewWith
-
--- | Yield the element at the given position. No bounds checks are performed.
-unsafeRead :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> m a
-{-# INLINE unsafeRead #-}
-unsafeRead = G.unsafeRead
+-- | Create a mutable vector of the given length (0 if the length is negative)
+-- and fill it with an initial value.
+replicate :: (PrimMonad m, Unbox a) => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE replicate #-}
+replicate = G.replicate
 
--- | Replace the element at the given position. No bounds checks are performed.
-unsafeWrite :: (PrimMonad m, Unbox a)
-                                => MVector (PrimState m) a -> Int -> a -> m ()
-{-# INLINE unsafeWrite #-}
-unsafeWrite = G.unsafeWrite
+-- | Create a copy of a mutable vector.
+clone :: (PrimMonad m, Unbox a)
+      => MVector (PrimState m) a -> m (MVector (PrimState m) a)
+{-# INLINE clone #-}
+clone = G.clone
 
--- | Swap the elements at the given positions. No bounds checks are performed.
-unsafeSwap :: (PrimMonad m, Unbox a)
-                => MVector (PrimState m) a -> Int -> Int -> m ()
-{-# INLINE unsafeSwap #-}
-unsafeSwap = G.unsafeSwap
+-- Growing
+-- -------
 
--- | Copy a vector. The two vectors must have the same length and may not
--- overlap. This is not checked.
-unsafeCopy :: (PrimMonad m, Unbox a) => MVector (PrimState m) a   -- ^ target
-                                    -> MVector (PrimState m) a   -- ^ source
-                                    -> m ()
-{-# INLINE unsafeCopy #-}
-unsafeCopy = G.unsafeCopy
+-- | Grow a vector by the given number of elements. The number must be
+-- positive.
+grow :: (PrimMonad m, Unbox a)  
+              => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
+{-# INLINE grow #-}
+grow = G.grow
 
 -- | Grow a vector by the given number of elements. The number must be
 -- positive but this is not checked.
@@ -86,31 +178,17 @@
 {-# INLINE unsafeGrow #-}
 unsafeGrow = G.unsafeGrow
 
--- | Length of the mutable vector.
-length :: Unbox a => MVector s a -> Int
-{-# INLINE length #-}
-length = G.length
-
--- Check whether two vectors overlap.
-overlaps :: Unbox a => MVector s a -> MVector s a -> Bool
-{-# INLINE overlaps #-}
-overlaps = G.overlaps
-
--- | Yield a part of the mutable vector without copying it.
-slice :: Unbox a => Int -> Int -> MVector s a -> MVector s a
-{-# INLINE slice #-}
-slice = G.slice
+-- Restricting memory usage
+-- ------------------------
 
--- | Create a mutable vector of the given length.
-new :: (PrimMonad m, Unbox a) => Int -> m (MVector (PrimState m) a)
-{-# INLINE new #-}
-new = G.new
+-- | Reset all elements of the vector to some undefined value, clearing all
+-- references to external objects. This is usually a noop for unboxed vectors. 
+clear :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> m ()
+{-# INLINE clear #-}
+clear = G.clear
 
--- | Create a mutable vector of the given length and fill it with an
--- initial value.
-newWith :: (PrimMonad m, Unbox a) => Int -> a -> m (MVector (PrimState m) a)
-{-# INLINE newWith #-}
-newWith = G.newWith
+-- Accessing individual elements
+-- -----------------------------
 
 -- | Yield the element at the given position.
 read :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> m a
@@ -123,17 +201,31 @@
 write = G.write
 
 -- | Swap the elements at the given positions.
-swap :: (PrimMonad m, Unbox a)
-                => MVector (PrimState m) a -> Int -> Int -> m ()
+swap :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> Int -> m ()
 {-# INLINE swap #-}
 swap = G.swap
 
--- | Reset all elements of the vector to some undefined value, clearing all
--- references to external objects. This is usually a noop for unboxed vectors. 
-clear :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> m ()
-{-# INLINE clear #-}
-clear = G.clear
 
+-- | Yield the element at the given position. No bounds checks are performed.
+unsafeRead :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> m a
+{-# INLINE unsafeRead #-}
+unsafeRead = G.unsafeRead
+
+-- | Replace the element at the given position. No bounds checks are performed.
+unsafeWrite
+    :: (PrimMonad m, Unbox a) =>  MVector (PrimState m) a -> Int -> a -> m ()
+{-# INLINE unsafeWrite #-}
+unsafeWrite = G.unsafeWrite
+
+-- | Swap the elements at the given positions. No bounds checks are performed.
+unsafeSwap
+    :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> Int -> m ()
+{-# INLINE unsafeSwap #-}
+unsafeSwap = G.unsafeSwap
+
+-- Filling and copying
+-- -------------------
+
 -- | Set all elements of the vector to the given value.
 set :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> a -> m ()
 {-# INLINE set #-}
@@ -141,17 +233,34 @@
 
 -- | Copy a vector. The two vectors must have the same length and may not
 -- overlap.
-copy :: (PrimMonad m, Unbox a)
-                => MVector (PrimState m) a -> MVector (PrimState m) a -> m ()
+copy :: (PrimMonad m, Unbox a) 
+                 => MVector (PrimState m) a -> MVector (PrimState m) a -> m ()
 {-# INLINE copy #-}
 copy = G.copy
 
--- | Grow a vector by the given number of elements. The number must be
--- positive.
-grow :: (PrimMonad m, Unbox a)
-              => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
-{-# INLINE grow #-}
-grow = G.grow
+-- | Copy a vector. The two vectors must have the same length and may not
+-- overlap. This is not checked.
+unsafeCopy :: (PrimMonad m, Unbox a)
+           => MVector (PrimState m) a   -- ^ target
+           -> MVector (PrimState m) a   -- ^ source
+           -> m ()
+{-# INLINE unsafeCopy #-}
+unsafeCopy = G.unsafeCopy
+
+-- Deprecated functions
+-- --------------------
+
+-- | /DEPRECATED/ Use 'replicate' instead
+newWith :: (PrimMonad m, Unbox a) => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE newWith #-}
+newWith = G.replicate
+
+-- | /DEPRECATED/ Use 'replicate' instead
+unsafeNewWith :: (PrimMonad m, Unbox a) => Int -> a -> m (MVector (PrimState m) a)
+{-# INLINE unsafeNewWith #-}
+unsafeNewWith = G.replicate
+
+{-# DEPRECATED newWith, unsafeNewWith "Use replicate instead" #-}
 
 #define DEFINE_MUTABLE
 #include "unbox-tuple-instances"
diff --git a/benchmarks/Algo/Tridiag.hs b/benchmarks/Algo/Tridiag.hs
--- a/benchmarks/Algo/Tridiag.hs
+++ b/benchmarks/Algo/Tridiag.hs
@@ -5,16 +5,12 @@
 tridiag :: (Vector Double, Vector Double, Vector Double, Vector Double)
             -> Vector Double
 {-# NOINLINE tridiag #-}
-tridiag (as,bs,cs,ds) = xs
+tridiag (as,bs,cs,ds) = V.prescanr' (\(c,d) x' -> d - c*x') 0
+                      $ V.prescanl' modify (0,0)
+                      $ V.zip (V.zip as bs) (V.zip cs ds)
     where
-      (cs',ds') = V.unzip
-                $ V.prescanl' modify (0,0)
-                $ V.zip (V.zip as bs) (V.zip cs ds)
-
       modify (c',d') ((a,b),(c,d)) = 
                    let id = 1 / (b - c'*a)
                    in
                    id `seq` (c*id, (d-d'*a)*id)
-
-      xs = V.prescanr' (\(c,d) x' -> d - c*x') 0 (V.zip cs' ds')
 
diff --git a/benchmarks/vector-benchmarks.cabal b/benchmarks/vector-benchmarks.cabal
--- a/benchmarks/vector-benchmarks.cabal
+++ b/benchmarks/vector-benchmarks.cabal
@@ -1,5 +1,5 @@
 Name:           vector-benchmarks
-Version:        0.6.0.1
+Version:        0.7
 License:        BSD3
 License-File:   LICENSE
 Author:         Roman Leshchinskiy <rl@cse.unsw.edu.au>
@@ -13,13 +13,13 @@
 
   Build-Depends: base >= 2 && < 5, array,
                  criterion >= 0.5 && < 0.6,
-                 mwc-random >= 0.5 && < 0.6,
-                 vector == 0.6.0.1
+                 mwc-random >= 0.5 && < 0.8,
+                 vector == 0.7
 
   if impl(ghc<6.13)
-    Ghc-Options: -finline-if-enough-args -fno-method-sharing
+    Ghc-Options: -finline-if-enough-args
   
-  Ghc-Options: -O2
+  Ghc-Options: -O2 -fno-method-sharing
 
   Other-Modules:
         Algo.ListRank
diff --git a/internal/GenUnboxTuple.hs b/internal/GenUnboxTuple.hs
--- a/internal/GenUnboxTuple.hs
+++ b/internal/GenUnboxTuple.hs
@@ -135,7 +135,7 @@
          mk_do [v <+> text "<-" <+> qM rec <+> var 'n' | v <- varss]
                $ text "return $" <+> con "MV" <+> var 'n' <+> sep varss)
 
-    gen_unsafeNewWith rec
+    gen_unsafeReplicate rec
       = (var 'n' <+> tuple vars,
          mk_do [vs <+> text "<-" <+> qM rec <+> var 'n' <+> v
                         | v  <- vars | vs <- varss]
@@ -178,6 +178,12 @@
                $ text "return $" <+> con "V" <+> var 'n'
                                  <+> sep [vs <> char '\'' | vs <- varss])
 
+    gen_unsafeThaw rec
+      = (pat "V",
+         mk_do [vs <> char '\'' <+> text "<-" <+> qG rec <+> vs | vs <- varss]
+               $ text "return $" <+> con "MV" <+> var 'n'
+                                 <+> sep [vs <> char '\'' | vs <- varss])
+
     gen_basicUnsafeIndexM rec
       = (pat "V" <+> var 'i',
          mk_do [v <+> text "<-" <+> qG rec <+> vs <+> var 'i'
@@ -206,7 +212,7 @@
                       ,("basicUnsafeSlice",       gen_unsafeSlice "M" "MV")
                       ,("basicOverlaps",          gen_overlaps)
                       ,("basicUnsafeNew",         gen_unsafeNew)
-                      ,("basicUnsafeNewWith",     gen_unsafeNewWith)
+                      ,("basicUnsafeReplicate",   gen_unsafeReplicate)
                       ,("basicUnsafeRead",        gen_unsafeRead)
                       ,("basicUnsafeWrite",       gen_unsafeWrite)
                       ,("basicClear",             gen_clear)
@@ -214,7 +220,8 @@
                       ,("basicUnsafeCopy",        gen_unsafeCopy "MV" qM)
                       ,("basicUnsafeGrow",        gen_unsafeGrow)]
 
-    methods_Vector  = [("unsafeFreeze",           gen_unsafeFreeze)
+    methods_Vector  = [("basicUnsafeFreeze",      gen_unsafeFreeze)
+                      ,("basicUnsafeThaw",        gen_unsafeThaw)
                       ,("basicLength",            gen_length "V")
                       ,("basicUnsafeSlice",       gen_unsafeSlice "G" "V")
                       ,("basicUnsafeIndexM",      gen_basicUnsafeIndexM)
diff --git a/internal/unbox-tuple-instances b/internal/unbox-tuple-instances
--- a/internal/unbox-tuple-instances
+++ b/internal/unbox-tuple-instances
@@ -23,11 +23,11 @@
           as <- M.basicUnsafeNew n_
           bs <- M.basicUnsafeNew n_
           return $ MV_2 n_ as bs
-  {-# INLINE basicUnsafeNewWith  #-}
-  basicUnsafeNewWith n_ (a, b)
+  {-# INLINE basicUnsafeReplicate  #-}
+  basicUnsafeReplicate n_ (a, b)
       = do
-          as <- M.basicUnsafeNewWith n_ a
-          bs <- M.basicUnsafeNewWith n_ b
+          as <- M.basicUnsafeReplicate n_ a
+          bs <- M.basicUnsafeReplicate n_ b
           return $ MV_2 n_ as bs
   {-# INLINE basicUnsafeRead  #-}
   basicUnsafeRead (MV_2 n_ as bs) i_
@@ -62,12 +62,18 @@
           bs' <- M.basicUnsafeGrow bs m_
           return $ MV_2 (m_+n_) as' bs'
 instance (Unbox a, Unbox b) => G.Vector Vector (a, b) where
-  {-# INLINE unsafeFreeze  #-}
-  unsafeFreeze (MV_2 n_ as bs)
+  {-# INLINE basicUnsafeFreeze  #-}
+  basicUnsafeFreeze (MV_2 n_ as bs)
       = do
-          as' <- G.unsafeFreeze as
-          bs' <- G.unsafeFreeze bs
+          as' <- G.basicUnsafeFreeze as
+          bs' <- G.basicUnsafeFreeze bs
           return $ V_2 n_ as' bs'
+  {-# INLINE basicUnsafeThaw  #-}
+  basicUnsafeThaw (V_2 n_ as bs)
+      = do
+          as' <- G.basicUnsafeThaw as
+          bs' <- G.basicUnsafeThaw bs
+          return $ MV_2 n_ as' bs'
   {-# INLINE basicLength  #-}
   basicLength (V_2 n_ as bs) = n_
   {-# INLINE basicUnsafeSlice  #-}
@@ -151,12 +157,12 @@
           bs <- M.basicUnsafeNew n_
           cs <- M.basicUnsafeNew n_
           return $ MV_3 n_ as bs cs
-  {-# INLINE basicUnsafeNewWith  #-}
-  basicUnsafeNewWith n_ (a, b, c)
+  {-# INLINE basicUnsafeReplicate  #-}
+  basicUnsafeReplicate n_ (a, b, c)
       = do
-          as <- M.basicUnsafeNewWith n_ a
-          bs <- M.basicUnsafeNewWith n_ b
-          cs <- M.basicUnsafeNewWith n_ c
+          as <- M.basicUnsafeReplicate n_ a
+          bs <- M.basicUnsafeReplicate n_ b
+          cs <- M.basicUnsafeReplicate n_ c
           return $ MV_3 n_ as bs cs
   {-# INLINE basicUnsafeRead  #-}
   basicUnsafeRead (MV_3 n_ as bs cs) i_
@@ -199,13 +205,20 @@
 instance (Unbox a,
           Unbox b,
           Unbox c) => G.Vector Vector (a, b, c) where
-  {-# INLINE unsafeFreeze  #-}
-  unsafeFreeze (MV_3 n_ as bs cs)
+  {-# INLINE basicUnsafeFreeze  #-}
+  basicUnsafeFreeze (MV_3 n_ as bs cs)
       = do
-          as' <- G.unsafeFreeze as
-          bs' <- G.unsafeFreeze bs
-          cs' <- G.unsafeFreeze cs
+          as' <- G.basicUnsafeFreeze as
+          bs' <- G.basicUnsafeFreeze bs
+          cs' <- G.basicUnsafeFreeze cs
           return $ V_3 n_ as' bs' cs'
+  {-# INLINE basicUnsafeThaw  #-}
+  basicUnsafeThaw (V_3 n_ as bs cs)
+      = do
+          as' <- G.basicUnsafeThaw as
+          bs' <- G.basicUnsafeThaw bs
+          cs' <- G.basicUnsafeThaw cs
+          return $ MV_3 n_ as' bs' cs'
   {-# INLINE basicLength  #-}
   basicLength (V_3 n_ as bs cs) = n_
   {-# INLINE basicUnsafeSlice  #-}
@@ -311,13 +324,13 @@
           cs <- M.basicUnsafeNew n_
           ds <- M.basicUnsafeNew n_
           return $ MV_4 n_ as bs cs ds
-  {-# INLINE basicUnsafeNewWith  #-}
-  basicUnsafeNewWith n_ (a, b, c, d)
+  {-# INLINE basicUnsafeReplicate  #-}
+  basicUnsafeReplicate n_ (a, b, c, d)
       = do
-          as <- M.basicUnsafeNewWith n_ a
-          bs <- M.basicUnsafeNewWith n_ b
-          cs <- M.basicUnsafeNewWith n_ c
-          ds <- M.basicUnsafeNewWith n_ d
+          as <- M.basicUnsafeReplicate n_ a
+          bs <- M.basicUnsafeReplicate n_ b
+          cs <- M.basicUnsafeReplicate n_ c
+          ds <- M.basicUnsafeReplicate n_ d
           return $ MV_4 n_ as bs cs ds
   {-# INLINE basicUnsafeRead  #-}
   basicUnsafeRead (MV_4 n_ as bs cs ds) i_
@@ -370,14 +383,22 @@
           Unbox b,
           Unbox c,
           Unbox d) => G.Vector Vector (a, b, c, d) where
-  {-# INLINE unsafeFreeze  #-}
-  unsafeFreeze (MV_4 n_ as bs cs ds)
+  {-# INLINE basicUnsafeFreeze  #-}
+  basicUnsafeFreeze (MV_4 n_ as bs cs ds)
       = do
-          as' <- G.unsafeFreeze as
-          bs' <- G.unsafeFreeze bs
-          cs' <- G.unsafeFreeze cs
-          ds' <- G.unsafeFreeze ds
+          as' <- G.basicUnsafeFreeze as
+          bs' <- G.basicUnsafeFreeze bs
+          cs' <- G.basicUnsafeFreeze cs
+          ds' <- G.basicUnsafeFreeze ds
           return $ V_4 n_ as' bs' cs' ds'
+  {-# INLINE basicUnsafeThaw  #-}
+  basicUnsafeThaw (V_4 n_ as bs cs ds)
+      = do
+          as' <- G.basicUnsafeThaw as
+          bs' <- G.basicUnsafeThaw bs
+          cs' <- G.basicUnsafeThaw cs
+          ds' <- G.basicUnsafeThaw ds
+          return $ MV_4 n_ as' bs' cs' ds'
   {-# INLINE basicLength  #-}
   basicLength (V_4 n_ as bs cs ds) = n_
   {-# INLINE basicUnsafeSlice  #-}
@@ -517,14 +538,14 @@
           ds <- M.basicUnsafeNew n_
           es <- M.basicUnsafeNew n_
           return $ MV_5 n_ as bs cs ds es
-  {-# INLINE basicUnsafeNewWith  #-}
-  basicUnsafeNewWith n_ (a, b, c, d, e)
+  {-# INLINE basicUnsafeReplicate  #-}
+  basicUnsafeReplicate n_ (a, b, c, d, e)
       = do
-          as <- M.basicUnsafeNewWith n_ a
-          bs <- M.basicUnsafeNewWith n_ b
-          cs <- M.basicUnsafeNewWith n_ c
-          ds <- M.basicUnsafeNewWith n_ d
-          es <- M.basicUnsafeNewWith n_ e
+          as <- M.basicUnsafeReplicate n_ a
+          bs <- M.basicUnsafeReplicate n_ b
+          cs <- M.basicUnsafeReplicate n_ c
+          ds <- M.basicUnsafeReplicate n_ d
+          es <- M.basicUnsafeReplicate n_ e
           return $ MV_5 n_ as bs cs ds es
   {-# INLINE basicUnsafeRead  #-}
   basicUnsafeRead (MV_5 n_ as bs cs ds es) i_
@@ -585,15 +606,24 @@
           Unbox c,
           Unbox d,
           Unbox e) => G.Vector Vector (a, b, c, d, e) where
-  {-# INLINE unsafeFreeze  #-}
-  unsafeFreeze (MV_5 n_ as bs cs ds es)
+  {-# INLINE basicUnsafeFreeze  #-}
+  basicUnsafeFreeze (MV_5 n_ as bs cs ds es)
       = do
-          as' <- G.unsafeFreeze as
-          bs' <- G.unsafeFreeze bs
-          cs' <- G.unsafeFreeze cs
-          ds' <- G.unsafeFreeze ds
-          es' <- G.unsafeFreeze es
+          as' <- G.basicUnsafeFreeze as
+          bs' <- G.basicUnsafeFreeze bs
+          cs' <- G.basicUnsafeFreeze cs
+          ds' <- G.basicUnsafeFreeze ds
+          es' <- G.basicUnsafeFreeze es
           return $ V_5 n_ as' bs' cs' ds' es'
+  {-# INLINE basicUnsafeThaw  #-}
+  basicUnsafeThaw (V_5 n_ as bs cs ds es)
+      = do
+          as' <- G.basicUnsafeThaw as
+          bs' <- G.basicUnsafeThaw bs
+          cs' <- G.basicUnsafeThaw cs
+          ds' <- G.basicUnsafeThaw ds
+          es' <- G.basicUnsafeThaw es
+          return $ MV_5 n_ as' bs' cs' ds' es'
   {-# INLINE basicLength  #-}
   basicLength (V_5 n_ as bs cs ds es) = n_
   {-# INLINE basicUnsafeSlice  #-}
@@ -775,15 +805,15 @@
           es <- M.basicUnsafeNew n_
           fs <- M.basicUnsafeNew n_
           return $ MV_6 n_ as bs cs ds es fs
-  {-# INLINE basicUnsafeNewWith  #-}
-  basicUnsafeNewWith n_ (a, b, c, d, e, f)
+  {-# INLINE basicUnsafeReplicate  #-}
+  basicUnsafeReplicate n_ (a, b, c, d, e, f)
       = do
-          as <- M.basicUnsafeNewWith n_ a
-          bs <- M.basicUnsafeNewWith n_ b
-          cs <- M.basicUnsafeNewWith n_ c
-          ds <- M.basicUnsafeNewWith n_ d
-          es <- M.basicUnsafeNewWith n_ e
-          fs <- M.basicUnsafeNewWith n_ f
+          as <- M.basicUnsafeReplicate n_ a
+          bs <- M.basicUnsafeReplicate n_ b
+          cs <- M.basicUnsafeReplicate n_ c
+          ds <- M.basicUnsafeReplicate n_ d
+          es <- M.basicUnsafeReplicate n_ e
+          fs <- M.basicUnsafeReplicate n_ f
           return $ MV_6 n_ as bs cs ds es fs
   {-# INLINE basicUnsafeRead  #-}
   basicUnsafeRead (MV_6 n_ as bs cs ds es fs) i_
@@ -852,16 +882,26 @@
           Unbox d,
           Unbox e,
           Unbox f) => G.Vector Vector (a, b, c, d, e, f) where
-  {-# INLINE unsafeFreeze  #-}
-  unsafeFreeze (MV_6 n_ as bs cs ds es fs)
+  {-# INLINE basicUnsafeFreeze  #-}
+  basicUnsafeFreeze (MV_6 n_ as bs cs ds es fs)
       = do
-          as' <- G.unsafeFreeze as
-          bs' <- G.unsafeFreeze bs
-          cs' <- G.unsafeFreeze cs
-          ds' <- G.unsafeFreeze ds
-          es' <- G.unsafeFreeze es
-          fs' <- G.unsafeFreeze fs
+          as' <- G.basicUnsafeFreeze as
+          bs' <- G.basicUnsafeFreeze bs
+          cs' <- G.basicUnsafeFreeze cs
+          ds' <- G.basicUnsafeFreeze ds
+          es' <- G.basicUnsafeFreeze es
+          fs' <- G.basicUnsafeFreeze fs
           return $ V_6 n_ as' bs' cs' ds' es' fs'
+  {-# INLINE basicUnsafeThaw  #-}
+  basicUnsafeThaw (V_6 n_ as bs cs ds es fs)
+      = do
+          as' <- G.basicUnsafeThaw as
+          bs' <- G.basicUnsafeThaw bs
+          cs' <- G.basicUnsafeThaw cs
+          ds' <- G.basicUnsafeThaw ds
+          es' <- G.basicUnsafeThaw es
+          fs' <- G.basicUnsafeThaw fs
+          return $ MV_6 n_ as' bs' cs' ds' es' fs'
   {-# INLINE basicLength  #-}
   basicLength (V_6 n_ as bs cs ds es fs) = n_
   {-# INLINE basicUnsafeSlice  #-}
diff --git a/vector.cabal b/vector.cabal
--- a/vector.cabal
+++ b/vector.cabal
@@ -1,5 +1,5 @@
 Name:           vector
-Version:        0.6.0.2
+Version:        0.7
 License:        BSD3
 License-File:   LICENSE
 Author:         Roman Leshchinskiy <rl@cse.unsw.edu.au>
@@ -38,27 +38,25 @@
         .
         * <http://trac.haskell.org/vector>
         .
-        Changes since version 0.6.0.1
-        .
-        * Workaround for GHC bug #4120
-        .
-        Changes since version 0.6
+        Changes in version 0.7
         .
-        * Improved documentation
+        * New functions for freezing, copying and thawing vectors: @freeze@,
+          @thaw@, @unsafeThaw@ and @clone@
         .
-        Changes since version 0.5
+        * @newWith@ and @newUnsafeWith@ on mutable vectors replaced by
+          @replicate@
         .
-        * More efficient representation of @Storable@ vectors
+        * New function: @concat@
         .
-        * Block copy operations used when possible
+        * New function for safe indexing: @(!?)@
         .
-        * @Typeable@ and @Data@ instances
+        * @Monoid@ instances for all vector types
         .
-        * Monadic combinators (@replicateM@, @mapM@ etc.)
+        * Significant recycling and fusion improvements
         .
-        * Better support for recycling (see @create@ and @modify@)
+        * Bug fixes
         .
-        * Performance improvements
+        * Support for GHC 7.0
         .
 
 Cabal-Version:  >= 1.2.3
@@ -142,7 +140,7 @@
   Install-Includes:
         vector.h
 
-  Build-Depends: base >= 4 && < 5, ghc >= 6.9, primitive >= 0.3 && < 0.4
+  Build-Depends: base >= 4 && < 5, ghc >= 6.9, primitive >= 0.3.1 && < 0.4
 
   if impl(ghc<6.13)
     Ghc-Options: -finline-if-enough-args -fno-method-sharing
