diff --git a/Data/Vector.hs b/Data/Vector.hs
--- a/Data/Vector.hs
+++ b/Data/Vector.hs
@@ -47,7 +47,7 @@
   unsafeIndexM, unsafeHeadM, unsafeLastM,
 
   -- ** Extracting subvectors (slicing)
-  slice, init, tail, take, drop, splitAt,
+  slice, init, tail, take, drop, splitAt, uncons, unsnoc,
   unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
 
   -- * Construction
@@ -59,8 +59,8 @@
   replicateM, generateM, iterateNM, create, createT,
 
   -- ** Unfolding
-  unfoldr, unfoldrN,
-  unfoldrM, unfoldrNM,
+  unfoldr, unfoldrN, unfoldrExactN,
+  unfoldrM, unfoldrNM, unfoldrExactNM,
   constructN, constructrN,
 
   -- ** Enumeration
@@ -98,6 +98,7 @@
 
   -- ** Monadic mapping
   mapM, imapM, mapM_, imapM_, forM, forM_,
+  iforM, iforM_,
 
   -- ** Zipping
   zipWith, zipWith3, zipWith4, zipWith5, zipWith6,
@@ -113,9 +114,10 @@
   -- * Working with predicates
 
   -- ** Filtering
-  filter, ifilter, uniq,
+  filter, ifilter, filterM, uniq,
   mapMaybe, imapMaybe,
-  filterM,
+  mapMaybeM, imapMaybeM,
+  catMaybes,
   takeWhile, dropWhile,
 
   -- ** Partitioning
@@ -127,6 +129,7 @@
   -- * Folding
   foldl, foldl1, foldl', foldl1', foldr, foldr1, foldr', foldr1',
   ifoldl, ifoldl', ifoldr, ifoldr',
+  foldMap, foldMap',
 
   -- ** Specialised folds
   all, any, and, or,
@@ -152,11 +155,17 @@
   scanr, scanr', scanr1, scanr1',
   iscanr, iscanr',
 
+  -- ** Comparisons
+  eqBy, cmpBy,
+
   -- * Conversions
 
   -- ** Lists
   toList, Data.Vector.fromList, Data.Vector.fromListN,
 
+  -- ** Arrays
+  fromArray, toArray,
+
   -- ** Other vector types
   G.convert,
 
@@ -176,11 +185,12 @@
                        )
 
 import Control.Monad ( MonadPlus(..), liftM, ap )
-import Control.Monad.ST ( ST )
+import Control.Monad.ST ( ST, runST )
 import Control.Monad.Primitive
 import qualified Control.Monad.Fail as Fail
-
+import Control.Monad.Fix ( MonadFix (mfix) )
 import Control.Monad.Zip
+import Data.Function ( fix )
 
 import Prelude hiding ( length, null,
                         replicate, (++), concat,
@@ -191,6 +201,9 @@
                         filter, takeWhile, dropWhile, span, break,
                         elem, notElem,
                         foldl, foldl1, foldr, foldr1,
+#if __GLASGOW_HASKELL__ >= 706
+                        foldMap,
+#endif
                         all, any, and, or, sum, product, minimum, maximum,
                         scanl, scanl1, scanr, scanr1,
                         enumFromTo, enumFromThenTo,
@@ -347,6 +360,11 @@
   {-# INLINE fmap #-}
   fmap = map
 
+#if MIN_VERSION_base(4,8,0)
+  {-# INLINE (<$) #-}
+  (<$) = map . const
+#endif
+
 instance Monad Vector where
   {-# INLINE return #-}
   return = Applicative.pure
@@ -381,6 +399,29 @@
   {-# INLINE munzip #-}
   munzip = unzip
 
+-- | Instance has same semantics as one for lists
+--
+--  @since 0.12.2.0
+instance MonadFix Vector where
+  -- We take care to dispose of v0 as soon as possible (see headM docs).
+  --
+  -- It's perfectly safe to use non-monadic indexing within generate
+  -- call since intermediate vector won't be created until result's
+  -- value is demanded.
+  {-# INLINE mfix #-}
+  mfix f
+    | null v0 = empty
+    -- We take first element of resulting vector from v0 and create
+    -- rest using generate. Note that cons should fuse with generate
+    | otherwise = runST $ do
+        h <- headM v0
+        return $ cons h $
+          generate (lv0 - 1) $
+            \i -> fix (\a -> f a ! (i + 1))
+    where
+      -- Used to calculate size of resulting vector
+      v0 = fix (f . head)
+      !lv0 = length v0
 
 instance Applicative.Applicative Vector where
   {-# INLINE pure #-}
@@ -605,10 +646,26 @@
 --
 -- Note that @'splitAt' n v@ is equivalent to @('take' n v, 'drop' n v)@
 -- but slightly more efficient.
-{-# INLINE splitAt #-}
+--
+-- @since 0.7.1
 splitAt :: Int -> Vector a -> (Vector a, Vector a)
+{-# INLINE splitAt #-}
 splitAt = G.splitAt
 
+-- | /O(1)/ Yield the 'head' and 'tail' of the vector, or 'Nothing' if empty.
+--
+-- @since 0.12.2.0
+uncons :: Vector a -> Maybe (a, Vector a)
+{-# INLINE uncons #-}
+uncons = G.uncons
+
+-- | /O(1)/ Yield the 'last' and 'init' of the vector, or 'Nothing' if empty.
+--
+-- @since 0.12.2.0
+unsnoc :: Vector a -> Maybe (Vector a, a)
+{-# INLINE unsnoc #-}
+unsnoc = G.unsnoc
+
 -- | /O(1)/ Yield a slice of the vector without copying. The vector must
 -- contain at least @i+n@ elements but this is not checked.
 unsafeSlice :: Int   -- ^ @i@ starting index
@@ -666,7 +723,21 @@
 {-# INLINE generate #-}
 generate = G.generate
 
--- | /O(n)/ Apply function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply function \(\max(n - 1, 0)\) times to an initial value, producing a vector
+-- of length \(\max(n, 0)\). Zeroth element will contain the initial value, that's why there
+-- is one less function application than the number of elements in the produced vector.
+--
+-- \( \underbrace{x, f (x), f (f (x)), \ldots}_{\max(0,n)\rm{~elements}} \)
+--
+-- ===__Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.iterateN 0 undefined undefined :: V.Vector String
+-- []
+-- >>> V.iterateN 4 (\x -> x <> x) "Hi"
+-- ["Hi","HiHi","HiHiHiHi","HiHiHiHiHiHiHiHi"]
+--
+-- @since 0.7.1
 iterateN :: Int -> (a -> a) -> a -> Vector a
 {-# INLINE iterateN #-}
 iterateN = G.iterateN
@@ -693,6 +764,17 @@
 {-# INLINE unfoldrN #-}
 unfoldrN = G.unfoldrN
 
+-- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly applying
+-- the generator function to a seed. The generator function yields the
+-- next element and the new seed.
+--
+-- > unfoldrExactN 3 (\n -> (n,n-1)) 10 = <10,9,8>
+--
+-- @since 0.12.2.0
+unfoldrExactN  :: Int -> (b -> (a, b)) -> b -> Vector a
+{-# INLINE unfoldrExactN #-}
+unfoldrExactN = G.unfoldrExactN
+
 -- | /O(n)/ Construct a vector by repeatedly applying the monadic
 -- generator function to a seed. The generator function yields 'Just'
 -- the next element and the new seed or 'Nothing' if there are no more
@@ -709,6 +791,15 @@
 {-# INLINE unfoldrNM #-}
 unfoldrNM = G.unfoldrNM
 
+-- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly
+-- applying the monadic generator function to a seed. The generator
+-- function yields the next element and the new seed.
+--
+-- @since 0.12.2.0
+unfoldrExactNM :: (Monad m) => Int -> (b -> m (a, b)) -> b -> m (Vector a)
+{-# INLINE unfoldrExactNM #-}
+unfoldrExactNM = G.unfoldrExactNM
+
 -- | /O(n)/ Construct a vector with @n@ elements by repeatedly applying the
 -- generator function to the already constructed part of the vector.
 --
@@ -802,7 +893,13 @@
 {-# INLINE generateM #-}
 generateM = G.generateM
 
--- | /O(n)/ Apply monadic function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply monadic function \(\max(n - 1, 0)\) times to an initial value, producing a vector
+-- of length \(\max(n, 0)\). Zeroth element will contain the initial value, that's why there
+-- is one less function application than the number of elements in the produced vector.
+--
+-- For non-monadic version see `iterateN`
+--
+-- @since 0.12.0.0
 iterateNM :: Monad m => Int -> (a -> m a) -> a -> m (Vector a)
 {-# INLINE iterateNM #-}
 iterateNM = G.iterateNM
@@ -906,7 +1003,11 @@
 -- | /O(m+n)/ For each pair @(i,b)@ from the list, replace the vector element
 -- @a@ at position @i@ by @f a b@.
 --
--- > accum (+) <5,9,2> [(2,4),(1,6),(0,3),(1,7)] = <5+3, 9+6+7, 2+4>
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.accum (+) (V.fromList [1000.0,2000.0,3000.0]) [(2,4),(1,6),(0,3),(1,10)]
+-- [1003.0,2016.0,3004.0]
 accum :: (a -> b -> a) -- ^ accumulating function @f@
       -> Vector a      -- ^ initial vector (of length @m@)
       -> [(Int,b)]     -- ^ list of index/value pairs (of length @n@)
@@ -917,7 +1018,11 @@
 -- | /O(m+n)/ For each pair @(i,b)@ from the vector of pairs, replace the vector
 -- element @a@ at position @i@ by @f a b@.
 --
--- > accumulate (+) <5,9,2> <(2,4),(1,6),(0,3),(1,7)> = <5+3, 9+6+7, 2+4>
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.accumulate (+) (V.fromList [1000.0,2000.0,3000.0]) (V.fromList [(2,4),(1,6),(0,3),(1,10)])
+-- [1003.0,2016.0,3004.0]
 accumulate :: (a -> b -> a)  -- ^ accumulating function @f@
             -> Vector a       -- ^ initial vector (of length @m@)
             -> Vector (Int,b) -- ^ vector of index/value pairs (of length @n@)
@@ -1063,6 +1168,22 @@
 {-# INLINE forM_ #-}
 forM_ = G.forM_
 
+-- | /O(n)/ Apply the monadic action to all elements of the vector and their indices, yielding a
+-- vector of results. Equivalent to 'flip' 'imapM'.
+--
+-- @since 0.12.2.0
+iforM :: Monad m => Vector a -> (Int -> a -> m b) -> m (Vector b)
+{-# INLINE iforM #-}
+iforM = G.iforM
+
+-- | /O(n)/ Apply the monadic action to all elements of the vector and their indices and ignore the
+-- results. Equivalent to 'flip' 'imapM_'.
+--
+-- @since 0.12.2.0
+iforM_ :: Monad m => Vector a -> (Int -> a -> m b) -> m ()
+{-# INLINE iforM_ #-}
+iforM_ = G.iforM_
+
 -- Zipping
 -- -------
 
@@ -1229,13 +1350,37 @@
 {-# INLINE imapMaybe #-}
 imapMaybe = G.imapMaybe
 
+-- | /O(n)/ Return a Vector of all the `Just` values.
+--
+-- @since 0.12.2.0
+catMaybes :: Vector (Maybe a) -> Vector a
+{-# INLINE catMaybes #-}
+catMaybes = mapMaybe id
+
 -- | /O(n)/ Drop elements that do not satisfy the monadic predicate
 filterM :: Monad m => (a -> m Bool) -> Vector a -> m (Vector a)
 {-# INLINE filterM #-}
 filterM = G.filterM
 
--- | /O(n)/ Yield the longest prefix of elements satisfying the predicate
--- without copying.
+-- | /O(n)/ Apply monadic function to each element of vector and
+-- discard elements returning Nothing.
+--
+-- @since 0.12.2.0
+mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Vector a -> m (Vector b)
+{-# INLINE mapMaybeM #-}
+mapMaybeM = G.mapMaybeM
+
+-- | /O(n)/ Apply monadic function to each element of vector and its index.
+-- Discards elements returning Nothing.
+--
+-- @since 0.12.2.0
+imapMaybeM :: Monad m => (Int -> a -> m (Maybe b)) -> Vector a -> m (Vector b)
+{-# INLINE imapMaybeM #-}
+imapMaybeM = G.imapMaybeM
+
+-- | /O(n)/ Yield the longest prefix of elements satisfying the predicate.
+-- Current implementation is not copy-free, unless the result vector is
+-- fused away.
 takeWhile :: (a -> Bool) -> Vector a -> Vector a
 {-# INLINE takeWhile #-}
 takeWhile = G.takeWhile
@@ -1265,11 +1410,11 @@
 {-# INLINE unstablePartition #-}
 unstablePartition = G.unstablePartition
 
--- | /O(n)/ Split the vector in two parts, the first one containing the
---   @Right@ elements and the second containing the @Left@ elements.
---   The relative order of the elements is preserved.
+-- | /O(n)/ Split the vector into two parts, the first one containing the
+-- @`Left`@ elements and the second containing the @`Right`@ elements.
+-- The relative order of the elements is preserved.
 --
---   @since 0.12.1.0
+-- @since 0.12.1.0
 partitionWith :: (a -> Either b c) -> Vector a -> (Vector b, Vector c)
 {-# INLINE partitionWith #-}
 partitionWith = G.partitionWith
@@ -1397,41 +1542,121 @@
 {-# INLINE ifoldr' #-}
 ifoldr' = G.ifoldr'
 
+-- | /O(n)/ Map each element of the structure to a monoid, and combine
+-- the results. It uses same implementation as corresponding method of
+-- 'Foldable' type cless. Note it's implemented in terms of 'foldr'
+-- and won't fuse with functions that traverse vector from left to
+-- right ('map', 'generate', etc.).
+--
+-- @since 0.12.2.0
+foldMap :: (Monoid m) => (a -> m) -> Vector a -> m
+{-# INLINE foldMap #-}
+foldMap = G.foldMap
+
+-- | /O(n)/ 'foldMap' which is strict in accumulator. It uses same
+-- implementation as corresponding method of 'Foldable' type class.
+-- Note it's implemented in terms of 'foldl'' so it fuses in most
+-- contexts.
+--
+-- @since 0.12.2.0
+foldMap' :: (Monoid m) => (a -> m) -> Vector a -> m
+{-# INLINE foldMap' #-}
+foldMap' = G.foldMap'
+
+
 -- Specialised folds
 -- -----------------
 
 -- | /O(n)/ Check if all elements satisfy the predicate.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.all even $ V.fromList [2, 4, 12 :: Int]
+-- True
+-- >>> V.all even $ V.fromList [2, 4, 13 :: Int]
+-- False
+-- >>> V.all even (V.empty :: V.Vector Int)
+-- True
 all :: (a -> Bool) -> Vector a -> Bool
 {-# INLINE all #-}
 all = G.all
 
 -- | /O(n)/ Check if any element satisfies the predicate.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.any even $ V.fromList [1, 3, 7 :: Int]
+-- False
+-- >>> V.any even $ V.fromList [3, 2, 13 :: Int]
+-- True
+-- >>> V.any even (V.empty :: V.Vector Int)
+-- False
 any :: (a -> Bool) -> Vector a -> Bool
 {-# INLINE any #-}
 any = G.any
 
 -- | /O(n)/ Check if all elements are 'True'
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.and $ V.fromList [True, False]
+-- False
+-- >>> V.and V.empty
+-- True
 and :: Vector Bool -> Bool
 {-# INLINE and #-}
 and = G.and
 
 -- | /O(n)/ Check if any element is 'True'
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.or $ V.fromList [True, False]
+-- True
+-- >>> V.or V.empty
+-- False
 or :: Vector Bool -> Bool
 {-# INLINE or #-}
 or = G.or
 
 -- | /O(n)/ Compute the sum of the elements
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.sum $ V.fromList [300,20,1 :: Int]
+-- 321
+-- >>> V.sum (V.empty :: V.Vector Int)
+-- 0
 sum :: Num a => Vector a -> a
 {-# INLINE sum #-}
 sum = G.sum
 
 -- | /O(n)/ Compute the produce of the elements
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.product $ V.fromList [1,2,3,4 :: Int]
+-- 24
+-- >>> V.product (V.empty :: V.Vector Int)
+-- 1
 product :: Num a => Vector a -> a
 {-# INLINE product #-}
 product = G.product
 
 -- | /O(n)/ Yield the maximum element of the vector. The vector may not be
 -- empty.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.maximum $ V.fromList [2.0, 1.0]
+-- 2.0
 maximum :: Ord a => Vector a -> a
 {-# INLINE maximum #-}
 maximum = G.maximum
@@ -1444,6 +1669,12 @@
 
 -- | /O(n)/ Yield the minimum element of the vector. The vector may not be
 -- empty.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.minimum $ V.fromList [2.0, 1.0]
+-- 1.0
 minimum :: Ord a => Vector a -> a
 {-# INLINE minimum #-}
 minimum = G.minimum
@@ -1613,11 +1844,15 @@
 scanl' = G.scanl'
 
 -- | /O(n)/ Scan over a vector with its index
+--
+-- @since 0.12.0.0
 iscanl :: (Int -> a -> b -> a) -> a -> Vector b -> Vector a
 {-# INLINE iscanl #-}
 iscanl = G.iscanl
 
 -- | /O(n)/ Scan over a vector (strictly) with its index
+--
+-- @since 0.12.0.0
 iscanl' :: (Int -> a -> b -> a) -> a -> Vector b -> Vector a
 {-# INLINE iscanl' #-}
 iscanl' = G.iscanl'
@@ -1673,11 +1908,15 @@
 scanr' = G.scanr'
 
 -- | /O(n)/ Right-to-left scan over a vector with its index
+--
+-- @since 0.12.0.0
 iscanr :: (Int -> a -> b -> b) -> b -> Vector a -> Vector b
 {-# INLINE iscanr #-}
 iscanr = G.iscanr
 
 -- | /O(n)/ Right-to-left scan over a vector (strictly) with its index
+--
+-- @since 0.12.0.0
 iscanr' :: (Int -> a -> b -> b) -> b -> Vector a -> Vector b
 {-# INLINE iscanr' #-}
 iscanr' = G.iscanr'
@@ -1693,6 +1932,26 @@
 {-# INLINE scanr1' #-}
 scanr1' = G.scanr1'
 
+-- Comparisons
+-- ------------------------
+
+-- | /O(n)/ Check if two vectors are equal using supplied equality
+-- predicate.
+--
+-- @since 0.12.2.0
+eqBy :: (a -> b -> Bool) -> Vector a -> Vector b -> Bool
+{-# INLINE eqBy #-}
+eqBy = G.eqBy
+
+-- | /O(n)/ Compare two vectors using supplied comparison function for
+-- vector elements. Comparison works same as for lists.
+--
+-- > cmpBy compare == compare
+--
+-- @since 0.12.2.0
+cmpBy :: (a -> b -> Ordering) -> Vector a -> Vector b -> Ordering
+cmpBy = G.cmpBy
+
 -- Conversions - Lists
 -- ------------------------
 
@@ -1714,6 +1973,25 @@
 fromListN :: Int -> [a] -> Vector a
 {-# INLINE fromListN #-}
 fromListN = G.fromListN
+
+-- Conversions - Arrays
+-- -----------------------------
+
+-- | /O(1)/ Convert an array to a vector.
+--
+-- @since 0.12.2.0
+fromArray :: Array a -> Vector a
+{-# INLINE fromArray #-}
+fromArray x = Vector 0 (sizeofArray x) x
+
+-- | /O(n)/ Convert a vector to an array.
+--
+-- @since 0.12.2.0
+toArray :: Vector a -> Array a
+{-# INLINE toArray #-}
+toArray (Vector offset size arr)
+  | offset == 0 && size == sizeofArray arr = arr
+  | otherwise = cloneArray arr offset size
 
 -- Conversions - Mutable vectors
 -- -----------------------------
diff --git a/Data/Vector/Fusion/Bundle.hs b/Data/Vector/Fusion/Bundle.hs
--- a/Data/Vector/Fusion/Bundle.hs
+++ b/Data/Vector/Fusion/Bundle.hs
@@ -55,7 +55,7 @@
   and, or,
 
   -- * Unfolding
-  unfoldr, unfoldrN, iterateN,
+  unfoldr, unfoldrN, unfoldrExactN, iterateN,
 
   -- * Scans
   prescanl, prescanl',
@@ -71,7 +71,7 @@
   fromVector, reVector, fromVectors, concatVectors,
 
   -- * Monadic combinators
-  mapM, mapM_, zipWithM, zipWithM_, filterM, foldM, fold1M, foldM', fold1M',
+  mapM, mapM_, zipWithM, zipWithM_, filterM, mapMaybeM, foldM, fold1M, foldM', fold1M',
 
   eq, cmp, eqBy, cmpBy
 ) where
@@ -80,7 +80,7 @@
 import Data.Vector.Fusion.Bundle.Size
 import Data.Vector.Fusion.Util
 import Data.Vector.Fusion.Stream.Monadic ( Stream(..), Step(..) )
-import Data.Vector.Fusion.Bundle.Monadic ( Chunk(..) )
+import Data.Vector.Fusion.Bundle.Monadic ( Chunk(..), lift )
 import qualified Data.Vector.Fusion.Bundle.Monadic as M
 import qualified Data.Vector.Fusion.Stream.Monadic as S
 
@@ -128,14 +128,6 @@
   inplace f1 g1 (inplace f2 g2 s) = inplace (f1 . f2) (g1 . g2) s   #-}
 
 
-
--- | Convert a pure stream to a monadic stream
-lift :: Monad m => Bundle v a -> M.Bundle m v a
-{-# INLINE_FUSED lift #-}
-lift (M.Bundle (Stream step s) (Stream vstep t) v sz)
-    = M.Bundle (Stream (return . unId . step) s)
-               (Stream (return . unId . vstep) t) v sz
-
 -- | 'Size' hint of a 'Bundle'
 size :: Bundle v a -> Size
 {-# INLINE size #-}
@@ -437,7 +429,15 @@
 {-# INLINE unfoldrN #-}
 unfoldrN = M.unfoldrN
 
--- | Apply function n-1 times to value. Zeroth element is original value.
+-- | Unfold exactly @n@ elements
+--
+-- @since 0.12.2.0
+unfoldrExactN :: Int -> (s -> (a, s)) -> s -> Bundle v a
+{-# INLINE unfoldrExactN #-}
+unfoldrExactN = M.unfoldrExactN
+
+-- | /O(n)/ Apply function \(\max(n - 1, 0)\) times to an initial value, producing a pure
+-- bundle of exact length \(\max(n, 0)\). Zeroth element will contain the initial value.
 iterateN :: Int -> (a -> a) -> a -> Bundle v a
 {-# INLINE iterateN #-}
 iterateN = M.iterateN
@@ -551,6 +551,14 @@
 filterM :: Monad m => (a -> m Bool) -> Bundle v a -> M.Bundle m v a
 {-# INLINE filterM #-}
 filterM f = M.filterM f . lift
+
+-- | /O(n)/ Apply monadic function to each element of a bundle and
+-- discard elements returning Nothing.
+--
+-- @since 0.12.2.0
+mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Bundle v a -> M.Bundle m v b
+{-# INLINE mapMaybeM #-}
+mapMaybeM f = M.mapMaybeM f . lift
 
 -- | Monadic fold
 foldM :: Monad m => (a -> b -> m a) -> a -> Bundle v b -> m a
diff --git a/Data/Vector/Fusion/Bundle/Monadic.hs b/Data/Vector/Fusion/Bundle/Monadic.hs
--- a/Data/Vector/Fusion/Bundle/Monadic.hs
+++ b/Data/Vector/Fusion/Bundle/Monadic.hs
@@ -13,7 +13,7 @@
 --
 
 module Data.Vector.Fusion.Bundle.Monadic (
-  Bundle(..), Chunk(..),
+  Bundle(..), Chunk(..), lift,
 
   -- * Size hints
   size, sized,
@@ -43,7 +43,7 @@
   eqBy, cmpBy,
 
   -- * Filtering
-  filter, filterM, takeWhile, takeWhileM, dropWhile, dropWhileM,
+  filter, filterM, mapMaybeM, takeWhile, takeWhileM, dropWhile, dropWhileM,
 
   -- * Searching
   elem, notElem, find, findM, findIndex, findIndexM,
@@ -59,6 +59,7 @@
   -- * Unfolding
   unfoldr, unfoldrM,
   unfoldrN, unfoldrNM,
+  unfoldrExactN, unfoldrExactNM,
   iterateN, iterateNM,
 
   -- * Scans
@@ -79,7 +80,7 @@
 import Data.Vector.Generic.Base
 import qualified Data.Vector.Generic.Mutable.Base as M
 import Data.Vector.Fusion.Bundle.Size
-import Data.Vector.Fusion.Util ( Box(..), delay_inline )
+import Data.Vector.Fusion.Util ( Box(..), delay_inline, Id(..) )
 import Data.Vector.Fusion.Stream.Monadic ( Stream(..), Step(..) )
 import qualified Data.Vector.Fusion.Stream.Monadic as S
 import Control.Monad.Primitive
@@ -124,6 +125,13 @@
                            , sSize   :: Size
                            }
 
+-- | Convert a pure stream to a monadic stream
+lift :: Monad m => Bundle Id v a -> Bundle m v a
+{-# INLINE_FUSED lift #-}
+lift (Bundle (Stream step s) (Stream vstep t) v sz)
+    = Bundle (Stream (return . unId . step) s)
+             (Stream (return . unId . vstep) t) v sz
+
 fromStream :: Monad m => Stream m a -> Size -> Bundle m v a
 {-# INLINE fromStream #-}
 fromStream (Stream step t) sz = Bundle (Stream step t) (Stream step' t) Nothing sz
@@ -283,6 +291,10 @@
 instance Monad m => Functor (Bundle m v) where
   {-# INLINE fmap #-}
   fmap = map
+#if MIN_VERSION_base(4,8,0)
+  {-# INLINE (<$) #-}
+  (<$) = map . const
+#endif
 
 -- | Map a function over a 'Bundle'
 map :: Monad m => (a -> b) -> Bundle m v a -> Bundle m v b
@@ -334,7 +346,7 @@
 {-# RULES
 
 "zipWithM xs xs [Vector.Bundle]" forall f xs.
-  zipWithM f xs xs = mapM (\x -> f x x) xs   #-}
+  zipWithM f (lift xs) (lift xs) = mapM (\x -> f x x) (lift xs) #-}
 
 
 zipWithM_ :: Monad m => (a -> b -> m c) -> Bundle m v a -> Bundle m v b -> m ()
@@ -454,6 +466,13 @@
 {-# INLINE_FUSED filterM #-}
 filterM f Bundle{sElems = s, sSize = n} = fromStream (S.filterM f s) (toMax n)
 
+-- | Apply monadic function to each element and drop all Nothings
+--
+-- @since 0.12.2.0
+mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Bundle m v a -> Bundle m v b
+{-# INLINE_FUSED mapMaybeM #-}
+mapMaybeM f Bundle{sElems = s, sSize = n} = fromStream (S.mapMaybeM f s) (toMax n)
+
 -- | Longest prefix of elements that satisfy the predicate
 takeWhile :: Monad m => (a -> Bool) -> Bundle m v a -> Bundle m v a
 {-# INLINE takeWhile #-}
@@ -640,17 +659,35 @@
 {-# INLINE_FUSED unfoldrN #-}
 unfoldrN n f = unfoldrNM n (return . f)
 
--- | Unfold at most @n@ elements with a monadic functions
+-- | Unfold at most @n@ elements with a monadic function.
 unfoldrNM :: Monad m => Int -> (s -> m (Maybe (a, s))) -> s -> Bundle m u a
 {-# INLINE_FUSED unfoldrNM #-}
 unfoldrNM n f s = fromStream (S.unfoldrNM n f s) (Max (delay_inline max n 0))
 
--- | Apply monadic function n times to value. Zeroth element is original value.
+-- | Unfold exactly @n@ elements
+--
+-- @since 0.12.2.0
+unfoldrExactN :: Monad m => Int -> (s -> (a, s)) -> s -> Bundle m u a
+{-# INLINE_FUSED unfoldrExactN #-}
+unfoldrExactN n f = unfoldrExactNM n (return . f)
+
+-- | Unfold exactly @n@ elements with a monadic function.
+--
+-- @since 0.12.2.0
+unfoldrExactNM :: Monad m => Int -> (s -> m (a, s)) -> s -> Bundle m u a
+{-# INLINE_FUSED unfoldrExactNM #-}
+unfoldrExactNM n f s = fromStream (S.unfoldrExactNM n f s) (Max (delay_inline max n 0))
+
+-- | /O(n)/ Apply monadic function \(\max(n - 1, 0)\) times to an initial value, producing
+-- a monadic bundle of exact length \(\max(n, 0)\). Zeroth element will contain the initial
+-- value.
 iterateNM :: Monad m => Int -> (a -> m a) -> a -> Bundle m u a
 {-# INLINE_FUSED iterateNM #-}
 iterateNM n f x0 = fromStream (S.iterateNM n f x0) (Exact (delay_inline max n 0))
 
--- | Apply function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply function \(\max(n - 1, 0)\) times to an initial value, producing a
+-- monadic bundle of exact length \(\max(n, 0)\). Zeroth element will contain the initial
+-- value.
 iterateN :: Monad m => Int -> (a -> a) -> a -> Bundle m u a
 {-# INLINE_FUSED iterateN #-}
 iterateN n f x0 = iterateNM n (return . f) x0
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
@@ -40,7 +40,7 @@
   eqBy, cmpBy,
 
   -- * Filtering
-  filter, filterM, uniq, mapMaybe, takeWhile, takeWhileM, dropWhile, dropWhileM,
+  filter, filterM, uniq, mapMaybe, mapMaybeM, catMaybes, takeWhile, takeWhileM, dropWhile, dropWhileM,
 
   -- * Searching
   elem, notElem, find, findM, findIndex, findIndexM,
@@ -56,6 +56,7 @@
   -- * Unfolding
   unfoldr, unfoldrM,
   unfoldrN, unfoldrNM,
+  unfoldrExactN, unfoldrExactNM,
   iterateN, iterateNM,
 
   -- * Scans
@@ -133,6 +134,10 @@
   fmap f (Yield x s) = Yield (f x) s
   fmap _ (Skip s) = Skip s
   fmap _ Done = Done
+#if MIN_VERSION_base(4,8,0)
+  {-# INLINE (<$) #-}
+  (<$) = fmap . const
+#endif
 
 -- | Monadic streams
 data Stream m a = forall s. Stream (s -> m (Step s a)) s
@@ -510,13 +515,6 @@
                                  Skip    sb' -> return $ Skip (sa, sb', Just x)
                                  Done        -> return $ Done
 
--- FIXME: This might expose an opportunity for inplace execution.
-{-# RULES
-
-"zipWithM xs xs [Vector.Stream]" forall f xs.
-  zipWithM f xs xs = mapM (\x -> f x x) xs   #-}
-
-
 zipWithM_ :: Monad m => (a -> b -> m c) -> Stream m a -> Stream m b -> m ()
 {-# INLINE zipWithM_ #-}
 zipWithM_ f sa sb = consume (zipWithM f sa sb)
@@ -703,6 +701,9 @@
                   Skip    s' -> return $ Skip s'
                   Done       -> return $ Done
 
+catMaybes :: Monad m => Stream m (Maybe a) -> Stream m a
+catMaybes = mapMaybe id
+
 -- | Drop elements which do not satisfy the monadic predicate
 filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
 {-# INLINE_FUSED filterM #-}
@@ -719,6 +720,25 @@
                   Skip    s' -> return $ Skip s'
                   Done       -> return $ Done
 
+-- | Apply monadic function to each element and drop all Nothings
+--
+-- @since 0.12.2.0
+mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
+{-# INLINE_FUSED mapMaybeM #-}
+mapMaybeM f (Stream step t) = Stream step' t
+  where
+    {-# INLINE_INNER step' #-}
+    step' s = do
+                r <- step s
+                case r of
+                  Yield x s' -> do
+                                  fx <- f x
+                                  return $ case fx of
+                                    Nothing -> Skip s'
+                                    Just b  -> Yield b s'
+                  Skip    s' -> return $ Skip s'
+                  Done       -> return $ Done
+
 -- | Drop repeated adjacent elements.
 uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
 {-# INLINE_FUSED uniq #-}
@@ -1104,7 +1124,7 @@
 {-# INLINE_FUSED unfoldrN #-}
 unfoldrN n f = unfoldrNM n (return . f)
 
--- | Unfold at most @n@ elements with a monadic functions
+-- | Unfold at most @n@ elements with a monadic function.
 unfoldrNM :: Monad m => Int -> (s -> m (Maybe (a, s))) -> s -> Stream m a
 {-# INLINE_FUSED unfoldrNM #-}
 unfoldrNM m f t = Stream step (t,m)
@@ -1117,7 +1137,27 @@
                                  Nothing     -> Done
                              ) (f s)
 
--- | Apply monadic function n times to value. Zeroth element is original value.
+-- | Unfold exactly @n@ elements
+--
+-- @since 0.12.2.0
+unfoldrExactN :: Monad m => Int -> (s -> (a, s)) -> s -> Stream m a
+{-# INLINE_FUSED unfoldrExactN #-}
+unfoldrExactN n f = unfoldrExactNM n (return . f)
+
+-- | Unfold exactly @n@ elements with a monadic function.
+--
+-- @since 0.12.2.0
+unfoldrExactNM :: Monad m => Int -> (s -> m (a, s)) -> s -> Stream m a
+{-# INLINE_FUSED unfoldrExactNM #-}
+unfoldrExactNM m f t = Stream step (t,m)
+  where
+    {-# INLINE_INNER step #-}
+    step (s,n) | n <= 0    = return Done
+               | otherwise = do (x,s') <- f s
+                                return $ Yield x (s',n-1)
+
+-- | /O(n)/ Apply monadic function \(\max(n - 1, 0)\) times to an initial value,
+-- producing a stream of \(\max(n, 0)\) values.
 iterateNM :: Monad m => Int -> (a -> m a) -> a -> Stream m a
 {-# INLINE_FUSED iterateNM #-}
 iterateNM n f x0 = Stream step (x0,n)
@@ -1128,7 +1168,8 @@
                | otherwise = do a <- f x
                                 return $ Yield a (a,i-1)
 
--- | Apply function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply function \(\max(n - 1, 0)\) times to an initial value,
+-- producing a stream of \(\max(n, 0)\) values.
 iterateN :: Monad m => Int -> (a -> a) -> a -> Stream m a
 {-# INLINE_FUSED iterateN #-}
 iterateN n f x0 = iterateNM n (return . f) x0
diff --git a/Data/Vector/Generic.hs b/Data/Vector/Generic.hs
--- a/Data/Vector/Generic.hs
+++ b/Data/Vector/Generic.hs
@@ -30,7 +30,7 @@
   unsafeIndexM, unsafeHeadM, unsafeLastM,
 
   -- ** Extracting subvectors (slicing)
-  slice, init, tail, take, drop, splitAt,
+  slice, init, tail, take, drop, splitAt, uncons, unsnoc,
   unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
 
   -- * Construction
@@ -42,8 +42,8 @@
   replicateM, generateM, iterateNM, create, createT,
 
   -- ** Unfolding
-  unfoldr, unfoldrN,
-  unfoldrM, unfoldrNM,
+  unfoldr, unfoldrN, unfoldrExactN,
+  unfoldrM, unfoldrNM, unfoldrExactNM,
   constructN, constructrN,
 
   -- ** Enumeration
@@ -81,6 +81,7 @@
 
   -- ** Monadic mapping
   mapM, imapM, mapM_, imapM_, forM, forM_,
+  iforM, iforM_,
 
   -- ** Zipping
   zipWith, zipWith3, zipWith4, zipWith5, zipWith6,
@@ -96,20 +97,21 @@
   -- * Working with predicates
 
   -- ** Filtering
-  filter, ifilter, uniq,
+  filter, ifilter, filterM, uniq,
   mapMaybe, imapMaybe,
-  filterM,
+  mapMaybeM, imapMaybeM,
   takeWhile, dropWhile,
 
   -- ** Partitioning
   partition, partitionWith, unstablePartition, span, break,
 
   -- ** Searching
-  elem, notElem, find, findIndex, findIndices, elemIndex, elemIndices,
+  elem, notElem, find, findIndex, findIndexR, findIndices, elemIndex, elemIndices,
 
   -- * Folding
   foldl, foldl1, foldl', foldl1', foldr, foldr1, foldr', foldr1',
   ifoldl, ifoldl', ifoldr, ifoldr',
+  foldMap, foldMap',
 
   -- ** Specialised folds
   all, any, and, or,
@@ -149,7 +151,7 @@
   -- * Fusion support
 
   -- ** Conversion to/from Bundles
-  stream, unstream, streamR, unstreamR,
+  stream, unstream, unstreamM, streamR, unstreamR,
 
   -- ** Recycling support
   new, clone,
@@ -194,6 +196,9 @@
                         filter, takeWhile, dropWhile, span, break,
                         elem, notElem,
                         foldl, foldl1, foldr, foldr1,
+#if __GLASGOW_HASKELL__ >= 706
+                        foldMap,
+#endif
                         all, any, and, or, sum, product, maximum, minimum,
                         scanl, scanl1, scanr, scanr1,
                         enumFromTo, enumFromThenTo,
@@ -203,6 +208,10 @@
 import qualified Text.Read as Read
 import qualified Data.List.NonEmpty as NonEmpty
 
+#if __GLASGOW_HASKELL__ < 710
+import Data.Monoid
+#endif
+
 #if __GLASGOW_HASKELL__ >= 707
 import Data.Typeable ( Typeable, gcast1 )
 #else
@@ -231,7 +240,7 @@
 -- | /O(1)/ Yield the length of the vector
 length :: Vector v a => v a -> Int
 {-# INLINE length #-}
-length = Bundle.length . stream'
+length = Bundle.length . stream
 
 -- | /O(1)/ Test whether a vector is empty
 null :: Vector v a => v a -> Bool
@@ -431,8 +440,10 @@
 --
 -- Note that @'splitAt' n v@ is equivalent to @('take' n v, 'drop' n v)@
 -- but slightly more efficient.
-{-# INLINE_FUSED splitAt #-}
+--
+-- @since 0.7.1
 splitAt :: Vector v a => Int -> v a -> (v a, v a)
+{-# INLINE_FUSED splitAt #-}
 splitAt n v = ( unsafeSlice 0 m v
               , unsafeSlice m (delay_inline max 0 (len - n')) v
               )
@@ -441,6 +452,20 @@
       n'  = max n 0
       len = length v
 
+-- | /O(1)/ Yield the 'head' and 'tail' of the vector, or 'Nothing' if empty.
+--
+-- @since 0.12.2.0
+uncons :: Vector v a => v a -> Maybe (a, v a)
+{-# INLINE_FUSED uncons #-}
+uncons xs = flip (,) (unsafeTail xs) `fmap` (xs !? 0)
+
+-- | /O(1)/ Yield the 'last' and 'init' of the vector, or 'Nothing' if empty.
+--
+-- @since 0.12.2.0
+unsnoc :: Vector v a => v a -> Maybe (v a, a)
+{-# INLINE_FUSED unsnoc #-}
+unsnoc xs = (,) (unsafeInit xs) `fmap` (xs !? (length xs - 1))
+
 -- | /O(1)/ Yield a slice of the vector without copying. The vector must
 -- contain at least @i+n@ elements but this is not checked.
 unsafeSlice :: Vector v a => Int   -- ^ @i@ starting index
@@ -532,7 +557,13 @@
 {-# INLINE generate #-}
 generate n f = unstream (Bundle.generate n f)
 
--- | /O(n)/ Apply function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply function \(\max(n - 1, 0)\) times to an initial value, producing a vector
+-- of length \(\max(n, 0)\). Zeroth element will contain the initial value, that's why there
+-- is one less function application than the number of elements in the produced vector.
+--
+-- \( \underbrace{x, f (x), f (f (x)), \ldots}_{\max(0,n)\rm{~elements}} \)
+--
+-- @since 0.7.1
 iterateN :: Vector v a => Int -> (a -> a) -> a -> v a
 {-# INLINE iterateN #-}
 iterateN n f x = unstream (Bundle.iterateN n f x)
@@ -559,6 +590,17 @@
 {-# INLINE unfoldrN #-}
 unfoldrN n f = unstream . Bundle.unfoldrN n f
 
+-- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly applying
+-- the generator function to a seed. The generator function yields the
+-- next element and the new seed.
+--
+-- > unfoldrExactN 3 (\n -> (n,n-1)) 10 = <10,9,8>
+--
+-- @since 0.12.2.0
+unfoldrExactN  :: Vector v a => Int -> (b -> (a, b)) -> b -> v a
+{-# INLINE unfoldrExactN #-}
+unfoldrExactN n f = unstream . Bundle.unfoldrExactN n f
+
 -- | /O(n)/ Construct a vector by repeatedly applying the monadic
 -- generator function to a seed. The generator function yields 'Just'
 -- the next element and the new seed or 'Nothing' if there are no more
@@ -575,6 +617,15 @@
 {-# INLINE unfoldrNM #-}
 unfoldrNM n f = unstreamM . MBundle.unfoldrNM n f
 
+-- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly
+-- applying the monadic generator function to a seed. The generator
+-- function yields the next element and the new seed.
+--
+-- @since 0.12.2.0
+unfoldrExactNM :: (Monad m, Vector v a) => Int -> (b -> m (a, b)) -> b -> m (v a)
+{-# INLINE unfoldrExactNM #-}
+unfoldrExactNM n f = unstreamM . MBundle.unfoldrExactNM n f
+
 -- | /O(n)/ Construct a vector with @n@ elements by repeatedly applying the
 -- generator function to the already constructed part of the vector.
 --
@@ -735,7 +786,13 @@
 {-# INLINE generateM #-}
 generateM n f = unstreamM (MBundle.generateM n f)
 
--- | /O(n)/ Apply monadic function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply monadic function \(\max(n - 1, 0)\) times to an initial value, producing a vector
+-- of length \(\max(n, 0)\). Zeroth element will contain the initial value, that's why there
+-- is one less function application than the number of elements in the produced vector.
+--
+-- For non-monadic version see `iterateN`
+--
+-- @since 0.12.0.0
 iterateNM :: (Monad m, Vector v a) => Int -> (a -> m a) -> a -> m (v a)
 {-# INLINE iterateNM #-}
 iterateNM n f x = unstreamM (MBundle.iterateNM n f x)
@@ -851,7 +908,11 @@
 -- | /O(m+n)/ For each pair @(i,b)@ from the list, replace the vector element
 -- @a@ at position @i@ by @f a b@.
 --
--- > accum (+) <5,9,2> [(2,4),(1,6),(0,3),(1,7)] = <5+3, 9+6+7, 2+4>
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.accum (+) (V.fromList [1000.0,2000.0,3000.0]) [(2,4),(1,6),(0,3),(1,10)]
+-- [1003.0,2016.0,3004.0]
 accum :: Vector v a
       => (a -> b -> a) -- ^ accumulating function @f@
       -> v a           -- ^ initial vector (of length @m@)
@@ -863,7 +924,11 @@
 -- | /O(m+n)/ For each pair @(i,b)@ from the vector of pairs, replace the vector
 -- element @a@ at position @i@ by @f a b@.
 --
--- > accumulate (+) <5,9,2> <(2,4),(1,6),(0,3),(1,7)> = <5+3, 9+6+7, 2+4>
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.accumulate (+) (V.fromList [1000.0,2000.0,3000.0]) (V.fromList [(2,4),(1,6),(0,3),(1,10)])
+-- [1003.0,2016.0,3004.0]
 accumulate :: (Vector v a, Vector v (Int, b))
            => (a -> b -> a) -- ^ accumulating function @f@
            -> v a           -- ^ initial vector (of length @m@)
@@ -1096,6 +1161,22 @@
 {-# INLINE forM_ #-}
 forM_ as f = mapM_ f as
 
+-- | /O(n)/ Apply the monadic action to all elements of the vector and their indices, yielding a
+-- vector of results. Equivalent to 'flip' 'imapM'.
+--
+-- @since 0.12.2.0
+iforM :: (Monad m, Vector v a, Vector v b) => v a -> (Int -> a -> m b) -> m (v b)
+{-# INLINE iforM #-}
+iforM as f = imapM f as
+
+-- | /O(n)/ Apply the monadic action to all elements of the vector and their indices and ignore the
+-- results. Equivalent to 'flip' 'imapM_'.
+--
+-- @since 0.12.2.0
+iforM_ :: (Monad m, Vector v a) => v a -> (Int -> a -> m b) -> m ()
+{-# INLINE iforM_ #-}
+iforM_ as f = imapM_ f as
+
 -- Zipping
 -- -------
 
@@ -1345,8 +1426,26 @@
 {-# INLINE filterM #-}
 filterM f = unstreamM . Bundle.filterM f . stream
 
--- | /O(n)/ Yield the longest prefix of elements satisfying the predicate
--- without copying.
+-- | /O(n)/ Apply monadic function to each element of vector and
+-- discard elements returning Nothing.
+--
+-- @since 0.12.2.0
+mapMaybeM :: (Monad m, Vector v a, Vector v b) => (a -> m (Maybe b)) -> v a -> m (v b)
+{-# INLINE mapMaybeM #-}
+mapMaybeM f = unstreamM . Bundle.mapMaybeM f . stream
+
+-- | /O(n)/ Apply monadic function to each element of vector and its index.
+-- Discards elements returning Nothing.
+--
+-- @since 0.12.2.0
+imapMaybeM :: (Monad m, Vector v a, Vector v b)
+      => (Int -> a -> m (Maybe b)) -> v a -> m (v b)
+{-# INLINE imapMaybeM #-}
+imapMaybeM f = unstreamM . Bundle.mapMaybeM (\(i, a) -> f i a) . Bundle.indexed . stream
+
+-- | /O(n)/ Yield the longest prefix of elements satisfying the predicate.
+-- Current implementation is not copy-free, unless the result vector is
+-- fused away.
 takeWhile :: Vector v a => (a -> Bool) -> v a -> v a
 {-# INLINE takeWhile #-}
 takeWhile f = unstream . Bundle.takeWhile f . stream
@@ -1354,9 +1453,25 @@
 -- | /O(n)/ Drop the longest prefix of elements that satisfy the predicate
 -- without copying.
 dropWhile :: Vector v a => (a -> Bool) -> v a -> v a
-{-# INLINE dropWhile #-}
-dropWhile f = unstream . Bundle.dropWhile f . stream
+{-# INLINE_FUSED dropWhile #-}
+-- In the case that the argument is an actual vector,
+-- this is a faster solution than stream fusion.
+dropWhile f xs = case findIndex (not . f) xs of
+                   Just i  -> unsafeDrop i xs
+                   Nothing -> empty
 
+-- If we have optimization turned on
+-- and the argument to 'dropWhile' comes from a stream,
+-- we never allocate the argument vector, and
+-- whenever possible, we avoid creating the resulting vector actually in heap.
+--
+-- Also note that @'new' . 'New.unstream'@
+-- is the definition (to be @INLINE@d) of 'unstream'.
+{-# RULES
+"dropWhile/unstream [Vector]" forall f p.
+  dropWhile f (new (New.unstream p)) = new (New.unstream (Bundle.dropWhile f p))
+  #-}
+
 -- Parititioning
 -- -------------
 
@@ -1380,6 +1495,11 @@
     v2 <- unsafeFreeze mv2
     return (v1,v2))
 
+-- | /O(n)/ Split the vector into two parts, the first one containing the
+-- @`Left`@ elements and the second containing the @`Right`@ elements.
+-- The relative order of the elements is preserved.
+--
+-- @since 0.12.1.0
 partitionWith :: (Vector v a, Vector v b, Vector v c) => (a -> Either b c) -> v a -> (v b, v c)
 {-# INLINE partitionWith #-}
 partitionWith f = partition_with_stream f . stream
@@ -1473,6 +1593,14 @@
 {-# INLINE findIndex #-}
 findIndex f = Bundle.findIndex f . stream
 
+-- | /O(n)/ Yield 'Just' the index of the /last/ element matching the predicate
+-- or 'Nothing' if no such element exists.
+--
+-- @since 0.12.2.0
+findIndexR :: Vector v a => (a -> Bool) -> v a -> Maybe Int
+{-# INLINE findIndexR #-}
+findIndexR f v = fmap (length v - 1 -) . Bundle.findIndex f $ streamR v
+
 -- | /O(n)/ Yield the indices of elements satisfying the predicate in ascending
 -- order.
 findIndices :: (Vector v a, Vector v Int) => (a -> Bool) -> v a -> v Int
@@ -1560,41 +1688,121 @@
 ifoldr' f z xs = Bundle.foldl' (flip (uncurry f)) z
                $ Bundle.indexedR (length xs) $ streamR xs
 
+-- | /O(n)/ Map each element of the structure to a monoid, and combine
+-- the results. It uses same implementation as corresponding method of
+-- 'Foldable' type cless. Note it's implemented in terms of 'foldr'
+-- and won't fuse with functions that traverse vector from left to
+-- right ('map', 'generate', etc.).
+--
+-- @since 0.12.2.0
+foldMap :: (Monoid m, Vector v a) => (a -> m) -> v a -> m
+{-# INLINE foldMap #-}
+foldMap f = foldr (mappend . f) mempty
+
+-- | /O(n)/ 'foldMap' which is strict in accumulator. It uses same
+-- implementation as corresponding method of 'Foldable' type class.
+-- Note it's implemented in terms of 'foldl'' so it fuses in most
+-- contexts.
+--
+-- @since 0.12.2.0
+foldMap' :: (Monoid m, Vector v a) => (a -> m) -> v a -> m
+{-# INLINE foldMap' #-}
+foldMap' f = foldl' (\acc a -> acc `mappend` f a) mempty
+
+
 -- Specialised folds
 -- -----------------
 
 -- | /O(n)/ Check if all elements satisfy the predicate.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.all even $ V.fromList [2, 4, 12 :: Int]
+-- True
+-- >>> V.all even $ V.fromList [2, 4, 13 :: Int]
+-- False
+-- >>> V.all even (V.empty :: V.Vector Int)
+-- True
 all :: Vector v a => (a -> Bool) -> v a -> Bool
 {-# INLINE all #-}
 all f = Bundle.and . Bundle.map f . stream
 
 -- | /O(n)/ Check if any element satisfies the predicate.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.any even $ V.fromList [1, 3, 7 :: Int]
+-- False
+-- >>> V.any even $ V.fromList [3, 2, 13 :: Int]
+-- True
+-- >>> V.any even (V.empty :: V.Vector Int)
+-- False
 any :: Vector v a => (a -> Bool) -> v a -> Bool
 {-# INLINE any #-}
 any f = Bundle.or . Bundle.map f . stream
 
 -- | /O(n)/ Check if all elements are 'True'
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.and $ V.fromList [True, False]
+-- False
+-- >>> V.and V.empty
+-- True
 and :: Vector v Bool => v Bool -> Bool
 {-# INLINE and #-}
 and = Bundle.and . stream
 
 -- | /O(n)/ Check if any element is 'True'
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.or $ V.fromList [True, False]
+-- True
+-- >>> V.or V.empty
+-- False
 or :: Vector v Bool => v Bool -> Bool
 {-# INLINE or #-}
 or = Bundle.or . stream
 
 -- | /O(n)/ Compute the sum of the elements
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.sum $ V.fromList [300,20,1 :: Int]
+-- 321
+-- >>> V.sum (V.empty :: V.Vector Int)
+-- 0
 sum :: (Vector v a, Num a) => v a -> a
 {-# INLINE sum #-}
 sum = Bundle.foldl' (+) 0 . stream
 
 -- | /O(n)/ Compute the produce of the elements
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.product $ V.fromList [1,2,3,4 :: Int]
+-- 24
+-- >>> V.product (V.empty :: V.Vector Int)
+-- 1
 product :: (Vector v a, Num a) => v a -> a
 {-# INLINE product #-}
 product = Bundle.foldl' (*) 1 . stream
 
 -- | /O(n)/ Yield the maximum element of the vector. The vector may not be
 -- empty.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.maximum $ V.fromList [2.0, 1.0]
+-- 2.0
 maximum :: (Vector v a, Ord a) => v a -> a
 {-# INLINE maximum #-}
 maximum = Bundle.foldl1' max . stream
@@ -1612,6 +1820,12 @@
 
 -- | /O(n)/ Yield the minimum element of the vector. The vector may not be
 -- empty.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.minimum $ V.fromList [2.0, 1.0]
+-- 1.0
 minimum :: (Vector v a, Ord a) => v a -> a
 {-# INLINE minimum #-}
 minimum = Bundle.foldl1' min . stream
@@ -1915,6 +2129,14 @@
 -- @
 -- fromListN n xs = 'fromList' ('take' n xs)
 -- @
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> V.fromListN 3 [1,2,3,4,5::Int]
+-- [1,2,3]
+-- >>> V.fromListN 3 [1::Int]
+-- [1]
 fromListN :: Vector v a => Int -> [a] -> v a
 {-# INLINE fromListN #-}
 fromListN n = unstream . Bundle.fromListN n
@@ -1995,7 +2217,7 @@
   :: (PrimMonad m, Vector v a) => Mutable v (PrimState m) a -> v a -> m ()
 {-# INLINE copy #-}
 copy dst src = BOUNDS_CHECK(check) "copy" "length mismatch"
-                                          (M.length dst == length src)
+                                          (M.length dst == basicLength src)
              $ unsafeCopy dst src
 
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
@@ -2004,7 +2226,7 @@
   :: (PrimMonad m, Vector v a) => Mutable v (PrimState m) a -> v a -> m ()
 {-# INLINE unsafeCopy #-}
 unsafeCopy dst src = UNSAFE_CHECK(check) "unsafeCopy" "length mismatch"
-                                         (M.length dst == length src)
+                                         (M.length dst == basicLength src)
                    $ (dst `seq` src `seq` basicUnsafeCopy dst src)
 
 -- Conversions to/from Bundles
@@ -2013,13 +2235,7 @@
 -- | /O(1)/ Convert a vector to a 'Bundle'
 stream :: Vector v a => v a -> Bundle v a
 {-# INLINE_FUSED stream #-}
-stream v = stream' v
-
--- Same as 'stream', but can be used to avoid having a cycle in the dependency
--- graph of functions, which forces GHC to create a loop breaker.
-stream' :: Vector v a => v a -> Bundle v a
-{-# INLINE stream' #-}
-stream' v = Bundle.fromVector v
+stream v = Bundle.fromVector v
 
 {-
 stream v = v `seq` n `seq` (Bundle.unfoldr get 0 `Bundle.sized` Exact n)
@@ -2100,7 +2316,10 @@
   streamR (new (New.transformR f g m)) = inplace f g (streamR (new m))  #-}
 
 
-
+-- | Load monadic stream bundle into a newly allocated vector. This function goes through
+-- a list, so prefer using `unstream`, unless you need to be in a monad.
+--
+-- @since 0.12.2.0
 unstreamM :: (Monad m, Vector v a) => MBundle m u a -> m (v a)
 {-# INLINE_FUSED unstreamM #-}
 unstreamM s = do
@@ -2142,7 +2361,7 @@
 {-# INLINE_FUSED clone #-}
 clone v = v `seq` New.create (
   do
-    mv <- M.new (length v)
+    mv <- M.new (basicLength v)
     unsafeCopy mv v
     return mv)
 
@@ -2157,7 +2376,8 @@
 {-# INLINE eq #-}
 xs `eq` ys = stream xs == stream ys
 
--- | /O(n)/
+-- | /O(n)/ Check if two vectors are equal using supplied equality
+-- predicate.
 eqBy :: (Vector v a, Vector v b) => (a -> b -> Bool) -> v a -> v b -> Bool
 {-# INLINE eqBy #-}
 eqBy e xs ys = Bundle.eqBy e (stream xs) (stream ys)
@@ -2170,7 +2390,10 @@
 {-# INLINE cmp #-}
 cmp xs ys = compare (stream xs) (stream ys)
 
--- | /O(n)/
+-- | /O(n)/ Compare two vectors using supplied comparison function for
+-- vector elements. Comparison works same as for lists.
+--
+-- > cmpBy compare == cmp
 cmpBy :: (Vector v a, Vector v b) => (a -> b -> Ordering) -> v a -> v b -> Ordering
 cmpBy c xs ys = Bundle.cmpBy c (stream xs) (stream ys)
 
@@ -2238,3 +2461,6 @@
          => (forall d. Data  d => c (t d)) -> Maybe  (c (v a))
 {-# INLINE dataCast #-}
 dataCast f = gcast1 f
+
+-- $setup
+-- >>> :set -XFlexibleContexts
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
@@ -145,4 +145,5 @@
   {-# INLINE elemseq #-}
   elemseq _ = \_ x -> x
 
-
+  {-# MINIMAL basicUnsafeFreeze, basicUnsafeThaw, basicLength,
+              basicUnsafeSlice, basicUnsafeIndexM #-}
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
@@ -591,7 +591,14 @@
 new n = BOUNDS_CHECK(checkLength) "new" n
       $ unsafeNew n >>= \v -> basicInitialize v >> return v
 
--- | Create a mutable vector of the given length. The memory is not initialized.
+-- | Create a mutable vector of the given length. The vector content
+--   should be presumed uninitialized. However exact semantics depends
+--   on vector implementation. For example unboxed and storable
+--   vectors will create vector filled with whatever underlying memory
+--   buffer happens to contain, while boxed vector's elements are
+--   initialized to bottoms which will throw exception when evaluated.
+--
+-- @since 0.4
 unsafeNew :: (PrimMonad m, MVector v a) => Int -> m (v (PrimState m) a)
 {-# INLINE unsafeNew #-}
 unsafeNew n = UNSAFE_CHECK(checkLength) "unsafeNew" n
@@ -620,8 +627,18 @@
 -- Growing
 -- -------
 
--- | Grow a vector by the given number of elements. The number must be
--- positive.
+-- | Grow a vector by the given number of elements. The number must not be
+-- negative otherwise error is thrown. Semantics of this function is exactly the
+-- same as `unsafeGrow`, except that it will initialize the newly
+-- allocated memory first.
+--
+-- It is important to note that mutating the returned vector will not affect the
+-- vector that was used as a source. In other words it does not, nor will it
+-- ever have the semantics of @realloc@ from C.
+--
+-- > grow mv 0 === clone mv
+--
+-- @since 0.4.0
 grow :: (PrimMonad m, MVector v a)
                 => v (PrimState m) a -> Int -> m (v (PrimState m) a)
 {-# INLINE grow #-}
@@ -630,6 +647,10 @@
                basicInitialize $ basicUnsafeSlice (length v) by vnew
                return vnew
 
+-- | Same as `grow`, except that it copies data towards the end of the newly
+-- allocated vector making extra space available at the beginning.
+--
+-- @since 0.11.0.0
 growFront :: (PrimMonad m, MVector v a)
                 => v (PrimState m) a -> Int -> m (v (PrimState m) a)
 {-# INLINE growFront #-}
@@ -661,14 +682,39 @@
   where
     by = enlarge_delta v
 
--- | Grow a vector by the given number of elements. The number must be
--- positive but this is not checked.
-unsafeGrow :: (PrimMonad m, MVector v a)
-                        => v (PrimState m) a -> Int -> m (v (PrimState m) a)
+-- | Grow a vector by allocating a new mutable vector of the same size plus the
+-- the given number of elements and copying all the data over to the new vector
+-- starting at its beginning. The newly allocated memory is not initialized and
+-- the extra space at the end will likely contain garbage data or uninitialzed
+-- error. Use `unsafeGrowFront` to make the extra space available in the front
+-- of the new vector.
+--
+-- It is important to note that mutating the returned vector will not affect
+-- elements of the vector that was used as a source. In other words it does not,
+-- nor will it ever have the semantics of @realloc@ from C. Keep in mind,
+-- however, that values themselves can be of a mutable type
+-- (eg. `Foreign.Ptr.Ptr`), in which case it would be possible to affect values
+-- stored in both vectors.
+--
+-- > unsafeGrow mv 0 === clone mv
+--
+-- @since 0.4.0
+unsafeGrow ::
+     (PrimMonad m, MVector v a)
+  => v (PrimState m) a
+  -- ^ A mutable vector to copy the data from.
+  -> Int
+  -- ^ Number of elements to grow the vector by. It must be non-negative but
+  -- this is not checked.
+  -> m (v (PrimState m) a)
 {-# INLINE unsafeGrow #-}
 unsafeGrow v n = UNSAFE_CHECK(checkLength) "unsafeGrow" n
                $ basicUnsafeGrow v n
 
+-- | Same as `unsafeGrow`, except that it copies data towards the end of the
+-- newly allocated vector making extra space available at the beginning.
+--
+-- @since 0.11.0.0
 unsafeGrowFront :: (PrimMonad m, MVector v a)
                         => v (PrimState m) a -> Int -> m (v (PrimState m) a)
 {-# INLINE unsafeGrowFront #-}
diff --git a/Data/Vector/Generic/Mutable/Base.hs b/Data/Vector/Generic/Mutable/Base.hs
--- a/Data/Vector/Generic/Mutable/Base.hs
+++ b/Data/Vector/Generic/Mutable/Base.hs
@@ -87,10 +87,12 @@
                                   -> v (PrimState m) a   -- ^ source
                                   -> m ()
 
-  -- | Grow a vector by the given number of elements. This method should not be
-  -- called directly, use 'unsafeGrow' instead.
-  basicUnsafeGrow  :: PrimMonad m => v (PrimState m) a -> Int
-                                                       -> m (v (PrimState m) a)
+  -- | Grow a vector by the given number of elements. Allocates a new vector and
+  -- copies all of the elements over starting at 0 index. This method should not
+  -- be called directly, use 'grow'\/'unsafeGrow' instead.
+  basicUnsafeGrow  :: PrimMonad m => v (PrimState m) a
+                                  -> Int
+                                  -> m (v (PrimState m) a)
 
   {-# INLINE basicUnsafeReplicate #-}
   basicUnsafeReplicate n x
@@ -145,3 +147,6 @@
     where
       n = basicLength v
 
+  {-# MINIMAL basicLength, basicUnsafeSlice, basicOverlaps,
+              basicUnsafeNew, basicInitialize, basicUnsafeRead,
+              basicUnsafeWrite #-}
diff --git a/Data/Vector/Mutable.hs b/Data/Vector/Mutable.hs
--- a/Data/Vector/Mutable.hs
+++ b/Data/Vector/Mutable.hs
@@ -47,10 +47,14 @@
   nextPermutation,
 
   -- ** Filling and copying
-  set, copy, move, unsafeCopy, unsafeMove
+
+  set, copy, move, unsafeCopy, unsafeMove,
+
+  -- ** Arrays
+  fromMutableArray, toMutableArray
 ) where
 
-import           Control.Monad (when)
+import           Control.Monad (when, liftM)
 import qualified Data.Vector.Generic.Mutable as G
 import           Data.Primitive.Array
 import           Control.Monad.Primitive
@@ -65,9 +69,9 @@
 
 
 -- | Mutable boxed vectors keyed on the monad they live in ('IO' or @'ST' s@).
-data MVector s a = MVector {-# UNPACK #-} !Int
-                           {-# UNPACK #-} !Int
-                           {-# UNPACK #-} !(MutableArray s a)
+data MVector s a = MVector {-# UNPACK #-} !Int                -- ^ Offset in underlying array
+                           {-# UNPACK #-} !Int                -- ^ Size of slice
+                           {-# UNPACK #-} !(MutableArray s a) -- ^ Underlying array
         deriving ( Typeable )
 
 type IOVector = MVector RealWorld
@@ -187,7 +191,7 @@
   in go 0
 
 uninitialised :: a
-uninitialised = error "Data.Vector.Mutable: uninitialised element. If you are trying to compact a vector, use the 'force' function to remove uninitialised elements from the underlying array."
+uninitialised = error "Data.Vector.Mutable: uninitialised element. If you are trying to compact a vector, use the 'Data.Vector.force' function to remove uninitialised elements from the underlying array."
 
 -- Length information
 -- ------------------
@@ -275,7 +279,10 @@
 {-# INLINE new #-}
 new = G.new
 
--- | Create a mutable vector of the given length. The memory is not initialized.
+-- | Create a mutable vector of the given length. The vector elements
+--   are set to bottom so accessing them will cause an exception.
+--
+-- @since 0.5
 unsafeNew :: PrimMonad m => Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeNew #-}
 unsafeNew = G.unsafeNew
@@ -300,15 +307,49 @@
 -- Growing
 -- -------
 
--- | Grow a vector by the given number of elements. The number must be
--- positive.
+-- | Grow a boxed vector by the given number of elements. The number must be
+-- non-negative. Same semantics as in `G.grow` for generic vector. It differs
+-- from @grow@ functions for unpacked vectors, however, in that only pointers to
+-- values are copied over, therefore values themselves will be shared between
+-- two vectors. This is an important distinction to know about during memory
+-- usage analysis and in case when values themselves are of a mutable type, eg.
+-- `Data.IORef.IORef` or another mutable vector.
+--
+-- ====__Examples__
+--
+-- >>> import qualified Data.Vector as V
+-- >>> import qualified Data.Vector.Mutable as MV
+-- >>> mv <- V.thaw $ V.fromList ([10, 20, 30] :: [Integer])
+-- >>> mv' <- MV.grow mv 2
+--
+-- The two extra elements at the end of the newly allocated vector will be
+-- uninitialized and will result in an error if evaluated, so me must overwrite
+-- them with new values first:
+--
+-- >>> MV.write mv' 3 999
+-- >>> MV.write mv' 4 777
+-- >>> V.unsafeFreeze mv'
+-- [10,20,30,999,777]
+--
+-- It is important to note that the source mutable vector is not affected when
+-- the newly allocated one is mutated.
+--
+-- >>> MV.write mv' 2 888
+-- >>> V.unsafeFreeze mv'
+-- [10,20,888,999,777]
+-- >>> V.unsafeFreeze mv
+-- [10,20,30]
+--
+-- @since 0.5
 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.
+-- | Grow a vector by the given number of elements. The number must be non-negative but
+-- this is not checked. Same semantics as in `G.unsafeGrow` for generic vector.
+--
+-- @since 0.5
 unsafeGrow :: PrimMonad m
                => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeGrow #-}
@@ -422,3 +463,22 @@
 nextPermutation :: (PrimMonad m,Ord e) => MVector (PrimState m) e -> m Bool
 {-# INLINE nextPermutation #-}
 nextPermutation = G.nextPermutation
+
+-- Conversions - Arrays
+-- -----------------------------
+
+-- | /O(n)/ Make a copy of a mutable array to a new mutable vector.
+--
+-- @since 0.12.2.0
+fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (PrimState m) a)
+{-# INLINE fromMutableArray #-}
+fromMutableArray marr =
+  let size = sizeofMutableArray marr
+   in MVector 0 size `liftM` cloneMutableArray marr 0 size
+
+-- | /O(n)/ Make a copy of a mutable vector into a new mutable array.
+--
+-- @since 0.12.2.0
+toMutableArray :: PrimMonad m => MVector (PrimState m) a -> m (MutableArray (PrimState m) a)
+{-# INLINE toMutableArray #-}
+toMutableArray (MVector offset size marr) = cloneMutableArray marr offset size
diff --git a/Data/Vector/Primitive.hs b/Data/Vector/Primitive.hs
--- a/Data/Vector/Primitive.hs
+++ b/Data/Vector/Primitive.hs
@@ -34,7 +34,7 @@
   unsafeIndexM, unsafeHeadM, unsafeLastM,
 
   -- ** Extracting subvectors (slicing)
-  slice, init, tail, take, drop, splitAt,
+  slice, init, tail, take, drop, splitAt, uncons, unsnoc,
   unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
 
   -- * Construction
@@ -46,8 +46,8 @@
   replicateM, generateM, iterateNM, create, createT,
 
   -- ** Unfolding
-  unfoldr, unfoldrN,
-  unfoldrM, unfoldrNM,
+  unfoldr, unfoldrN, unfoldrExactN,
+  unfoldrM, unfoldrNM, unfoldrExactNM,
   constructN, constructrN,
 
   -- ** Enumeration
@@ -81,21 +81,22 @@
   map, imap, concatMap,
 
   -- ** Monadic mapping
-  mapM, mapM_, forM, forM_,
+  mapM, imapM, mapM_, imapM_, forM, forM_,
+  iforM, iforM_,
 
   -- ** Zipping
   zipWith, zipWith3, zipWith4, zipWith5, zipWith6,
   izipWith, izipWith3, izipWith4, izipWith5, izipWith6,
 
   -- ** Monadic zipping
-  zipWithM, zipWithM_,
+  zipWithM, izipWithM, zipWithM_, izipWithM_,
 
   -- * Working with predicates
 
   -- ** Filtering
-  filter, ifilter, uniq,
+  filter, ifilter, filterM, uniq,
   mapMaybe, imapMaybe,
-  filterM,
+  mapMaybeM, imapMaybeM,
   takeWhile, dropWhile,
 
   -- ** Partitioning
@@ -107,6 +108,7 @@
   -- * Folding
   foldl, foldl1, foldl', foldl1', foldr, foldr1, foldr', foldr1',
   ifoldl, ifoldl', ifoldr, ifoldr',
+  foldMap, foldMap',
 
   -- ** Specialised folds
   all, any,
@@ -115,17 +117,23 @@
   minIndex, minIndexBy, maxIndex, maxIndexBy,
 
   -- ** Monadic folds
-  foldM, foldM', fold1M, fold1M',
-  foldM_, foldM'_, fold1M_, fold1M'_,
+  foldM, ifoldM, foldM', ifoldM',
+  fold1M, fold1M', foldM_, ifoldM_,
+  foldM'_, ifoldM'_, fold1M_, fold1M'_,
 
   -- * Prefix sums (scans)
   prescanl, prescanl',
   postscanl, postscanl',
   scanl, scanl', scanl1, scanl1',
+  iscanl, iscanl',
   prescanr, prescanr',
   postscanr, postscanr',
   scanr, scanr', scanr1, scanr1',
+  iscanr, iscanr',
 
+  -- ** Comparisons
+  eqBy, cmpBy,
+
   -- * Conversions
 
   -- ** Lists
@@ -163,6 +171,9 @@
                         filter, takeWhile, dropWhile, span, break,
                         elem, notElem,
                         foldl, foldl1, foldr, foldr1,
+#if __GLASGOW_HASKELL__ >= 706
+                        foldMap,
+#endif
                         all, any, sum, product, minimum, maximum,
                         scanl, scanl1, scanr, scanr1,
                         enumFromTo, enumFromThenTo,
@@ -441,10 +452,26 @@
 --
 -- Note that @'splitAt' n v@ is equivalent to @('take' n v, 'drop' n v)@
 -- but slightly more efficient.
-{-# INLINE splitAt #-}
+--
+-- @since 0.7.1
 splitAt :: Prim a => Int -> Vector a -> (Vector a, Vector a)
+{-# INLINE splitAt #-}
 splitAt = G.splitAt
 
+-- | /O(1)/ Yield the 'head' and 'tail' of the vector, or 'Nothing' if empty.
+--
+-- @since 0.12.2.0
+uncons :: Prim a => Vector a -> Maybe (a, Vector a)
+{-# INLINE uncons #-}
+uncons = G.uncons
+
+-- | /O(1)/ Yield the 'last' and 'init' of the vector, or 'Nothing' if empty.
+--
+-- @since 0.12.2.0
+unsnoc :: Prim a => Vector a -> Maybe (Vector a, a)
+{-# INLINE unsnoc #-}
+unsnoc = G.unsnoc
+
 -- | /O(1)/ Yield a slice of the vector without copying. The vector must
 -- contain at least @i+n@ elements but this is not checked.
 unsafeSlice :: Prim a => Int   -- ^ @i@ starting index
@@ -502,7 +529,21 @@
 {-# INLINE generate #-}
 generate = G.generate
 
--- | /O(n)/ Apply function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply function \(\max(n - 1, 0)\) times to an initial value, producing a vector
+-- of length \(\max(n, 0)\). Zeroth element will contain the initial value, that's why there
+-- is one less function application than the number of elements in the produced vector.
+--
+-- \( \underbrace{x, f (x), f (f (x)), \ldots}_{\max(0,n)\rm{~elements}} \)
+--
+-- ===__Examples__
+--
+-- >>> import qualified Data.Vector.Primitive as VP
+-- >>> VP.iterateN 0 undefined undefined :: VP.Vector Int
+-- []
+-- >>> VP.iterateN 26 succ 'a'
+-- "abcdefghijklmnopqrstuvwxyz"
+--
+-- @since 0.7.1
 iterateN :: Prim a => Int -> (a -> a) -> a -> Vector a
 {-# INLINE iterateN #-}
 iterateN = G.iterateN
@@ -529,6 +570,17 @@
 {-# INLINE unfoldrN #-}
 unfoldrN = G.unfoldrN
 
+-- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly applying
+-- the generator function to a seed. The generator function yields the
+-- next element and the new seed.
+--
+-- > unfoldrExactN 3 (\n -> (n,n-1)) 10 = <10,9,8>
+--
+-- @since 0.12.2.0
+unfoldrExactN :: (Prim a) => Int -> (b -> (a, b)) -> b -> Vector a
+{-# INLINE unfoldrExactN #-}
+unfoldrExactN = G.unfoldrExactN
+
 -- | /O(n)/ Construct a vector by repeatedly applying the monadic
 -- generator function to a seed. The generator function yields 'Just'
 -- the next element and the new seed or 'Nothing' if there are no more
@@ -545,6 +597,15 @@
 {-# INLINE unfoldrNM #-}
 unfoldrNM = G.unfoldrNM
 
+-- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly
+-- applying the monadic generator function to a seed. The generator
+-- function yields the next element and the new seed.
+--
+-- @since 0.12.2.0
+unfoldrExactNM :: (Monad m, Prim a) => Int -> (b -> m (a, b)) -> b -> m (Vector a)
+{-# INLINE unfoldrExactNM #-}
+unfoldrExactNM = G.unfoldrExactNM
+
 -- | /O(n)/ Construct a vector with @n@ elements by repeatedly applying the
 -- generator function to the already constructed part of the vector.
 --
@@ -638,7 +699,13 @@
 {-# INLINE generateM #-}
 generateM = G.generateM
 
--- | /O(n)/ Apply monadic function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply monadic function \(\max(n - 1, 0)\) times to an initial value, producing a vector
+-- of length \(\max(n, 0)\). Zeroth element will contain the initial value, that's why there
+-- is one less function application than the number of elements in the produced vector.
+--
+-- For non-monadic version see `iterateN`
+--
+-- @since 0.12.0.0
 iterateNM :: (Monad m, Prim a) => Int -> (a -> m a) -> a -> m (Vector a)
 {-# INLINE iterateNM #-}
 iterateNM = G.iterateNM
@@ -719,7 +786,11 @@
 -- | /O(m+n)/ For each pair @(i,b)@ from the list, replace the vector element
 -- @a@ at position @i@ by @f a b@.
 --
--- > accum (+) <5,9,2> [(2,4),(1,6),(0,3),(1,7)] = <5+3, 9+6+7, 2+4>
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Primitive as VP
+-- >>> VP.accum (+) (VP.fromList [1000.0,2000.0,3000.0]) [(2,4),(1,6),(0,3),(1,10)]
+-- [1003.0,2016.0,3004.0]
 accum :: Prim a
       => (a -> b -> a) -- ^ accumulating function @f@
       -> Vector a      -- ^ initial vector (of length @m@)
@@ -818,12 +889,29 @@
 {-# INLINE mapM #-}
 mapM = G.mapM
 
+-- | /O(n)/ Apply the monadic action to every element of a vector and its
+-- index, yielding a vector of results
+--
+-- @since 0.12.2.0
+imapM :: (Monad m, Prim a, Prim b)
+      => (Int -> a -> m b) -> Vector a -> m (Vector b)
+{-# INLINE imapM #-}
+imapM = G.imapM
+
 -- | /O(n)/ Apply the monadic action to all elements of a vector and ignore the
 -- results
 mapM_ :: (Monad m, Prim a) => (a -> m b) -> Vector a -> m ()
 {-# INLINE mapM_ #-}
 mapM_ = G.mapM_
 
+-- | /O(n)/ Apply the monadic action to every element of a vector and its
+-- index, ignoring the results
+--
+-- @since 0.12.2.0
+imapM_ :: (Monad m, Prim a) => (Int -> a -> m b) -> Vector a -> m ()
+{-# INLINE imapM_ #-}
+imapM_ = G.imapM_
+
 -- | /O(n)/ Apply the monadic action to all elements of the vector, yielding a
 -- vector of results. Equivalent to @flip 'mapM'@.
 forM :: (Monad m, Prim a, Prim b) => Vector a -> (a -> m b) -> m (Vector b)
@@ -836,6 +924,22 @@
 {-# INLINE forM_ #-}
 forM_ = G.forM_
 
+-- | /O(n)/ Apply the monadic action to all elements of the vector and their indices, yielding a
+-- vector of results. Equivalent to 'flip' 'imapM'.
+--
+-- @since 0.12.2.0
+iforM :: (Monad m, Prim a, Prim b) => Vector a -> (Int -> a -> m b) -> m (Vector b)
+{-# INLINE iforM #-}
+iforM = G.iforM
+
+-- | /O(n)/ Apply the monadic action to all elements of the vector and their indices and ignore the
+-- results. Equivalent to 'flip' 'imapM_'.
+--
+-- @since 0.12.2.0
+iforM_ :: (Monad m, Prim a) => Vector a -> (Int -> a -> m b) -> m ()
+{-# INLINE iforM_ #-}
+iforM_ = G.iforM_
+
 -- Zipping
 -- -------
 
@@ -919,6 +1023,15 @@
 {-# INLINE zipWithM #-}
 zipWithM = G.zipWithM
 
+-- | /O(min(m,n))/ Zip the two vectors with a monadic action that also takes
+-- the element index and yield a vector of results
+--
+-- @since 0.12.2.0
+izipWithM :: (Monad m, Prim a, Prim b, Prim c)
+          => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m (Vector c)
+{-# INLINE izipWithM #-}
+izipWithM = G.izipWithM
+
 -- | /O(min(m,n))/ Zip the two vectors with the monadic action and ignore the
 -- results
 zipWithM_ :: (Monad m, Prim a, Prim b)
@@ -926,6 +1039,15 @@
 {-# INLINE zipWithM_ #-}
 zipWithM_ = G.zipWithM_
 
+-- | /O(min(m,n))/ Zip the two vectors with a monadic action that also takes
+-- the element index and ignore the results
+--
+-- @since 0.12.2.0
+izipWithM_ :: (Monad m, Prim a, Prim b)
+           => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m ()
+{-# INLINE izipWithM_ #-}
+izipWithM_ = G.izipWithM_
+
 -- Filtering
 -- ---------
 
@@ -950,18 +1072,39 @@
 {-# INLINE mapMaybe #-}
 mapMaybe = G.mapMaybe
 
+-- | /O(n)/ Apply monadic function to each element of vector and
+-- discard elements returning Nothing.
+--
+-- @since 0.12.2.0
+mapMaybeM
+  :: (Monad m, Prim a, Prim b)
+  => (a -> m (Maybe b)) -> Vector a -> m (Vector b)
+{-# INLINE mapMaybeM #-}
+mapMaybeM = G.mapMaybeM
+
 -- | /O(n)/ Drop elements when predicate, applied to index and value, returns Nothing
 imapMaybe :: (Prim a, Prim b) => (Int -> a -> Maybe b) -> Vector a -> Vector b
 {-# INLINE imapMaybe #-}
 imapMaybe = G.imapMaybe
 
+-- | /O(n)/ Apply monadic function to each element of vector and its index.
+-- Discards elements returning Nothing.
+--
+-- @since 0.12.2.0
+imapMaybeM
+  :: (Monad m, Prim a, Prim b)
+  => (Int -> a -> m (Maybe b)) -> Vector a -> m (Vector b)
+{-# INLINE imapMaybeM #-}
+imapMaybeM = G.imapMaybeM
+
 -- | /O(n)/ Drop elements that do not satisfy the monadic predicate
 filterM :: (Monad m, Prim a) => (a -> m Bool) -> Vector a -> m (Vector a)
 {-# INLINE filterM #-}
 filterM = G.filterM
 
--- | /O(n)/ Yield the longest prefix of elements satisfying the predicate
--- without copying.
+-- | /O(n)/ Yield the longest prefix of elements satisfying the predicate.
+-- Current implementation is not copy-free, unless the result vector is
+-- fused away.
 takeWhile :: Prim a => (a -> Bool) -> Vector a -> Vector a
 {-# INLINE takeWhile #-}
 takeWhile = G.takeWhile
@@ -991,11 +1134,11 @@
 {-# INLINE unstablePartition #-}
 unstablePartition = G.unstablePartition
 
--- | /O(n)/ Split the vector in two parts, the first one containing the
---   @Right@ elements and the second containing the @Left@ elements.
---   The relative order of the elements is preserved.
+-- | /O(n)/ Split the vector into two parts, the first one containing the
+-- @`Left`@ elements and the second containing the @`Right`@ elements.
+-- The relative order of the elements is preserved.
 --
---   @since 0.12.1.0
+-- @since 0.12.1.0
 partitionWith :: (Prim a, Prim b, Prim c) => (a -> Either b c) -> Vector a -> (Vector b, Vector c)
 {-# INLINE partitionWith #-}
 partitionWith = G.partitionWith
@@ -1123,31 +1266,94 @@
 {-# INLINE ifoldr' #-}
 ifoldr' = G.ifoldr'
 
+-- | /O(n)/ Map each element of the structure to a monoid, and combine
+-- the results. It uses same implementation as corresponding method of
+-- 'Foldable' type cless. Note it's implemented in terms of 'foldr'
+-- and won't fuse with functions that traverse vector from left to
+-- right ('map', 'generate', etc.).
+--
+-- @since 0.12.2.0
+foldMap :: (Monoid m, Prim a) => (a -> m) -> Vector a -> m
+{-# INLINE foldMap #-}
+foldMap = G.foldMap
+
+-- | /O(n)/ 'foldMap' which is strict in accumulator. It uses same
+-- implementation as corresponding method of 'Foldable' type class.
+-- Note it's implemented in terms of 'foldl'' so it fuses in most
+-- contexts.
+--
+-- @since 0.12.2.0
+foldMap' :: (Monoid m, Prim a) => (a -> m) -> Vector a -> m
+{-# INLINE foldMap' #-}
+foldMap' = G.foldMap'
+
 -- Specialised folds
 -- -----------------
 
 -- | /O(n)/ Check if all elements satisfy the predicate.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Primitive as VP
+-- >>> VP.all even $ VP.fromList [2, 4, 12 :: Int]
+-- True
+-- >>> VP.all even $ VP.fromList [2, 4, 13 :: Int]
+-- False
+-- >>> VP.all even (VP.empty :: VP.Vector Int)
+-- True
 all :: Prim a => (a -> Bool) -> Vector a -> Bool
 {-# INLINE all #-}
 all = G.all
 
 -- | /O(n)/ Check if any element satisfies the predicate.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Primitive as VP
+-- >>> VP.any even $ VP.fromList [1, 3, 7 :: Int]
+-- False
+-- >>> VP.any even $ VP.fromList [3, 2, 13 :: Int]
+-- True
+-- >>> VP.any even (VP.empty :: VP.Vector Int)
+-- False
 any :: Prim a => (a -> Bool) -> Vector a -> Bool
 {-# INLINE any #-}
 any = G.any
 
 -- | /O(n)/ Compute the sum of the elements
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Primitive as VP
+-- >>> VP.sum $ VP.fromList [300,20,1 :: Int]
+-- 321
+-- >>> VP.sum (VP.empty :: VP.Vector Int)
+-- 0
 sum :: (Prim a, Num a) => Vector a -> a
 {-# INLINE sum #-}
 sum = G.sum
 
 -- | /O(n)/ Compute the produce of the elements
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Primitive as VP
+-- >>> VP.product $ VP.fromList [1,2,3,4 :: Int]
+-- 24
+-- >>> VP.product (VP.empty :: VP.Vector Int)
+-- 1
 product :: (Prim a, Num a) => Vector a -> a
 {-# INLINE product #-}
 product = G.product
 
 -- | /O(n)/ Yield the maximum element of the vector. The vector may not be
 -- empty.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Primitive as VP
+-- >>> VP.maximum $ VP.fromList [2.0, 1.0]
+-- 2.0
 maximum :: (Prim a, Ord a) => Vector a -> a
 {-# INLINE maximum #-}
 maximum = G.maximum
@@ -1160,6 +1366,12 @@
 
 -- | /O(n)/ Yield the minimum element of the vector. The vector may not be
 -- empty.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Primitive as VP
+-- >>> VP.minimum $ VP.fromList [2.0, 1.0]
+-- 1.0
 minimum :: (Prim a, Ord a) => Vector a -> a
 {-# INLINE minimum #-}
 minimum = G.minimum
@@ -1202,6 +1414,13 @@
 {-# INLINE foldM #-}
 foldM = G.foldM
 
+-- | /O(n)/ Monadic fold (action applied to each element and its index)
+--
+-- @since 0.12.2.0
+ifoldM :: (Monad m, Prim b) => (a -> Int -> b -> m a) -> a -> Vector b -> m a
+{-# INLINE ifoldM #-}
+ifoldM = G.ifoldM
+
 -- | /O(n)/ Monadic fold over non-empty vectors
 fold1M :: (Monad m, Prim a) => (a -> a -> m a) -> Vector a -> m a
 {-# INLINE fold1M #-}
@@ -1212,6 +1431,14 @@
 {-# INLINE foldM' #-}
 foldM' = G.foldM'
 
+-- | /O(n)/ Monadic fold with strict accumulator (action applied to each
+-- element and its index)
+--
+-- @since 0.12.2.0
+ifoldM' :: (Monad m, Prim b) => (a -> Int -> b -> m a) -> a -> Vector b -> m a
+{-# INLINE ifoldM' #-}
+ifoldM' = G.ifoldM'
+
 -- | /O(n)/ Monadic fold over non-empty vectors with strict accumulator
 fold1M' :: (Monad m, Prim a) => (a -> a -> m a) -> Vector a -> m a
 {-# INLINE fold1M' #-}
@@ -1222,6 +1449,14 @@
 {-# INLINE foldM_ #-}
 foldM_ = G.foldM_
 
+-- | /O(n)/ Monadic fold that discards the result (action applied to each
+-- element and its index)
+--
+-- @since 0.12.2.0
+ifoldM_ :: (Monad m, Prim b) => (a -> Int -> b -> m a) -> a -> Vector b -> m ()
+{-# INLINE ifoldM_ #-}
+ifoldM_ = G.ifoldM_
+
 -- | /O(n)/ Monadic fold over non-empty vectors that discards the result
 fold1M_ :: (Monad m, Prim a) => (a -> a -> m a) -> Vector a -> m ()
 {-# INLINE fold1M_ #-}
@@ -1232,6 +1467,15 @@
 {-# INLINE foldM'_ #-}
 foldM'_ = G.foldM'_
 
+-- | /O(n)/ Monadic fold with strict accumulator that discards the result
+-- (action applied to each element and its index)
+--
+-- @since 0.12.2.0
+ifoldM'_ :: (Monad m, Prim b)
+         => (a -> Int -> b -> m a) -> a -> Vector b -> m ()
+{-# INLINE ifoldM'_ #-}
+ifoldM'_ = G.ifoldM'_
+
 -- | /O(n)/ Monadic fold over non-empty vectors with strict accumulator
 -- that discards the result
 fold1M'_ :: (Monad m, Prim a) => (a -> a -> m a) -> Vector a -> m ()
@@ -1292,6 +1536,21 @@
 {-# INLINE scanl' #-}
 scanl' = G.scanl'
 
+-- | /O(n)/ Scan over a vector with its index
+--
+-- @since 0.12.2.0
+iscanl :: (Prim a, Prim b) => (Int -> a -> b -> a) -> a -> Vector b -> Vector a
+{-# INLINE iscanl #-}
+iscanl = G.iscanl
+
+-- | /O(n)/ Scan over a vector (strictly) with its index
+--
+-- @since 0.12.2.0
+iscanl' :: (Prim a, Prim b) => (Int -> a -> b -> a) -> a -> Vector b -> Vector a
+{-# INLINE iscanl' #-}
+iscanl' = G.iscanl'
+
+
 -- | /O(n)/ Scan over a non-empty vector
 --
 -- > scanl f <x1,...,xn> = <y1,...,yn>
@@ -1342,6 +1601,20 @@
 {-# INLINE scanr' #-}
 scanr' = G.scanr'
 
+-- | /O(n)/ Right-to-left scan over a vector with its index
+--
+-- @since 0.12.2.0
+iscanr :: (Prim a, Prim b) => (Int -> a -> b -> b) -> b -> Vector a -> Vector b
+{-# INLINE iscanr #-}
+iscanr = G.iscanr
+
+-- | /O(n)/ Right-to-left scan over a vector (strictly) with its index
+--
+-- @since 0.12.2.0
+iscanr' :: (Prim a, Prim b) => (Int -> a -> b -> b) -> b -> Vector a -> Vector b
+{-# INLINE iscanr' #-}
+iscanr' = G.iscanr'
+
 -- | /O(n)/ Right-to-left scan over a non-empty vector
 scanr1 :: Prim a => (a -> a -> a) -> Vector a -> Vector a
 {-# INLINE scanr1 #-}
@@ -1353,6 +1626,26 @@
 {-# INLINE scanr1' #-}
 scanr1' = G.scanr1'
 
+-- Comparisons
+-- ------------------------
+
+-- | /O(n)/ Check if two vectors are equal using supplied equality
+-- predicate.
+--
+-- @since 0.12.2.0
+eqBy :: (Prim a, Prim b) => (a -> b -> Bool) -> Vector a -> Vector b -> Bool
+{-# INLINE eqBy #-}
+eqBy = G.eqBy
+
+-- | /O(n)/ Compare two vectors using supplied comparison function for
+-- vector elements. Comparison works same as for lists.
+--
+-- > cmpBy compare == compare
+--
+-- @since 0.12.2.0
+cmpBy :: (Prim a, Prim b) => (a -> b -> Ordering) -> Vector a -> Vector b -> Ordering
+cmpBy = G.cmpBy
+
 -- Conversions - Lists
 -- ------------------------
 
@@ -1371,6 +1664,14 @@
 -- @
 -- fromListN n xs = 'fromList' ('take' n xs)
 -- @
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Primitive as VP
+-- >>> VP.fromListN 3 [1,2,3,4,5::Int]
+-- [1,2,3]
+-- >>> VP.fromListN 3 [1::Int]
+-- [1]
 fromListN :: Prim a => Int -> [a] -> Vector a
 {-# INLINE fromListN #-}
 fromListN = G.fromListN
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
@@ -226,7 +226,11 @@
 {-# INLINE new #-}
 new = G.new
 
--- | Create a mutable vector of the given length. The memory is not initialized.
+-- | Create a mutable vector of the given length. The vector content
+--   is uninitialized, which means it is filled with whatever underlying memory
+--   buffer happens to contain.
+--
+-- @since 0.5
 unsafeNew :: (PrimMonad m, Prim a) => Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeNew #-}
 unsafeNew = G.unsafeNew
@@ -252,15 +256,50 @@
 -- Growing
 -- -------
 
--- | Grow a vector by the given number of elements. The number must be
--- positive.
+-- | Grow a primitive vector by the given number of elements. The number must be
+-- non-negative. Same semantics as in `G.grow` for generic vector.
+--
+-- ====__Examples__
+--
+-- >>> import qualified Data.Vector.Primitive as VP
+-- >>> import qualified Data.Vector.Primitive.Mutable as MVP
+-- >>> mv <- VP.thaw $ VP.fromList ([10, 20, 30] :: [Int])
+-- >>> mv' <- MVP.grow mv 2
+--
+-- Extra memory at the end of the newly allocated vector is initialized to 0
+-- bytes, which for `Prim` instance will usually correspond to some default
+-- value for a particular type, eg. @0@ for @Int@, @\NUL@ for @Char@,
+-- etc. However, if `unsafeGrow` was used instead this would not have been
+-- guaranteed and some garbage would be there instead:
+--
+-- >>> VP.unsafeFreeze mv'
+-- [10,20,30,0,0]
+--
+-- Having the extra space we can write new values in there:
+--
+-- >>> MVP.write mv' 3 999
+-- >>> VP.unsafeFreeze mv'
+-- [10,20,30,999,0]
+--
+-- It is important to note that the source mutable vector is not affected when
+-- the newly allocated one is mutated.
+--
+-- >>> MVP.write mv' 2 888
+-- >>> VP.unsafeFreeze mv'
+-- [10,20,888,999,0]
+-- >>> VP.unsafeFreeze mv
+-- [10,20,30]
+--
+-- @since 0.5
 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.
+-- | Grow a vector by the given number of elements. The number must be non-negative but
+-- this is not checked. Same semantics as in `G.unsafeGrow` for generic vector.
+--
+-- @since 0.5
 unsafeGrow :: (PrimMonad m, Prim a)
                => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeGrow #-}
diff --git a/Data/Vector/Storable.hs b/Data/Vector/Storable.hs
--- a/Data/Vector/Storable.hs
+++ b/Data/Vector/Storable.hs
@@ -31,7 +31,7 @@
   unsafeIndexM, unsafeHeadM, unsafeLastM,
 
   -- ** Extracting subvectors (slicing)
-  slice, init, tail, take, drop, splitAt,
+  slice, init, tail, take, drop, splitAt, uncons, unsnoc,
   unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
 
   -- * Construction
@@ -43,8 +43,8 @@
   replicateM, generateM, iterateNM, create, createT,
 
   -- ** Unfolding
-  unfoldr, unfoldrN,
-  unfoldrM, unfoldrNM,
+  unfoldr, unfoldrN, unfoldrExactN,
+  unfoldrM, unfoldrNM, unfoldrExactNM,
   constructN, constructrN,
 
   -- ** Enumeration
@@ -78,21 +78,22 @@
   map, imap, concatMap,
 
   -- ** Monadic mapping
-  mapM, mapM_, forM, forM_,
+  mapM, imapM, mapM_, imapM_, forM, forM_,
+  iforM, iforM_,
 
   -- ** Zipping
   zipWith, zipWith3, zipWith4, zipWith5, zipWith6,
   izipWith, izipWith3, izipWith4, izipWith5, izipWith6,
 
   -- ** Monadic zipping
-  zipWithM, zipWithM_,
+  zipWithM, izipWithM, zipWithM_, izipWithM_,
 
   -- * Working with predicates
 
   -- ** Filtering
-  filter, ifilter, uniq,
+  filter, ifilter, filterM, uniq,
   mapMaybe, imapMaybe,
-  filterM,
+  mapMaybeM, imapMaybeM,
   takeWhile, dropWhile,
 
   -- ** Partitioning
@@ -104,6 +105,7 @@
   -- * Folding
   foldl, foldl1, foldl', foldl1', foldr, foldr1, foldr', foldr1',
   ifoldl, ifoldl', ifoldr, ifoldr',
+  foldMap, foldMap',
 
   -- ** Specialised folds
   all, any, and, or,
@@ -112,17 +114,27 @@
   minIndex, minIndexBy, maxIndex, maxIndexBy,
 
   -- ** Monadic folds
-  foldM, foldM', fold1M, fold1M',
-  foldM_, foldM'_, fold1M_, fold1M'_,
+  foldM, ifoldM, foldM', ifoldM',
+  fold1M, fold1M', foldM_, ifoldM_,
+  foldM'_, ifoldM'_, fold1M_, fold1M'_,
 
   -- * Prefix sums (scans)
   prescanl, prescanl',
   postscanl, postscanl',
   scanl, scanl', scanl1, scanl1',
+  iscanl, iscanl',
   prescanr, prescanr',
   postscanr, postscanr',
   scanr, scanr', scanr1, scanr1',
+  iscanr, iscanr',
 
+  -- ** Comparisons
+  eqBy, cmpBy,
+
+  -- * Utilities
+  -- ** Comparisons
+  isSameVector,
+
   -- * Conversions
 
   -- ** Lists
@@ -168,6 +180,9 @@
                         filter, takeWhile, dropWhile, span, break,
                         elem, notElem,
                         foldl, foldl1, foldr, foldr1,
+#if __GLASGOW_HASKELL__ >= 706
+                        foldMap,
+#endif
                         all, any, and, or, sum, product, minimum, maximum,
                         scanl, scanl1, scanr, scanr1,
                         enumFromTo, enumFromThenTo,
@@ -453,10 +468,26 @@
 --
 -- Note that @'splitAt' n v@ is equivalent to @('take' n v, 'drop' n v)@
 -- but slightly more efficient.
-{-# INLINE splitAt #-}
+--
+-- @since 0.7.1
 splitAt :: Storable a => Int -> Vector a -> (Vector a, Vector a)
+{-# INLINE splitAt #-}
 splitAt = G.splitAt
 
+-- | /O(1)/ Yield the 'head' and 'tail' of the vector, or 'Nothing' if empty.
+--
+-- @since 0.12.2.0
+uncons :: Storable a => Vector a -> Maybe (a, Vector a)
+{-# INLINE uncons #-}
+uncons = G.uncons
+
+-- | /O(1)/ Yield the 'last' and 'init' of the vector, or 'Nothing' if empty.
+--
+-- @since 0.12.2.0
+unsnoc :: Storable a => Vector a -> Maybe (Vector a, a)
+{-# INLINE unsnoc #-}
+unsnoc = G.unsnoc
+
 -- | /O(1)/ Yield a slice of the vector without copying. The vector must
 -- contain at least @i+n@ elements but this is not checked.
 unsafeSlice :: Storable a => Int   -- ^ @i@ starting index
@@ -514,7 +545,21 @@
 {-# INLINE generate #-}
 generate = G.generate
 
--- | /O(n)/ Apply function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply function \(\max(n - 1, 0)\) times to an initial value, producing a vector
+-- of length \(\max(n, 0)\). Zeroth element will contain the initial value, that's why there
+-- is one less function application than the number of elements in the produced vector.
+--
+-- \( \underbrace{x, f (x), f (f (x)), \ldots}_{\max(0,n)\rm{~elements}} \)
+--
+-- ===__Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.iterateN 0 undefined undefined :: VS.Vector Int
+-- []
+-- >>> VS.iterateN 26 succ 'a'
+-- "abcdefghijklmnopqrstuvwxyz"
+--
+-- @since 0.7.1
 iterateN :: Storable a => Int -> (a -> a) -> a -> Vector a
 {-# INLINE iterateN #-}
 iterateN = G.iterateN
@@ -541,6 +586,17 @@
 {-# INLINE unfoldrN #-}
 unfoldrN = G.unfoldrN
 
+-- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly applying
+-- the generator function to a seed. The generator function yields the
+-- next element and the new seed.
+--
+-- > unfoldrExactN 3 (\n -> (n,n-1)) 10 = <10,9,8>
+--
+-- @since 0.12.2.0
+unfoldrExactN :: (Storable a) => Int -> (b -> (a, b)) -> b -> Vector a
+{-# INLINE unfoldrExactN #-}
+unfoldrExactN = G.unfoldrExactN
+
 -- | /O(n)/ Construct a vector by repeatedly applying the monadic
 -- generator function to a seed. The generator function yields 'Just'
 -- the next element and the new seed or 'Nothing' if there are no more
@@ -557,6 +613,15 @@
 {-# INLINE unfoldrNM #-}
 unfoldrNM = G.unfoldrNM
 
+-- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly
+-- applying the monadic generator function to a seed. The generator
+-- function yields the next element and the new seed.
+--
+-- @since 0.12.2.0
+unfoldrExactNM :: (Monad m, Storable a) => Int -> (b -> m (a, b)) -> b -> m (Vector a)
+{-# INLINE unfoldrExactNM #-}
+unfoldrExactNM = G.unfoldrExactNM
+
 -- | /O(n)/ Construct a vector with @n@ elements by repeatedly applying the
 -- generator function to the already constructed part of the vector.
 --
@@ -650,7 +715,13 @@
 {-# INLINE generateM #-}
 generateM = G.generateM
 
--- | /O(n)/ Apply monadic function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply monadic function \(\max(n - 1, 0)\) times to an initial value, producing a vector
+-- of length \(\max(n, 0)\). Zeroth element will contain the initial value, that's why there
+-- is one less function application than the number of elements in the produced vector.
+--
+-- For non-monadic version see `iterateN`
+--
+-- @since 0.12.0.0
 iterateNM :: (Monad m, Storable a) => Int -> (a -> m a) -> a -> m (Vector a)
 {-# INLINE iterateNM #-}
 iterateNM = G.iterateNM
@@ -731,7 +802,11 @@
 -- | /O(m+n)/ For each pair @(i,b)@ from the list, replace the vector element
 -- @a@ at position @i@ by @f a b@.
 --
--- > accum (+) <5,9,2> [(2,4),(1,6),(0,3),(1,7)] = <5+3, 9+6+7, 2+4>
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.accum (+) (VS.fromList [1000.0,2000.0,3000.0]) [(2,4),(1,6),(0,3),(1,10)]
+-- [1003.0,2016.0,3004.0]
 accum :: Storable a
       => (a -> b -> a) -- ^ accumulating function @f@
       -> Vector a      -- ^ initial vector (of length @m@)
@@ -830,12 +905,29 @@
 {-# INLINE mapM #-}
 mapM = G.mapM
 
+-- | /O(n)/ Apply the monadic action to every element of a vector and its
+-- index, yielding a vector of results
+--
+-- @since 0.12.2.0
+imapM :: (Monad m, Storable a, Storable b)
+      => (Int -> a -> m b) -> Vector a -> m (Vector b)
+{-# INLINE imapM #-}
+imapM = G.imapM
+
 -- | /O(n)/ Apply the monadic action to all elements of a vector and ignore the
 -- results
 mapM_ :: (Monad m, Storable a) => (a -> m b) -> Vector a -> m ()
 {-# INLINE mapM_ #-}
 mapM_ = G.mapM_
 
+-- | /O(n)/ Apply the monadic action to every element of a vector and its
+-- index, ignoring the results
+--
+-- @since 0.12.2.0
+imapM_ :: (Monad m, Storable a) => (Int -> a -> m b) -> Vector a -> m ()
+{-# INLINE imapM_ #-}
+imapM_ = G.imapM_
+
 -- | /O(n)/ Apply the monadic action to all elements of the vector, yielding a
 -- vector of results. Equivalent to @flip 'mapM'@.
 forM :: (Monad m, Storable a, Storable b) => Vector a -> (a -> m b) -> m (Vector b)
@@ -848,6 +940,22 @@
 {-# INLINE forM_ #-}
 forM_ = G.forM_
 
+-- | /O(n)/ Apply the monadic action to all elements of the vector and their indices, yielding a
+-- vector of results. Equivalent to 'flip' 'imapM'.
+--
+-- @since 0.12.2.0
+iforM :: (Monad m, Storable a, Storable b) => Vector a -> (Int -> a -> m b) -> m (Vector b)
+{-# INLINE iforM #-}
+iforM = G.iforM
+
+-- | /O(n)/ Apply the monadic action to all elements of the vector and their indices and ignore the
+-- results. Equivalent to 'flip' 'imapM_'.
+--
+-- @since 0.12.2.0
+iforM_ :: (Monad m, Storable a) => Vector a -> (Int -> a -> m b) -> m ()
+{-# INLINE iforM_ #-}
+iforM_ = G.iforM_
+
 -- Zipping
 -- -------
 
@@ -921,6 +1029,16 @@
 {-# INLINE izipWith6 #-}
 izipWith6 = G.izipWith6
 
+-- | Checks whether two values are same vector: they have same length
+--   and share same buffer.
+--
+-- >>> let xs = fromList [0/0::Double] in isSameVector xs xs
+-- True
+isSameVector :: (Storable a) => Vector a -> Vector a -> Bool
+{-# INLINE isSameVector #-}
+isSameVector (Vector n1 ptr1) (Vector n2 ptr2) = n1 == n2 && ptr1 == ptr2
+
+
 -- Monadic zipping
 -- ---------------
 
@@ -931,6 +1049,15 @@
 {-# INLINE zipWithM #-}
 zipWithM = G.zipWithM
 
+-- | /O(min(m,n))/ Zip the two vectors with a monadic action that also takes
+-- the element index and yield a vector of results
+--
+-- @since 0.12.2.0
+izipWithM :: (Monad m, Storable a, Storable b, Storable c)
+          => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m (Vector c)
+{-# INLINE izipWithM #-}
+izipWithM = G.izipWithM
+
 -- | /O(min(m,n))/ Zip the two vectors with the monadic action and ignore the
 -- results
 zipWithM_ :: (Monad m, Storable a, Storable b)
@@ -938,6 +1065,15 @@
 {-# INLINE zipWithM_ #-}
 zipWithM_ = G.zipWithM_
 
+-- | /O(min(m,n))/ Zip the two vectors with a monadic action that also takes
+-- the element index and ignore the results
+--
+-- @since 0.12.2.0
+izipWithM_ :: (Monad m, Storable a, Storable b)
+           => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m ()
+{-# INLINE izipWithM_ #-}
+izipWithM_ = G.izipWithM_
+
 -- Filtering
 -- ---------
 
@@ -967,13 +1103,34 @@
 {-# INLINE imapMaybe #-}
 imapMaybe = G.imapMaybe
 
+-- | /O(n)/ Apply monadic function to each element of vector and
+-- discard elements returning Nothing.
+--
+-- @since 0.12.2.0
+mapMaybeM
+  :: (Monad m, Storable a, Storable b)
+  => (a -> m (Maybe b)) -> Vector a -> m (Vector b)
+{-# INLINE mapMaybeM #-}
+mapMaybeM = G.mapMaybeM
+
+-- | /O(n)/ Apply monadic function to each element of vector and its index.
+-- Discards elements returning Nothing.
+--
+-- @since 0.12.2.0
+imapMaybeM
+  :: (Monad m, Storable a, Storable b)
+  => (Int -> a -> m (Maybe b)) -> Vector a -> m (Vector b)
+{-# INLINE imapMaybeM #-}
+imapMaybeM = G.imapMaybeM
+
 -- | /O(n)/ Drop elements that do not satisfy the monadic predicate
 filterM :: (Monad m, Storable a) => (a -> m Bool) -> Vector a -> m (Vector a)
 {-# INLINE filterM #-}
 filterM = G.filterM
 
--- | /O(n)/ Yield the longest prefix of elements satisfying the predicate
--- without copying.
+-- | /O(n)/ Yield the longest prefix of elements satisfying the predicate.
+-- Current implementation is not copy-free, unless the result vector is
+-- fused away.
 takeWhile :: Storable a => (a -> Bool) -> Vector a -> Vector a
 {-# INLINE takeWhile #-}
 takeWhile = G.takeWhile
@@ -1003,11 +1160,11 @@
 {-# INLINE unstablePartition #-}
 unstablePartition = G.unstablePartition
 
--- | /O(n)/ Split the vector in two parts, the first one containing the
---   @Right@ elements and the second containing the @Left@ elements.
---   The relative order of the elements is preserved.
+-- | /O(n)/ Split the vector into two parts, the first one containing the
+-- @`Left`@ elements and the second containing the @`Right`@ elements.
+-- The relative order of the elements is preserved.
 --
---   @since 0.12.1.0
+-- @since 0.12.1.0
 partitionWith :: (Storable a, Storable b, Storable c) => (a -> Either b c) -> Vector a -> (Vector b, Vector c)
 {-# INLINE partitionWith #-}
 partitionWith = G.partitionWith
@@ -1135,41 +1292,120 @@
 {-# INLINE ifoldr' #-}
 ifoldr' = G.ifoldr'
 
+-- | /O(n)/ Map each element of the structure to a monoid, and combine
+-- the results. It uses same implementation as corresponding method of
+-- 'Foldable' type cless. Note it's implemented in terms of 'foldr'
+-- and won't fuse with functions that traverse vector from left to
+-- right ('map', 'generate', etc.).
+--
+-- @since 0.12.2.0
+foldMap :: (Monoid m, Storable a) => (a -> m) -> Vector a -> m
+{-# INLINE foldMap #-}
+foldMap = G.foldMap
+
+-- | /O(n)/ 'foldMap' which is strict in accumulator. It uses same
+-- implementation as corresponding method of 'Foldable' type class.
+-- Note it's implemented in terms of 'foldl'' so it fuses in most
+-- contexts.
+--
+-- @since 0.12.2.0
+foldMap' :: (Monoid m, Storable a) => (a -> m) -> Vector a -> m
+{-# INLINE foldMap' #-}
+foldMap' = G.foldMap'
+
 -- Specialised folds
 -- -----------------
 
 -- | /O(n)/ Check if all elements satisfy the predicate.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.all even $ VS.fromList [2, 4, 12 :: Int]
+-- True
+-- >>> VS.all even $ VS.fromList [2, 4, 13 :: Int]
+-- False
+-- >>> VS.all even (VS.empty :: VS.Vector Int)
+-- True
 all :: Storable a => (a -> Bool) -> Vector a -> Bool
 {-# INLINE all #-}
 all = G.all
 
 -- | /O(n)/ Check if any element satisfies the predicate.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.any even $ VS.fromList [1, 3, 7 :: Int]
+-- False
+-- >>> VS.any even $ VS.fromList [3, 2, 13 :: Int]
+-- True
+-- >>> VS.any even (VS.empty :: VS.Vector Int)
+-- False
 any :: Storable a => (a -> Bool) -> Vector a -> Bool
 {-# INLINE any #-}
 any = G.any
 
 -- | /O(n)/ Check if all elements are 'True'
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.and $ VS.fromList [True, False]
+-- False
+-- >>> VS.and VS.empty
+-- True
 and :: Vector Bool -> Bool
 {-# INLINE and #-}
 and = G.and
 
 -- | /O(n)/ Check if any element is 'True'
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.or $ VS.fromList [True, False]
+-- True
+-- >>> VS.or VS.empty
+-- False
 or :: Vector Bool -> Bool
 {-# INLINE or #-}
 or = G.or
 
 -- | /O(n)/ Compute the sum of the elements
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.sum $ VS.fromList [300,20,1 :: Int]
+-- 321
+-- >>> VS.sum (VS.empty :: VS.Vector Int)
+-- 0
 sum :: (Storable a, Num a) => Vector a -> a
 {-# INLINE sum #-}
 sum = G.sum
 
 -- | /O(n)/ Compute the produce of the elements
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.product $ VS.fromList [1,2,3,4 :: Int]
+-- 24
+-- >>> VS.product (VS.empty :: VS.Vector Int)
+-- 1
 product :: (Storable a, Num a) => Vector a -> a
 {-# INLINE product #-}
 product = G.product
 
 -- | /O(n)/ Yield the maximum element of the vector. The vector may not be
 -- empty.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.maximum $ VS.fromList [2.0, 1.0]
+-- 2.0
 maximum :: (Storable a, Ord a) => Vector a -> a
 {-# INLINE maximum #-}
 maximum = G.maximum
@@ -1182,6 +1418,12 @@
 
 -- | /O(n)/ Yield the minimum element of the vector. The vector may not be
 -- empty.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.minimum $ VS.fromList [2.0, 1.0]
+-- 1.0
 minimum :: (Storable a, Ord a) => Vector a -> a
 {-# INLINE minimum #-}
 minimum = G.minimum
@@ -1224,6 +1466,13 @@
 {-# INLINE foldM #-}
 foldM = G.foldM
 
+-- | /O(n)/ Monadic fold (action applied to each element and its index)
+--
+-- @since 0.12.2.0
+ifoldM :: (Monad m, Storable b) => (a -> Int -> b -> m a) -> a -> Vector b -> m a
+{-# INLINE ifoldM #-}
+ifoldM = G.ifoldM
+
 -- | /O(n)/ Monadic fold over non-empty vectors
 fold1M :: (Monad m, Storable a) => (a -> a -> m a) -> Vector a -> m a
 {-# INLINE fold1M #-}
@@ -1234,6 +1483,14 @@
 {-# INLINE foldM' #-}
 foldM' = G.foldM'
 
+-- | /O(n)/ Monadic fold with strict accumulator (action applied to each
+-- element and its index)
+--
+-- @since 0.12.2.0
+ifoldM' :: (Monad m, Storable b) => (a -> Int -> b -> m a) -> a -> Vector b -> m a
+{-# INLINE ifoldM' #-}
+ifoldM' = G.ifoldM'
+
 -- | /O(n)/ Monadic fold over non-empty vectors with strict accumulator
 fold1M' :: (Monad m, Storable a) => (a -> a -> m a) -> Vector a -> m a
 {-# INLINE fold1M' #-}
@@ -1244,6 +1501,14 @@
 {-# INLINE foldM_ #-}
 foldM_ = G.foldM_
 
+-- | /O(n)/ Monadic fold that discards the result (action applied to each
+-- element and its index)
+--
+-- @since 0.12.2.0
+ifoldM_ :: (Monad m, Storable b) => (a -> Int -> b -> m a) -> a -> Vector b -> m ()
+{-# INLINE ifoldM_ #-}
+ifoldM_ = G.ifoldM_
+
 -- | /O(n)/ Monadic fold over non-empty vectors that discards the result
 fold1M_ :: (Monad m, Storable a) => (a -> a -> m a) -> Vector a -> m ()
 {-# INLINE fold1M_ #-}
@@ -1254,6 +1519,15 @@
 {-# INLINE foldM'_ #-}
 foldM'_ = G.foldM'_
 
+-- | /O(n)/ Monadic fold with strict accumulator that discards the result
+-- (action applied to each element and its index)
+--
+-- @since 0.12.2.0
+ifoldM'_ :: (Monad m, Storable b)
+         => (a -> Int -> b -> m a) -> a -> Vector b -> m ()
+{-# INLINE ifoldM'_ #-}
+ifoldM'_ = G.ifoldM'_
+
 -- | /O(n)/ Monadic fold over non-empty vectors with strict accumulator
 -- that discards the result
 fold1M'_ :: (Monad m, Storable a) => (a -> a -> m a) -> Vector a -> m ()
@@ -1314,6 +1588,20 @@
 {-# INLINE scanl' #-}
 scanl' = G.scanl'
 
+-- | /O(n)/ Scan over a vector with its index
+--
+-- @since 0.12.2.0
+iscanl :: (Storable a, Storable b) => (Int -> a -> b -> a) -> a -> Vector b -> Vector a
+{-# INLINE iscanl #-}
+iscanl = G.iscanl
+
+-- | /O(n)/ Scan over a vector (strictly) with its index
+--
+-- @since 0.12.2.0
+iscanl' :: (Storable a, Storable b) => (Int -> a -> b -> a) -> a -> Vector b -> Vector a
+{-# INLINE iscanl' #-}
+iscanl' = G.iscanl'
+
 -- | /O(n)/ Scan over a non-empty vector
 --
 -- > scanl f <x1,...,xn> = <y1,...,yn>
@@ -1364,6 +1652,20 @@
 {-# INLINE scanr' #-}
 scanr' = G.scanr'
 
+-- | /O(n)/ Right-to-left scan over a vector with its index
+--
+-- @since 0.12.2.0
+iscanr :: (Storable a, Storable b) => (Int -> a -> b -> b) -> b -> Vector a -> Vector b
+{-# INLINE iscanr #-}
+iscanr = G.iscanr
+
+-- | /O(n)/ Right-to-left scan over a vector (strictly) with its index
+--
+-- @since 0.12.2.0
+iscanr' :: (Storable a, Storable b) => (Int -> a -> b -> b) -> b -> Vector a -> Vector b
+{-# INLINE iscanr' #-}
+iscanr' = G.iscanr'
+
 -- | /O(n)/ Right-to-left scan over a non-empty vector
 scanr1 :: Storable a => (a -> a -> a) -> Vector a -> Vector a
 {-# INLINE scanr1 #-}
@@ -1375,6 +1677,26 @@
 {-# INLINE scanr1' #-}
 scanr1' = G.scanr1'
 
+-- Comparisons
+-- ------------------------
+
+-- | /O(n)/ Check if two vectors are equal using supplied equality
+-- predicate.
+--
+-- @since 0.12.2.0
+eqBy :: (Storable a, Storable b) => (a -> b -> Bool) -> Vector a -> Vector b -> Bool
+{-# INLINE eqBy #-}
+eqBy = G.eqBy
+
+-- | /O(n)/ Compare two vectors using supplied comparison function for
+-- vector elements. Comparison works same as for lists.
+--
+-- > cmpBy compare == compare
+--
+-- @since 0.12.2.0
+cmpBy :: (Storable a, Storable b) => (a -> b -> Ordering) -> Vector a -> Vector b -> Ordering
+cmpBy = G.cmpBy
+
 -- Conversions - Lists
 -- ------------------------
 
@@ -1393,6 +1715,14 @@
 -- @
 -- fromListN n xs = 'fromList' ('take' n xs)
 -- @
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> VS.fromListN 3 [1,2,3,4,5::Int]
+-- [1,2,3]
+-- >>> VS.fromListN 3 [1::Int]
+-- [1]
 fromListN :: Storable a => Int -> [a] -> Vector a
 {-# INLINE fromListN #-}
 fromListN = G.fromListN
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
@@ -354,7 +354,11 @@
 {-# INLINE new #-}
 new = G.new
 
--- | Create a mutable vector of the given length. The memory is not initialized.
+-- | Create a mutable vector of the given length. The vector content
+--   is uninitialized, which means it is filled with whatever underlying memory
+--   buffer happens to contain.
+--
+-- @since 0.5
 unsafeNew :: (PrimMonad m, Storable a) => Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeNew #-}
 unsafeNew = G.unsafeNew
@@ -380,15 +384,50 @@
 -- Growing
 -- -------
 
--- | Grow a vector by the given number of elements. The number must be
--- positive.
+-- | Grow a storable vector by the given number of elements. The number must be
+-- non-negative. Same semantics as in `G.grow` for generic vector.
+--
+-- ====__Examples__
+--
+-- >>> import qualified Data.Vector.Storable as VS
+-- >>> import qualified Data.Vector.Storable.Mutable as MVS
+-- >>> mv <- VS.thaw $ VS.fromList ([10, 20, 30] :: [Int])
+-- >>> mv' <- MVS.grow mv 2
+--
+-- Extra memory at the end of the newly allocated vector is initialized to 0
+-- bytes, which for `Storable` instance will usually correspond to some default
+-- value for a particular type, eg. @0@ for @Int@, @False@ for @Bool@,
+-- etc. However, if `unsafeGrow` was used instead this would not have been
+-- guaranteed and some garbage would be there instead:
+--
+-- >>> VS.unsafeFreeze mv'
+-- [10,20,30,0,0]
+--
+-- Having the extra space we can write new values in there:
+--
+-- >>> MVS.write mv' 3 999
+-- >>> VS.unsafeFreeze mv'
+-- [10,20,30,999,0]
+--
+-- It is important to note that the source mutable vector is not affected when
+-- the newly allocated one is mutated.
+--
+-- >>> MVS.write mv' 2 888
+-- >>> VS.unsafeFreeze mv'
+-- [10,20,888,999,0]
+-- >>> VS.unsafeFreeze mv
+-- [10,20,30]
+--
+-- @since 0.5
 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.
+-- | Grow a vector by the given number of elements. The number must be non-negative but
+-- this is not checked. Same semantics as in `G.unsafeGrow` for generic vector.
+--
+-- @since 0.5
 unsafeGrow :: (PrimMonad m, Storable a)
            => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeGrow #-}
@@ -583,4 +622,3 @@
 unsafeWith :: Storable a => IOVector a -> (Ptr a -> IO b) -> IO b
 {-# INLINE unsafeWith #-}
 unsafeWith (MVector _ fp) = withForeignPtr fp
-
diff --git a/Data/Vector/Unboxed.hs b/Data/Vector/Unboxed.hs
--- a/Data/Vector/Unboxed.hs
+++ b/Data/Vector/Unboxed.hs
@@ -53,7 +53,7 @@
   unsafeIndexM, unsafeHeadM, unsafeLastM,
 
   -- ** Extracting subvectors (slicing)
-  slice, init, tail, take, drop, splitAt,
+  slice, init, tail, take, drop, splitAt, uncons, unsnoc,
   unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
 
   -- * Construction
@@ -65,8 +65,8 @@
   replicateM, generateM, iterateNM, create, createT,
 
   -- ** Unfolding
-  unfoldr, unfoldrN,
-  unfoldrM, unfoldrNM,
+  unfoldr, unfoldrN, unfoldrExactN,
+  unfoldrM, unfoldrNM, unfoldrExactNM,
   constructN, constructrN,
 
   -- ** Enumeration
@@ -104,6 +104,7 @@
 
   -- ** Monadic mapping
   mapM, imapM, mapM_, imapM_, forM, forM_,
+  iforM, iforM_,
 
   -- ** Zipping
   zipWith, zipWith3, zipWith4, zipWith5, zipWith6,
@@ -119,9 +120,9 @@
   -- * Working with predicates
 
   -- ** Filtering
-  filter, ifilter, uniq,
+  filter, ifilter, filterM, uniq,
   mapMaybe, imapMaybe,
-  filterM,
+  mapMaybeM, imapMaybeM,
   takeWhile, dropWhile,
 
   -- ** Partitioning
@@ -133,6 +134,7 @@
   -- * Folding
   foldl, foldl1, foldl', foldl1', foldr, foldr1, foldr', foldr1',
   ifoldl, ifoldl', ifoldr, ifoldr',
+  foldMap, foldMap',
 
   -- ** Specialised folds
   all, any, and, or,
@@ -149,10 +151,15 @@
   prescanl, prescanl',
   postscanl, postscanl',
   scanl, scanl', scanl1, scanl1',
+  iscanl, iscanl',
   prescanr, prescanr',
   postscanr, postscanr',
   scanr, scanr', scanr1, scanr1',
+  iscanr, iscanr',
 
+  -- ** Comparisons
+  eqBy, cmpBy,
+
   -- * Conversions
 
   -- ** Lists
@@ -182,6 +189,9 @@
                         filter, takeWhile, dropWhile, span, break,
                         elem, notElem,
                         foldl, foldl1, foldr, foldr1,
+#if __GLASGOW_HASKELL__ >= 706
+                        foldMap,
+#endif
                         all, any, and, or, sum, product, minimum, maximum,
                         scanl, scanl1, scanr, scanr1,
                         enumFromTo, enumFromThenTo,
@@ -408,10 +418,26 @@
 --
 -- Note that @'splitAt' n v@ is equivalent to @('take' n v, 'drop' n v)@
 -- but slightly more efficient.
-{-# INLINE splitAt #-}
+--
+-- @since 0.7.1
 splitAt :: Unbox a => Int -> Vector a -> (Vector a, Vector a)
+{-# INLINE splitAt #-}
 splitAt = G.splitAt
 
+-- | /O(1)/ Yield the 'head' and 'tail' of the vector, or 'Nothing' if empty.
+--
+-- @since 0.12.2.0
+uncons :: Unbox a => Vector a -> Maybe (a, Vector a)
+{-# INLINE uncons #-}
+uncons = G.uncons
+
+-- | /O(1)/ Yield the 'last' and 'init' of the vector, or 'Nothing' if empty.
+--
+-- @since 0.12.2.0
+unsnoc :: Unbox a => Vector a -> Maybe (Vector a, a)
+{-# INLINE unsnoc #-}
+unsnoc = G.unsnoc
+
 -- | /O(1)/ Yield a slice of the vector without copying. The vector must
 -- contain at least @i+n@ elements but this is not checked.
 unsafeSlice :: Unbox a => Int   -- ^ @i@ starting index
@@ -469,7 +495,21 @@
 {-# INLINE generate #-}
 generate = G.generate
 
--- | /O(n)/ Apply function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply function \(\max(n - 1, 0)\) times to an initial value, producing a vector
+-- of length \(\max(n, 0)\). Zeroth element will contain the initial value, that's why there
+-- is one less function application than the number of elements in the produced vector.
+--
+-- \( \underbrace{x, f (x), f (f (x)), \ldots}_{\max(0,n)\rm{~elements}} \)
+--
+-- ===__Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.iterateN 0 undefined undefined :: VU.Vector Int
+-- []
+-- >>> VU.iterateN 3 (\(i, c) -> (pred i, succ c)) (0 :: Int, 'a')
+-- [(0,'a'),(-1,'b'),(-2,'c')]
+--
+-- @since 0.7.1
 iterateN :: Unbox a => Int -> (a -> a) -> a -> Vector a
 {-# INLINE iterateN #-}
 iterateN = G.iterateN
@@ -496,6 +536,17 @@
 {-# INLINE unfoldrN #-}
 unfoldrN = G.unfoldrN
 
+-- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly applying
+-- the generator function to a seed. The generator function yields the
+-- next element and the new seed.
+--
+-- > unfoldrExactN 3 (\n -> (n,n-1)) 10 = <10,9,8>
+--
+-- @since 0.12.2.0
+unfoldrExactN  :: Unbox a => Int -> (b -> (a, b)) -> b -> Vector a
+{-# INLINE unfoldrExactN #-}
+unfoldrExactN = G.unfoldrExactN
+
 -- | /O(n)/ Construct a vector by repeatedly applying the monadic
 -- generator function to a seed. The generator function yields 'Just'
 -- the next element and the new seed or 'Nothing' if there are no more
@@ -512,6 +563,15 @@
 {-# INLINE unfoldrNM #-}
 unfoldrNM = G.unfoldrNM
 
+-- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly
+-- applying the monadic generator function to a seed. The generator
+-- function yields the next element and the new seed.
+--
+-- @since 0.12.2.0
+unfoldrExactNM :: (Monad m, Unbox a) => Int -> (b -> m (a, b)) -> b -> m (Vector a)
+{-# INLINE unfoldrExactNM #-}
+unfoldrExactNM = G.unfoldrExactNM
+
 -- | /O(n)/ Construct a vector with @n@ elements by repeatedly applying the
 -- generator function to the already constructed part of the vector.
 --
@@ -605,7 +665,13 @@
 {-# INLINE generateM #-}
 generateM = G.generateM
 
--- | /O(n)/ Apply monadic function n times to value. Zeroth element is original value.
+-- | /O(n)/ Apply monadic function \(\max(n - 1, 0)\) times to an initial value, producing a vector
+-- of length \(\max(n, 0)\). Zeroth element will contain the initial value, that's why there
+-- is one less function application than the number of elements in the produced vector.
+--
+-- For non-monadic version see `iterateN`
+--
+-- @since 0.12.0.0
 iterateNM :: (Monad m, Unbox a) => Int -> (a -> m a) -> a -> m (Vector a)
 {-# INLINE iterateNM #-}
 iterateNM = G.iterateNM
@@ -709,7 +775,11 @@
 -- | /O(m+n)/ For each pair @(i,b)@ from the list, replace the vector element
 -- @a@ at position @i@ by @f a b@.
 --
--- > accum (+) <5,9,2> [(2,4),(1,6),(0,3),(1,7)] = <5+3, 9+6+7, 2+4>
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.accum (+) (VU.fromList [1000.0,2000.0,3000.0]) [(2,4),(1,6),(0,3),(1,10)]
+-- [1003.0,2016.0,3004.0]
 accum :: Unbox a
       => (a -> b -> a) -- ^ accumulating function @f@
       -> Vector a      -- ^ initial vector (of length @m@)
@@ -721,7 +791,11 @@
 -- | /O(m+n)/ For each pair @(i,b)@ from the vector of pairs, replace the vector
 -- element @a@ at position @i@ by @f a b@.
 --
--- > accumulate (+) <5,9,2> <(2,4),(1,6),(0,3),(1,7)> = <5+3, 9+6+7, 2+4>
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.accumulate (+) (VU.fromList [1000.0,2000.0,3000.0]) (VU.fromList [(2,4),(1,6),(0,3),(1,10)])
+-- [1003.0,2016.0,3004.0]
 accumulate :: (Unbox a, Unbox b)
             => (a -> b -> a)  -- ^ accumulating function @f@
             -> Vector a       -- ^ initial vector (of length @m@)
@@ -871,6 +945,22 @@
 {-# INLINE forM_ #-}
 forM_ = G.forM_
 
+-- | /O(n)/ Apply the monadic action to all elements of the vector and their indices, yielding a
+-- vector of results. Equivalent to 'flip' 'imapM'.
+--
+-- @since 0.12.2.0
+iforM :: (Monad m, Unbox a, Unbox b) => Vector a -> (Int -> a -> m b) -> m (Vector b)
+{-# INLINE iforM #-}
+iforM = G.iforM
+
+-- | /O(n)/ Apply the monadic action to all elements of the vector and their indices and ignore the
+-- results. Equivalent to 'flip' 'imapM_'.
+--
+-- @since 0.12.2.0
+iforM_ :: (Monad m, Unbox a) => Vector a -> (Int -> a -> m b) -> m ()
+{-# INLINE iforM_ #-}
+iforM_ = G.iforM_
+
 -- Zipping
 -- -------
 
@@ -953,7 +1043,7 @@
 -- | /O(min(m,n))/ Zip the two vectors with a monadic action that also takes
 -- the element index and yield a vector of results
 izipWithM :: (Monad m, Unbox a, Unbox b, Unbox c)
-         => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m (Vector c)
+          => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m (Vector c)
 {-# INLINE izipWithM #-}
 izipWithM = G.izipWithM
 
@@ -967,7 +1057,7 @@
 -- | /O(min(m,n))/ Zip the two vectors with a monadic action that also takes
 -- the element index and ignore the results
 izipWithM_ :: (Monad m, Unbox a, Unbox b)
-          => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m ()
+           => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m ()
 {-# INLINE izipWithM_ #-}
 izipWithM_ = G.izipWithM_
 
@@ -1000,13 +1090,30 @@
 {-# INLINE imapMaybe #-}
 imapMaybe = G.imapMaybe
 
+-- | /O(n)/ Apply monadic function to each element of vector and
+-- discard elements returning Nothing.
+--
+-- @since 0.12.2.0
+mapMaybeM :: (Monad m, Unbox a, Unbox b) => (a -> m (Maybe b)) -> Vector a -> m (Vector b)
+{-# INLINE mapMaybeM #-}
+mapMaybeM = G.mapMaybeM
+
+-- | /O(n)/ Apply monadic function to each element of vector and its index.
+-- Discards elements returning Nothing.
+--
+-- @since 0.12.2.0
+imapMaybeM :: (Monad m, Unbox a, Unbox b) => (Int -> a -> m (Maybe b)) -> Vector a -> m (Vector b)
+{-# INLINE imapMaybeM #-}
+imapMaybeM = G.imapMaybeM
+
 -- | /O(n)/ Drop elements that do not satisfy the monadic predicate
 filterM :: (Monad m, Unbox a) => (a -> m Bool) -> Vector a -> m (Vector a)
 {-# INLINE filterM #-}
 filterM = G.filterM
 
--- | /O(n)/ Yield the longest prefix of elements satisfying the predicate
--- without copying.
+-- | /O(n)/ Yield the longest prefix of elements satisfying the predicate.
+-- Current implementation is not copy-free, unless the result vector is
+-- fused away.
 takeWhile :: Unbox a => (a -> Bool) -> Vector a -> Vector a
 {-# INLINE takeWhile #-}
 takeWhile = G.takeWhile
@@ -1036,11 +1143,11 @@
 {-# INLINE unstablePartition #-}
 unstablePartition = G.unstablePartition
 
--- | /O(n)/ Split the vector in two parts, the first one containing the
---   @Right@ elements and the second containing the @Left@ elements.
---   The relative order of the elements is preserved.
+-- | /O(n)/ Split the vector into two parts, the first one containing the
+-- @`Left`@ elements and the second containing the @`Right`@ elements.
+-- The relative order of the elements is preserved.
 --
---   @since 0.12.1.0
+-- @since 0.12.1.0
 partitionWith :: (Unbox a, Unbox b, Unbox c) => (a -> Either b c) -> Vector a -> (Vector b, Vector c)
 {-# INLINE partitionWith #-}
 partitionWith = G.partitionWith
@@ -1168,41 +1275,120 @@
 {-# INLINE ifoldr' #-}
 ifoldr' = G.ifoldr'
 
+-- | /O(n)/ Map each element of the structure to a monoid, and combine
+-- the results. It uses same implementation as corresponding method of
+-- 'Foldable' type cless. Note it's implemented in terms of 'foldr'
+-- and won't fuse with functions that traverse vector from left to
+-- right ('map', 'generate', etc.).
+--
+-- @since 0.12.2.0
+foldMap :: (Monoid m, Unbox a) => (a -> m) -> Vector a -> m
+{-# INLINE foldMap #-}
+foldMap = G.foldMap
+
+-- | /O(n)/ 'foldMap' which is strict in accumulator. It uses same
+-- implementation as corresponding method of 'Foldable' type class.
+-- Note it's implemented in terms of 'foldl'' so it fuses in most
+-- contexts.
+--
+-- @since 0.12.2.0
+foldMap' :: (Monoid m, Unbox a) => (a -> m) -> Vector a -> m
+{-# INLINE foldMap' #-}
+foldMap' = G.foldMap'
+
 -- Specialised folds
 -- -----------------
 
 -- | /O(n)/ Check if all elements satisfy the predicate.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.all even $ VU.fromList [2, 4, 12 :: Int]
+-- True
+-- >>> VU.all even $ VU.fromList [2, 4, 13 :: Int]
+-- False
+-- >>> VU.all even (VU.empty :: VU.Vector Int)
+-- True
 all :: Unbox a => (a -> Bool) -> Vector a -> Bool
 {-# INLINE all #-}
 all = G.all
 
 -- | /O(n)/ Check if any element satisfies the predicate.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.any even $ VU.fromList [1, 3, 7 :: Int]
+-- False
+-- >>> VU.any even $ VU.fromList [3, 2, 13 :: Int]
+-- True
+-- >>> VU.any even (VU.empty :: VU.Vector Int)
+-- False
 any :: Unbox a => (a -> Bool) -> Vector a -> Bool
 {-# INLINE any #-}
 any = G.any
 
 -- | /O(n)/ Check if all elements are 'True'
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.and $ VU.fromList [True, False]
+-- False
+-- >>> VU.and VU.empty
+-- True
 and :: Vector Bool -> Bool
 {-# INLINE and #-}
 and = G.and
 
 -- | /O(n)/ Check if any element is 'True'
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.or $ VU.fromList [True, False]
+-- True
+-- >>> VU.or VU.empty
+-- False
 or :: Vector Bool -> Bool
 {-# INLINE or #-}
 or = G.or
 
 -- | /O(n)/ Compute the sum of the elements
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.sum $ VU.fromList [300,20,1 :: Int]
+-- 321
+-- >>> VU.sum (VU.empty :: VU.Vector Int)
+-- 0
 sum :: (Unbox a, Num a) => Vector a -> a
 {-# INLINE sum #-}
 sum = G.sum
 
 -- | /O(n)/ Compute the produce of the elements
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.product $ VU.fromList [1,2,3,4 :: Int]
+-- 24
+-- >>> VU.product (VU.empty :: VU.Vector Int)
+-- 1
 product :: (Unbox a, Num a) => Vector a -> a
 {-# INLINE product #-}
 product = G.product
 
 -- | /O(n)/ Yield the maximum element of the vector. The vector may not be
 -- empty.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.maximum $ VU.fromList [2.0, 1.0]
+-- 2.0
 maximum :: (Unbox a, Ord a) => Vector a -> a
 {-# INLINE maximum #-}
 maximum = G.maximum
@@ -1215,6 +1401,12 @@
 
 -- | /O(n)/ Yield the minimum element of the vector. The vector may not be
 -- empty.
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.minimum $ VU.fromList [2.0, 1.0]
+-- 1.0
 minimum :: (Unbox a, Ord a) => Vector a -> a
 {-# INLINE minimum #-}
 minimum = G.minimum
@@ -1371,6 +1563,20 @@
 {-# INLINE scanl' #-}
 scanl' = G.scanl'
 
+-- | /O(n)/ Scan over a vector with its index
+--
+-- @since 0.12.2.0
+iscanl :: (Unbox a, Unbox b) => (Int -> a -> b -> a) -> a -> Vector b -> Vector a
+{-# INLINE iscanl #-}
+iscanl = G.iscanl
+
+-- | /O(n)/ Scan over a vector (strictly) with its index
+--
+-- @since 0.12.2.0
+iscanl' :: (Unbox a, Unbox b) => (Int -> a -> b -> a) -> a -> Vector b -> Vector a
+{-# INLINE iscanl' #-}
+iscanl' = G.iscanl'
+
 -- | /O(n)/ Scan over a non-empty vector
 --
 -- > scanl f <x1,...,xn> = <y1,...,yn>
@@ -1421,6 +1627,20 @@
 {-# INLINE scanr' #-}
 scanr' = G.scanr'
 
+-- | /O(n)/ Right-to-left scan over a vector with its index
+--
+-- @since 0.12.2.0
+iscanr :: (Unbox a, Unbox b) => (Int -> a -> b -> b) -> b -> Vector a -> Vector b
+{-# INLINE iscanr #-}
+iscanr = G.iscanr
+
+-- | /O(n)/ Right-to-left scan over a vector (strictly) with its index
+--
+-- @sinqce 0.12.2.0
+iscanr' :: (Unbox a, Unbox b) => (Int -> a -> b -> b) -> b -> Vector a -> Vector b
+{-# INLINE iscanr' #-}
+iscanr' = G.iscanr'
+
 -- | /O(n)/ Right-to-left scan over a non-empty vector
 scanr1 :: Unbox a => (a -> a -> a) -> Vector a -> Vector a
 {-# INLINE scanr1 #-}
@@ -1432,6 +1652,26 @@
 {-# INLINE scanr1' #-}
 scanr1' = G.scanr1'
 
+-- Comparisons
+-- ------------------------
+
+-- | /O(n)/ Check if two vectors are equal using supplied equality
+-- predicate.
+--
+-- @since 0.12.2.0
+eqBy :: (Unbox a, Unbox b) => (a -> b -> Bool) -> Vector a -> Vector b -> Bool
+{-# INLINE eqBy #-}
+eqBy = G.eqBy
+
+-- | /O(n)/ Compare two vectors using supplied comparison function for
+-- vector elements. Comparison works same as for lists.
+--
+-- > cmpBy compare == compare
+--
+-- @since 0.12.2.0
+cmpBy :: (Unbox a, Unbox b) => (a -> b -> Ordering) -> Vector a -> Vector b -> Ordering
+cmpBy = G.cmpBy
+
 -- Conversions - Lists
 -- ------------------------
 
@@ -1450,6 +1690,14 @@
 -- @
 -- fromListN n xs = 'fromList' ('take' n xs)
 -- @
+--
+-- ==== __Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> VU.fromListN 3 [1,2,3,4,5::Int]
+-- [1,2,3]
+-- >>> VU.fromListN 3 [1::Int]
+-- [1]
 fromListN :: Unbox a => Int -> [a] -> Vector a
 {-# INLINE fromListN #-}
 fromListN = G.fromListN
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
@@ -155,7 +155,11 @@
 {-# INLINE new #-}
 new = G.new
 
--- | Create a mutable vector of the given length. The memory is not initialized.
+-- | Create a mutable vector of the given length. The vector content
+--   is uninitialized, which means it is filled with whatever underlying memory
+--   buffer happens to contain.
+--
+-- @since 0.5
 unsafeNew :: (PrimMonad m, Unbox a) => Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeNew #-}
 unsafeNew = G.unsafeNew
@@ -181,15 +185,50 @@
 -- Growing
 -- -------
 
--- | Grow a vector by the given number of elements. The number must be
--- positive.
+-- | Grow an unboxed vector by the given number of elements. The number must be
+-- non-negative. Same semantics as in `G.grow` for generic vector.
+--
+-- ====__Examples__
+--
+-- >>> import qualified Data.Vector.Unboxed as VU
+-- >>> import qualified Data.Vector.Unboxed.Mutable as MVU
+-- >>> mv <- VU.thaw $ VU.fromList ([('a', 10), ('b', 20), ('c', 30)] :: [(Char, Int)])
+-- >>> mv' <- MVU.grow mv 2
+--
+-- Extra memory at the end of the newly allocated vector is initialized to 0
+-- bytes, which for `Unbox` instance will usually correspond to some default
+-- value for a particular type, eg. @0@ for @Int@, @False@ for @Bool@,
+-- etc. However, if `unsafeGrow` was used instead this would not have been
+-- guaranteed and some garbage would be there instead:
+--
+-- >>> VU.unsafeFreeze mv'
+-- [('a',10),('b',20),('c',30),('\NUL',0),('\NUL',0)]
+--
+-- Having the extra space we can write new values in there:
+--
+-- >>> MVU.write mv' 3 ('d', 999)
+-- >>> VU.unsafeFreeze mv'
+-- [('a',10),('b',20),('c',30),('d',999),('\NUL',0)]
+--
+-- It is important to note that the source mutable vector is not affected when
+-- the newly allocated one is mutated.
+--
+-- >>> MVU.write mv' 2 ('X', 888)
+-- >>> VU.unsafeFreeze mv'
+-- [('a',10),('b',20),('X',888),('d',999),('\NUL',0)]
+-- >>> VU.unsafeFreeze mv
+-- [('a',10),('b',20),('c',30)]
+--
+-- @since 0.5
 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.
+-- | Grow a vector by the given number of elements. The number must be non-negative but
+-- this is not checked. Same semantics as in `G.unsafeGrow` for generic vector.
+--
+-- @since 0.5
 unsafeGrow :: (PrimMonad m, Unbox a)
                => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
 {-# INLINE unsafeGrow #-}
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,22 @@
+# Changes in version 0.12.2.0
+
+ * Add `MINIMAL` pragma to `Vector` & `MVector` type classes: [#11](https://github.com/haskell/vector/issues/11)
+ * Export `unstreamM` from`from Data.Vector.Generic`: [#70](https://github.com/haskell/vector/issues/70)
+ * New functions: `unfoldrExactN` and `unfoldrExactNM`: [#140](https://github.com/haskell/vector/issues/140)
+ * Added `iforM` and `iforM_`: [#262](https://github.com/haskell/vector/issues/262)
+ * Added `MonadFix` instance for boxed vectors: [#178](https://github.com/haskell/vector/issues/178)
+ * Added `uncons` and `unsnoc`: [#212](https://github.com/haskell/vector/issues/212)
+ * Added `foldMap` and `foldMap'`: [#263](https://github.com/haskell/vector/issues/263)
+ * Added `isSameVector` for storable vectors
+ * Added `toArray`, `fromArray`, `toMutableArray` and `fromMutableArray`
+ * Added `iscanl`, `iscanl'`, `iscanr`, `iscanr'` to `Primitive`, `Storable` and `Unboxed`
+ * Added `izipWithM`, `izipWithM_`, `imapM` and `imapM_` to `Primitive` and `Storable`
+ * Added `ifoldM`, `ifoldM'`, `ifoldM_` and `ifoldM'_` to `Primitive` and `Storable`
+ * Added `eqBy` and `cmpBy`
+ * Added `findIndexR` to `Generic`: [#172](https://github.com/haskell/vector/issues/172)
+ * Added `catMaybes`: [#329](https://github.com/haskell/vector/issues/329)
+ * Added `mapMaybeM` and `imapMaybeM`: [#183](https://github.com/haskell/vector/issues/183)
+
 # Changes in version 0.12.1.2
 
  * Fix for lost function `Data.Vector.Generic.mkType`: [#287](https://github.com/haskell/vector/issues/287)
diff --git a/tests/Tests/Vector/Boxed.hs b/tests/Tests/Vector/Boxed.hs
--- a/tests/Tests/Vector/Boxed.hs
+++ b/tests/Tests/Vector/Boxed.hs
@@ -21,6 +21,7 @@
   , testMonadFunctions
   , testApplicativeFunctions
   , testAlternativeFunctions
+  , testSequenceFunctions
   , testDataFunctions
   ]
 
diff --git a/tests/Tests/Vector/Property.hs b/tests/Tests/Vector/Property.hs
--- a/tests/Tests/Vector/Property.hs
+++ b/tests/Tests/Vector/Property.hs
@@ -13,6 +13,7 @@
   , testMonadFunctions
   , testApplicativeFunctions
   , testAlternativeFunctions
+  , testSequenceFunctions
   , testBoolFunctions
   , testNumFunctions
   , testNestedVectorFunctions
@@ -20,12 +21,13 @@
   -- re-exports
   , Data
   , Random
-  ,Test
+  , Test
   ) where
 
 import Boilerplater
 import Utilities as Util hiding (limitUnfolds)
 
+import Control.Monad
 import Data.Functor.Identity
 import qualified Data.Traversable as T (Traversable(..))
 import Data.Foldable (Foldable(foldMap))
@@ -67,37 +69,12 @@
 type Test = TestTree
 -- TODO: implement Vector equivalents of list functions for some of the commented out properties
 
--- TODO: test and implement some of these other Prelude functions:
---  mapM *
---  mapM_ *
---  sequence
---  sequence_
---  sum *
---  product *
---  scanl *
---  scanl1 *
---  scanr *
---  scanr1 *
---  lookup *
---  lines
---  words
---  unlines
---  unwords
--- NB: this is an exhaustive list of all Prelude list functions that make sense for vectors.
--- Ones with *s are the most plausible candidates.
-
 -- TODO: add tests for the other extra functions
 -- IVector exports still needing tests:
 --  copy,
---  slice,
---  (//), update, bpermute,
---  prescanl, prescanl',
 --  new,
 --  unsafeSlice, unsafeIndex,
---  vlength, vnew
 
--- TODO: test non-IVector stuff?
-
 testSanity :: forall a v. (CommonContext a v) => v a -> [Test]
 {-# INLINE testSanity #-}
 testSanity _ = [
@@ -121,7 +98,7 @@
         -- Length information
         'prop_length, 'prop_null,
 
-        -- Indexing (FIXME)
+        -- Indexing
         'prop_index, 'prop_safeIndex, 'prop_head, 'prop_last,
         'prop_unsafeIndex, 'prop_unsafeHead, 'prop_unsafeLast,
 
@@ -138,17 +115,16 @@
         -- Initialisation (FIXME)
         'prop_empty, 'prop_singleton, 'prop_replicate,
         'prop_generate, 'prop_iterateN, 'prop_iterateNM,
+        'prop_generateM, 'prop_replicateM,
 
         -- Monadic initialisation (FIXME)
-        'prop_createT,
-        {- 'prop_replicateM, 'prop_generateM, 'prop_create, -}
+        'prop_create, 'prop_createT,
 
         -- Unfolding
-        'prop_unfoldr, 'prop_unfoldrN, 'prop_unfoldrM, 'prop_unfoldrNM,
+        'prop_unfoldr, 'prop_unfoldrN, 'prop_unfoldrExactN,
+        'prop_unfoldrM, 'prop_unfoldrNM, 'prop_unfoldrExactNM,
         'prop_constructN, 'prop_constructrN,
 
-        -- Enumeration? (FIXME?)
-
         -- Concatenation (FIXME)
         'prop_cons, 'prop_snoc, 'prop_append,
         'prop_concat,
@@ -159,7 +135,7 @@
 
         -- Bulk updates (FIXME)
         'prop_upd,
-        {- 'prop_update, 'prop_update_,
+        {- 'prop_update_,
         'prop_unsafeUpd, 'prop_unsafeUpdate, 'prop_unsafeUpdate_, -}
 
         -- Accumulations (FIXME)
@@ -171,30 +147,23 @@
         'prop_reverse, 'prop_backpermute,
         {- 'prop_unsafeBackpermute, -}
 
-        -- Elementwise indexing
-        {- 'prop_indexed, -}
-
         -- Mapping
         'prop_map, 'prop_imap, 'prop_concatMap,
 
         -- Monadic mapping
-        {- 'prop_mapM, 'prop_mapM_, 'prop_forM, 'prop_forM_, -}
+        'prop_mapM, 'prop_mapM_, 'prop_forM, 'prop_forM_,
         'prop_imapM, 'prop_imapM_,
 
         -- Zipping
-        'prop_zipWith, 'prop_zipWith3, {- ... -}
-        'prop_izipWith, 'prop_izipWith3, {- ... -}
+        'prop_zipWith, 'prop_zipWith3,
+        'prop_izipWith, 'prop_izipWith3,
         'prop_izipWithM, 'prop_izipWithM_,
-        {- 'prop_zip, ... -}
 
         -- Monadic zipping
-        {- 'prop_zipWithM, 'prop_zipWithM_, -}
-
-        -- Unzipping
-        {- 'prop_unzip, ... -}
+        'prop_zipWithM, 'prop_zipWithM_,
 
         -- Filtering
-        'prop_filter, 'prop_ifilter, {- prop_filterM, -}
+        'prop_filter, 'prop_ifilter, 'prop_filterM,
         'prop_uniq,
         'prop_mapMaybe, 'prop_imapMaybe,
         'prop_takeWhile, 'prop_dropWhile,
@@ -206,7 +175,7 @@
 
         -- Searching
         'prop_elem, 'prop_notElem,
-        'prop_find, 'prop_findIndex, 'prop_findIndices,
+        'prop_find, 'prop_findIndex, 'prop_findIndexR, 'prop_findIndices,
         'prop_elemIndex, 'prop_elemIndices,
 
         -- Folding
@@ -217,15 +186,7 @@
 
         -- Specialised folds
         'prop_all, 'prop_any,
-        {- 'prop_maximumBy, 'prop_minimumBy,
-        'prop_maxIndexBy, 'prop_minIndexBy, -}
 
-        -- Monadic folds
-        {- ... -}
-
-        -- Monadic sequencing
-        {- ... -}
-
         -- Scans
         'prop_prescanl, 'prop_prescanl',
         'prop_postscanl, 'prop_postscanl',
@@ -245,9 +206,11 @@
     prop_null   :: P (v a -> Bool)    = V.null `eq` null
 
     prop_empty  :: P (v a)            = V.empty `eq` []
-    prop_singleton :: P (a -> v a)    = V.singleton `eq` singleton
+    prop_singleton :: P (a -> v a)    = V.singleton `eq` Util.singleton
     prop_replicate :: P (Int -> a -> v a)
               = (\n _ -> n < 1000) ===> V.replicate `eq` replicate
+    prop_replicateM :: P (Int -> Writer [a] a -> Writer [a] (v a))
+              = (\n _ -> n < 1000) ===> V.replicateM `eq` replicateM
     prop_cons      :: P (a -> v a -> v a) = V.cons `eq` (:)
     prop_snoc      :: P (v a -> a -> v a) = V.snoc `eq` snoc
     prop_append    :: P (v a -> v a -> v a) = (V.++) `eq` (++)
@@ -255,10 +218,14 @@
     prop_force     :: P (v a -> v a)        = V.force `eq` id
     prop_generate  :: P (Int -> (Int -> a) -> v a)
               = (\n _ -> n < 1000) ===> V.generate `eq` Util.generate
+    prop_generateM  :: P (Int -> (Int -> Writer [a] a) -> Writer [a] (v a))
+              = (\n _ -> n < 1000) ===> V.generateM `eq` Util.generateM
     prop_iterateN  :: P (Int -> (a -> a) -> a -> v a)
               = (\n _ _ -> n < 1000) ===> V.iterateN `eq` (\n f -> take n . iterate f)
     prop_iterateNM :: P (Int -> (a -> Writer [Int] a) -> a -> Writer [Int] (v a))
               = (\n _ _ -> n < 1000) ===> V.iterateNM `eq` Util.iterateNM
+    prop_create :: P (v a -> v a)
+    prop_create = (\v -> V.create (V.thaw v)) `eq` id
     prop_createT :: P ((a, v a) -> (a, v a))
     prop_createT = (\v -> V.createT (T.mapM V.thaw v)) `eq` id
 
@@ -319,6 +286,14 @@
     prop_reverse :: P (v a -> v a) = V.reverse `eq` reverse
 
     prop_map :: P ((a -> a) -> v a -> v a) = V.map `eq` map
+    prop_mapM :: P ((a -> Identity a) -> v a -> Identity (v a))
+            = V.mapM `eq` mapM
+    prop_mapM_ :: P ((a -> Writer [a] ()) -> v a -> Writer [a] ())
+            = V.mapM_ `eq` mapM_
+    prop_forM :: P (v a -> (a -> Identity a) -> Identity (v a))
+            = V.forM `eq` forM
+    prop_forM_ :: P (v a -> (a -> Writer [a] ()) -> Writer [a] ())
+            = V.forM_ `eq` forM_
     prop_zipWith :: P ((a -> a -> a) -> v a -> v a -> v a) = V.zipWith `eq` zipWith
     prop_zipWith3 :: P ((a -> a -> a -> a) -> v a -> v a -> v a -> v a)
              = V.zipWith3 `eq` zipWith3
@@ -328,6 +303,10 @@
     prop_imapM_ :: P ((Int -> a -> Writer [a] ()) -> v a -> Writer [a] ())
             = V.imapM_ `eq` imapM_
     prop_izipWith :: P ((Int -> a -> a -> a) -> v a -> v a -> v a) = V.izipWith `eq` izipWith
+    prop_zipWithM :: P ((a -> a -> Identity a) -> v a -> v a -> Identity (v a))
+            = V.zipWithM `eq` zipWithM
+    prop_zipWithM_ :: P ((a -> a -> Writer [a] ()) -> v a -> v a -> Writer [a] ())
+            = V.zipWithM_ `eq` zipWithM_
     prop_izipWithM :: P ((Int -> a -> a -> Identity a) -> v a -> v a -> Identity (v a))
             = V.izipWithM `eq` izipWithM
     prop_izipWithM_ :: P ((Int -> a -> a -> Writer [a] ()) -> v a -> v a -> Writer [a] ())
@@ -337,6 +316,7 @@
 
     prop_filter :: P ((a -> Bool) -> v a -> v a) = V.filter `eq` filter
     prop_ifilter :: P ((Int -> a -> Bool) -> v a -> v a) = V.ifilter `eq` ifilter
+    prop_filterM :: P ((a -> Writer [a] Bool) -> v a -> Writer [a] (v a)) = V.filterM `eq` filterM
     prop_mapMaybe :: P ((a -> Maybe a) -> v a -> v a) = V.mapMaybe `eq` mapMaybe
     prop_imapMaybe :: P ((Int -> a -> Maybe a) -> v a -> v a) = V.imapMaybe `eq` imapMaybe
     prop_takeWhile :: P ((a -> Bool) -> v a -> v a) = V.takeWhile `eq` takeWhile
@@ -353,6 +333,10 @@
     prop_find    :: P ((a -> Bool) -> v a -> Maybe a) = V.find `eq` find
     prop_findIndex :: P ((a -> Bool) -> v a -> Maybe Int)
       = V.findIndex `eq` findIndex
+    prop_findIndexR :: P ((a -> Bool) -> v a -> Maybe Int)
+      = V.findIndexR `eq` \p l -> case filter (p . snd) . reverse $ zip [0..] l of
+                                     (i,_):_ -> Just i
+                                     []      -> Nothing
     prop_findIndices :: P ((a -> Bool) -> v a -> v Int)
         = V.findIndices `eq` findIndices
     prop_elemIndex :: P (a -> v a -> Maybe Int) = V.elemIndex `eq` elemIndex
@@ -439,18 +423,8 @@
 
     prop_uniq :: P (v a -> v a)
       = V.uniq `eq` (map head . group)
-    --prop_span         = (V.span :: (a -> Bool) -> v a -> (v a, v a))  `eq2` span
-    --prop_break        = (V.break :: (a -> Bool) -> v a -> (v a, v a)) `eq2` break
-    --prop_splitAt      = (V.splitAt :: Int -> v a -> (v a, v a))       `eq2` splitAt
-    --prop_all          = (V.all :: (a -> Bool) -> v a -> Bool)         `eq2` all
-    --prop_any          = (V.any :: (a -> Bool) -> v a -> Bool)         `eq2` any
 
     -- Data.List
-    --prop_findIndices  = V.findIndices `eq2` (findIndices :: (a -> Bool) -> v a -> v Int)
-    --prop_isPrefixOf   = V.isPrefixOf  `eq2` (isPrefixOf  :: v a -> v a -> Bool)
-    --prop_elemIndex    = V.elemIndex   `eq2` (elemIndex   :: a -> v a -> Maybe Int)
-    --prop_elemIndices  = V.elemIndices `eq2` (elemIndices :: a -> v a -> v Int)
-    --
     --prop_mapAccumL  = eq3
     --    (V.mapAccumL :: (X -> W -> (X,W)) -> X -> B   -> (X, B))
     --    (  mapAccumL :: (X -> W -> (X,W)) -> X -> [W] -> (X, [W]))
@@ -476,11 +450,15 @@
            `eq` (\n f a -> unfoldr (limitUnfolds f) (a, n))
     prop_unfoldrN :: P (Int -> (Int -> Maybe (a,Int)) -> Int -> v a)
          = V.unfoldrN `eq` (\n f a -> unfoldr (limitUnfolds f) (a, n))
+    prop_unfoldrExactN :: P (Int -> (Int -> (a,Int)) -> Int -> v a)
+         = V.unfoldrExactN `eq` (\n f a -> unfoldr (limitUnfolds (Just . f)) (a, n))
     prop_unfoldrM :: P (Int -> (Int -> Writer [Int] (Maybe (a,Int))) -> Int -> Writer [Int] (v a))
          = (\n f a -> V.unfoldrM (limitUnfoldsM f) (a,n))
            `eq` (\n f a -> Util.unfoldrM (limitUnfoldsM f) (a, n))
     prop_unfoldrNM :: P (Int -> (Int -> Writer [Int] (Maybe (a,Int))) -> Int -> Writer [Int] (v a))
          = V.unfoldrNM `eq` (\n f a -> Util.unfoldrM (limitUnfoldsM f) (a, n))
+    prop_unfoldrExactNM :: P (Int -> (Int -> Writer [Int] (a,Int)) -> Int -> Writer [Int] (v a))
+         = V.unfoldrExactNM `eq` (\n f a -> Util.unfoldrM (limitUnfoldsM (liftM Just . f)) (a, n))
 
     prop_constructN  = \f -> forAll (choose (0,20)) $ \n -> unP prop n f
       where
@@ -504,16 +482,30 @@
                          Right c -> (bs, c:cs)
     where (bs,cs) = partitionWith f xs
 
-testTuplyFunctions :: forall a v. (CommonContext a v, VectorContext (a, a) v, VectorContext (a, a, a) v) => v a -> [Test]
+testTuplyFunctions
+  :: forall a v. ( CommonContext a v
+                 , VectorContext (a, a)    v
+                 , VectorContext (a, a, a) v
+                 , VectorContext (Int, a)  v
+                 )
+  => v a -> [Test]
 {-# INLINE testTuplyFunctions #-}
 testTuplyFunctions _ = $(testProperties [ 'prop_zip, 'prop_zip3
                                         , 'prop_unzip, 'prop_unzip3
+                                        , 'prop_indexed
+                                        , 'prop_update
                                         ])
   where
-    prop_zip    :: P (v a -> v a -> v (a, a))           = V.zip `eq` zip
-    prop_zip3   :: P (v a -> v a -> v a -> v (a, a, a)) = V.zip3 `eq` zip3
-    prop_unzip  :: P (v (a, a) -> (v a, v a))           = V.unzip `eq` unzip
-    prop_unzip3 :: P (v (a, a, a) -> (v a, v a, v a))   = V.unzip3 `eq` unzip3
+    prop_zip     :: P (v a -> v a -> v (a, a))           = V.zip `eq` zip
+    prop_zip3    :: P (v a -> v a -> v a -> v (a, a, a)) = V.zip3 `eq` zip3
+    prop_unzip   :: P (v (a, a) -> (v a, v a))           = V.unzip `eq` unzip
+    prop_unzip3  :: P (v (a, a, a) -> (v a, v a, v a))   = V.unzip3 `eq` unzip3
+    prop_indexed :: P (v a -> v (Int, a))                = V.indexed `eq` (\xs -> [0..] `zip` xs)
+    prop_update = \xs ->
+      forAll (index_value_pairs (V.length xs)) $ \ps ->
+      unP prop xs ps
+      where
+        prop :: P (v a -> [(Int,a)] -> v a) = (V.//) `eq` (//)
 
 testOrdFunctions :: forall a v. (CommonContext a v, Ord a, Ord (v a)) => v a -> [Test]
 {-# INLINE testOrdFunctions #-}
@@ -617,13 +609,31 @@
 testMonadFunctions :: forall a v. (CommonContext a v, VectorContext (a, a) v, MonadZip v) => v a -> [Test]
 {-# INLINE testMonadFunctions #-}
 testMonadFunctions _ = $(testProperties [ 'prop_return, 'prop_bind
-                                        , 'prop_mzip, 'prop_munzip])
+                                        , 'prop_mzip, 'prop_munzip
+                                        ])
   where
     prop_return :: P (a -> v a) = return `eq` return
     prop_bind   :: P (v a -> (a -> v a) -> v a) = (>>=) `eq` (>>=)
     prop_mzip   :: P (v a -> v a -> v (a, a)) = mzip `eq` zip
     prop_munzip :: P (v (a, a) -> (v a, v a)) = munzip `eq` unzip
 
+testSequenceFunctions
+  :: forall a v. ( CommonContext a v
+                 , Model (v (Writer [a] a)) ~ [Writer [a] a]
+                 , V.Vector v (Writer [a] a)
+                 , Arbitrary (v (Writer [a] a))
+                 , Show      (v (Writer [a] a))
+                 , TestData  (v (Writer [a] a))
+                 )
+  => v a -> [Test]
+testSequenceFunctions _ = $(testProperties [ 'prop_sequence, 'prop_sequence_
+                                           ])
+  where
+    prop_sequence :: P (v (Writer [a] a) -> Writer [a] (v a))
+      = V.sequence `eq` sequence
+    prop_sequence_ :: P (v (Writer [a] a) -> Writer [a] ())
+      = V.sequence_ `eq` sequence_
+
 testApplicativeFunctions :: forall a v. (CommonContext a v, V.Vector v (a -> a), Applicative.Applicative v) => v a -> [Test]
 {-# INLINE testApplicativeFunctions #-}
 testApplicativeFunctions _ = $(testProperties
@@ -659,16 +669,11 @@
 
 testNestedVectorFunctions :: forall a v. (CommonContext a v) => v a -> [Test]
 {-# INLINE testNestedVectorFunctions #-}
-testNestedVectorFunctions _ = $(testProperties [])
+testNestedVectorFunctions _ = $(testProperties
+  [ 'prop_concat
+  ])
   where
-    -- Prelude
-    --prop_concat       = (V.concat :: [v a] -> v a)                    `eq1` concat
-
-    -- Data.List
-    --prop_transpose    = V.transpose   `eq1` (transpose   :: [v a] -> [v a])
-    --prop_group        = V.group       `eq1` (group       :: v a -> [v a])
-    --prop_inits        = V.inits       `eq1` (inits       :: v a -> [v a])
-    --prop_tails        = V.tails       `eq1` (tails       :: v a -> [v a])
+    prop_concat :: P ([v a] -> v a) = V.concat `eq` concat
 
 testDataFunctions :: forall a v. (CommonContext a v, Data a, Data (v a)) => v a -> [Test]
 {-# INLINE testDataFunctions #-}
diff --git a/tests/Tests/Vector/Unboxed.hs b/tests/Tests/Vector/Unboxed.hs
--- a/tests/Tests/Vector/Unboxed.hs
+++ b/tests/Tests/Vector/Unboxed.hs
@@ -13,6 +13,7 @@
     testSanity
   , testPolymorphicFunctions
   , testOrdFunctions
+  , testTuplyFunctions
   , testMonoidFunctions
   , testDataFunctions
   ]
diff --git a/tests/Tests/Vector/UnitTests.hs b/tests/Tests/Vector/UnitTests.hs
--- a/tests/Tests/Vector/UnitTests.hs
+++ b/tests/Tests/Vector/UnitTests.hs
@@ -6,24 +6,25 @@
 import Control.Applicative as Applicative
 import Control.Exception
 import Control.Monad.Primitive
+import Control.Monad.Fix (mfix)
 import Data.Int
 import Data.Word
 import Data.Typeable
 import qualified Data.List as List
 import qualified Data.Vector.Generic  as Generic
 import qualified Data.Vector as Boxed
+import qualified Data.Vector.Mutable as MBoxed
 import qualified Data.Vector.Primitive as Primitive
 import qualified Data.Vector.Storable as Storable
 import qualified Data.Vector.Unboxed as Unboxed
-import qualified Data.Vector         as Vector
 import Foreign.Ptr
 import Foreign.Storable
 import Text.Printf
 
 import Test.Tasty
-import Test.Tasty.HUnit (testCase,Assertion, assertBool, (@=?), assertFailure)
--- import Test.HUnit ()
+import Test.Tasty.HUnit (testCase, Assertion, assertBool, assertEqual, (@=?), assertFailure)
 
+
 newtype Aligned a = Aligned { getAligned :: a }
 
 instance (Storable a) => Storable (Aligned a) where
@@ -80,6 +81,11 @@
       , testCase "Unboxed" $ testTakeOutOfMemory Unboxed.take
       ]
     ]
+  , testGroup "Data.Vector"
+    [ testCase "MonadFix" checkMonadFix
+    , testCase "toFromArray" toFromArray
+    , testCase "toFromMutableArray" toFromMutableArray
+    ]
   ]
 
 testsSliceOutOfBounds ::
@@ -141,7 +147,7 @@
   :: forall proxy a. (Typeable a, Enum a, Bounded a, Eq a, Show a)
   => proxy a -> TestTree
 regression188 _ = testCase (show (typeOf (undefined :: a)))
-  $ Vector.fromList [maxBound::a] @=? Vector.enumFromTo maxBound maxBound
+  $ Boxed.fromList [maxBound::a] @=? Boxed.enumFromTo maxBound maxBound
 {-# INLINE regression188 #-}
 
 alignedDoubleVec :: Storable.Vector (Aligned Double)
@@ -157,3 +163,45 @@
    => Generic.Mutable v (PrimState f) a -> f (w a)
 _f v = Generic.convert `fmap` Generic.unsafeFreeze v
 #endif
+
+checkMonadFix :: Assertion
+checkMonadFix = assertBool "checkMonadFix" $
+    Boxed.toList fewV == fewL &&
+    Boxed.toList none == []
+  where
+    facty _ 0 = 1; facty f n = n * f (n - 1)
+    fewV :: Boxed.Vector Int
+    fewV = fmap ($ 12) $ mfix (\i -> Boxed.fromList [facty i, facty (+1), facty (+2)])
+    fewL :: [Int]
+    fewL = fmap ($ 12) $ mfix (\i -> [facty i, facty (+1), facty (+2)])
+    none :: Boxed.Vector Int
+    none = mfix (const Boxed.empty)
+
+mkArrayRoundtrip :: (String -> Boxed.Vector Integer -> Assertion) -> Assertion
+mkArrayRoundtrip mkAssertion =
+  sequence_
+    [ mkAssertion name v
+    | (name, v) <-
+        [ ("full", vec)
+        , ("slicedTail", Boxed.slice 0 (n - 3) vec)
+        , ("slicedHead", Boxed.slice 2 (n - 2) vec)
+        , ("slicedBoth", Boxed.slice 2 (n - 4) vec)
+        ]
+    ]
+  where
+    vec = Boxed.fromList [0 .. 10]
+    n = Boxed.length vec
+
+toFromArray :: Assertion
+toFromArray =
+  mkArrayRoundtrip $ \name v ->
+    assertEqual name v $ Boxed.fromArray (Boxed.toArray v)
+
+toFromMutableArray :: Assertion
+toFromMutableArray = mkArrayRoundtrip assetRoundtrip
+  where
+    assetRoundtrip assertionName vec = do
+      mvec <- Boxed.unsafeThaw vec
+      mvec' <- MBoxed.fromMutableArray =<< MBoxed.toMutableArray mvec
+      vec' <- Boxed.unsafeFreeze mvec'
+      assertEqual assertionName vec vec'
diff --git a/tests/Utilities.hs b/tests/Utilities.hs
--- a/tests/Utilities.hs
+++ b/tests/Utilities.hs
@@ -68,42 +68,42 @@
   type EqTest a
   equal :: a -> a -> EqTest a
 
-instance Eq a => TestData (S.Bundle v a) where
-  type Model (S.Bundle v a) = [a]
-  model = S.toList
-  unmodel = S.fromList
+instance (Eq a, TestData a) => TestData (S.Bundle v a) where
+  type Model (S.Bundle v a) = [Model a]
+  model   = map model  . S.toList
+  unmodel = S.fromList . map unmodel
 
   type EqTest (S.Bundle v a) = Property
   equal x y = property (x == y)
 
-instance Eq a => TestData (DV.Vector a) where
-  type Model (DV.Vector a) = [a]
-  model = DV.toList
-  unmodel = DV.fromList
+instance (Eq a, TestData a) => TestData (DV.Vector a) where
+  type Model (DV.Vector a) = [Model a]
+  model   = map model    . DV.toList
+  unmodel = DV.fromList . map unmodel
 
   type EqTest (DV.Vector a) = Property
   equal x y = property (x == y)
 
-instance (Eq a, DVP.Prim a) => TestData (DVP.Vector a) where
-  type Model (DVP.Vector a) = [a]
-  model = DVP.toList
-  unmodel = DVP.fromList
+instance (Eq a, DVP.Prim a, TestData a) => TestData (DVP.Vector a) where
+  type Model (DVP.Vector a) = [Model a]
+  model   = map model    . DVP.toList
+  unmodel = DVP.fromList . map unmodel
 
   type EqTest (DVP.Vector a) = Property
   equal x y = property (x == y)
 
-instance (Eq a, DVS.Storable a) => TestData (DVS.Vector a) where
-  type Model (DVS.Vector a) = [a]
-  model = DVS.toList
-  unmodel = DVS.fromList
+instance (Eq a, DVS.Storable a, TestData a) => TestData (DVS.Vector a) where
+  type Model (DVS.Vector a) = [Model a]
+  model   = map model    . DVS.toList
+  unmodel = DVS.fromList . map unmodel
 
   type EqTest (DVS.Vector a) = Property
   equal x y = property (x == y)
 
-instance (Eq a, DVU.Unbox a) => TestData (DVU.Vector a) where
-  type Model (DVU.Vector a) = [a]
-  model = DVU.toList
-  unmodel = DVU.fromList
+instance (Eq a, DVU.Unbox a, TestData a) => TestData (DVU.Vector a) where
+  type Model (DVU.Vector a) = [Model a]
+  model   = map model    . DVU.toList
+  unmodel = DVU.fromList . map unmodel
 
   type EqTest (DVU.Vector a) = Property
   equal x y = property (x == y)
@@ -247,6 +247,7 @@
 singleton x = [x]
 snoc xs x = xs ++ [x]
 generate n f = [f i | i <- [0 .. n-1]]
+generateM n f = sequence [f i | i <- [0 .. n-1]]
 slice i n xs = take n (drop i xs)
 backpermute xs is = map (xs!!) is
 prescanl f z = init . scanl f z
diff --git a/tests/doctests.hs b/tests/doctests.hs
new file mode 100644
--- /dev/null
+++ b/tests/doctests.hs
@@ -0,0 +1,4 @@
+import Test.DocTest (doctest)
+
+main :: IO ()
+main = doctest ["-Iinclude", "-Iinternal", "Data"]
diff --git a/vector.cabal b/vector.cabal
--- a/vector.cabal
+++ b/vector.cabal
@@ -1,5 +1,5 @@
 Name:           vector
-Version:        0.12.1.2
+Version:        0.12.2.0
 -- don't forget to update the changelog file!
 License:        BSD3
 License-File:   LICENSE
@@ -152,9 +152,9 @@
   Install-Includes:
         vector.h
 
-  Build-Depends: base >= 4.5 && < 4.15
-               , primitive >= 0.5.0.1 && < 0.8
-               , ghc-prim >= 0.2 && < 0.7
+  Build-Depends: base >= 4.5 && < 4.16
+               , primitive >= 0.6.4.0 && < 0.8
+               , ghc-prim >= 0.2 && < 0.8
                , deepseq >= 1.1 && < 1.5
   if !impl(ghc > 8.0)
     Build-Depends: fail == 4.9.*
@@ -203,9 +203,11 @@
   hs-source-dirs: tests
   Build-Depends: base >= 4.5 && < 5, template-haskell, base-orphans >= 0.6, vector,
                  primitive, random,
-                 QuickCheck >= 2.9 && < 2.14 , HUnit, tasty,
+                 QuickCheck >= 2.9 && < 2.15, HUnit, tasty,
                  tasty-hunit, tasty-quickcheck,
-                 transformers >= 0.2.0.0,semigroups
+                 transformers >= 0.2.0.0
+  if !impl(ghc > 8.0)
+    Build-Depends: semigroups
 
   default-extensions: CPP,
               ScopedTypeVariables,
@@ -246,9 +248,11 @@
   hs-source-dirs: tests
   Build-Depends: base >= 4.5 && < 5, template-haskell, base-orphans >= 0.6, vector,
                  primitive, random,
-                 QuickCheck >= 2.9 && < 2.14 , HUnit,  tasty,
+                 QuickCheck >= 2.9 && < 2.15, HUnit, tasty,
                  tasty-hunit, tasty-quickcheck,
-                 transformers >= 0.2.0.0,semigroups
+                 transformers >= 0.2.0.0
+  if !impl(ghc > 8.0)
+    Build-Depends: semigroups
 
   default-extensions: CPP,
               ScopedTypeVariables,
@@ -268,3 +272,19 @@
     if impl(ghc >= 8.0) && impl(ghc < 8.1)
       Ghc-Options: -Wno-redundant-constraints
 
+test-suite vector-doctest
+  type:             exitcode-stdio-1.0
+  main-is:          doctests.hs
+  hs-source-dirs:   tests
+  default-language: Haskell2010
+  -- Older GHC choke on {-# UNPACK #-} pragma for some reason
+  if impl(ghc < 8.6)
+    buildable: False
+  -- GHC 8.10 fails to run doctests for some reason
+  if impl(ghc >= 8.10) && impl(ghc < 8.11)
+    buildable: False
+  build-depends:
+        base      -any
+      , doctest   >=0.15 && <0.18
+      , primitive >= 0.6.4.0 && < 0.8
+      , vector    -any
