diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,11 +1,24 @@
 # Change Log
 
+## [1.0.0.0] - 2018-03-20
+
+- More functions using `Finite` instead of `Int`
+- Add `Read` and `Semigroup` instances
+- Performance improvements for `Applicative`
+- Add a `knownLength` function
+- Add `fromTuple` (ghc < 8.3 for now)
+- Add sized variants of mutable vectors 
+- Expose sized vector constructors from Internal modules
+
+Huge thanks to all the contributors!
+
 ## [0.6.1.0] - 2017-08-04
 - Add lenses ix, _head and _last
 
 ## [0.6.0.0] - 2017-06-07
 - Make ordering of additions in types be more consistent
 - Make slice more general
+- `Num`, `Fractional`, and `Floating` instances for vectors
 
 ## [0.5.1.0] - 2017-02-01
 - Loosen upper bound on `vector`
diff --git a/readme.md b/readme.md
--- a/readme.md
+++ b/readme.md
@@ -3,12 +3,19 @@
 This package exports a newtype tagging the vectors from the
 [vector](https://hackage.haskell.org/package/vector) package with a type level
 natural representing their size.
-
 It also exports a few functions from vector appropriately retyped.
 
-This package is fairly similar to the
-[fixed-vector](https://hackage.haskell.org/package/fixed-vector) package. The
-difference is that fixed-vector uses Peano naturals to represent the size tag
-on the vectors and this package uses typelits.
+This package is fairly similar to
+the [fixed-vector](https://hackage.haskell.org/package/fixed-vector) package.
+While both provide vectors of statically know length they use completely
+different implementation with different tradeoffs. `vector-sized` is a newtype
+wrapper over `vector` thus it's able to handle vectors of arbitrary length but
+have to carry runtime representation of length which is significant memory
+overhead for small vectors. `fixed-vector` defines all functions as
+manipulations of Church-encoded product types (`∀r. (a→a→r) → r` for 2D vectors)
+so it can work for both arbitrary product types like `data V2 a = V2 a a` and
+opaque length-parametrized vectors provided by library. As consequence of
+implementation it can't handle vectors larger than tens of elements.
+
 
 The initial code for this package was written by @bgamari in a [PR for vulkan](https://github.com/expipiplus1/vulkan/pull/1)
diff --git a/src/Data/Vector/Generic/Mutable/Sized.hs b/src/Data/Vector/Generic/Mutable/Sized.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Vector/Generic/Mutable/Sized.hs
@@ -0,0 +1,484 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE RankNTypes #-}
+
+{-|
+This module reexports the functionality in 'Data.Vector.Generic.Mutable'
+which maps well to explicity sized vectors.
+
+Functions returning a vector determine the size from the type context
+unless they have a @'@ suffix in which case they take an explicit 'Proxy'
+argument.
+
+Functions where the resultant vector size is not know until compile time
+are not exported.
+-}
+
+module Data.Vector.Generic.Mutable.Sized
+ ( MVector
+   -- * Accessors
+   -- ** Length information
+  , length
+  , length'
+  , null
+   -- ** Extracting subvectors
+  , slice
+  , slice'
+  , init
+  , tail
+  , take
+  , take'
+  , drop
+  , drop'
+  , splitAt
+  , splitAt'
+  -- ** Overlaps
+  , overlaps
+  -- * Construction
+  -- ** Initialisation
+  , new
+  , unsafeNew
+  , replicate
+  , replicate'
+  , replicateM
+  , replicateM'
+  , clone
+  -- ** Growing
+  , grow
+  , growFront
+  -- ** Restricting memory usage
+  , clear
+  -- * Accessing individual elements
+  , read
+  , read'
+  , write
+  , write'
+  , modify
+  , modify'
+  , swap
+  , exchange
+  , exchange'
+  , unsafeRead
+  , unsafeWrite
+  , unsafeModify
+  , unsafeSwap
+  , unsafeExchange
+#if MIN_VERSION_vector(0,12,0)
+  -- * Modifying vectors
+  , nextPermutation
+#endif
+  -- ** Filling and copying
+  , set
+  , copy
+  , move
+  , unsafeCopy
+    -- * Conversions
+    -- ** Unsized Mutable Vectors
+  , toSized
+  , withSized
+  , fromSized
+  ) where
+
+import qualified Data.Vector.Generic.Mutable as VGM
+import Data.Vector.Generic.Mutable.Sized.Internal
+import GHC.TypeLits
+import Data.Finite
+import Data.Proxy
+import Control.Monad.Primitive
+import Prelude hiding ( length, null, replicate, init,
+                        tail, take, drop, splitAt, read )
+
+-- * Accessors
+
+-- ** Length information
+
+-- | /O(1)/ Yield the length of the mutable vector as an 'Int'.
+length :: forall v n s a. (KnownNat n)
+       => MVector v n s a -> Int
+length _ = fromInteger (natVal (Proxy :: Proxy n))
+{-# inline length #-}
+
+-- | /O(1)/ Yield the length of the mutable vector as a 'Proxy'.
+length' :: forall v n s a. (KnownNat n)
+        => MVector v n s a -> Proxy n
+length' _ = Proxy
+{-# inline length' #-}
+
+-- | /O(1)/ Check whether the mutable vector is empty
+null :: forall v n s a. (KnownNat n)
+       => MVector v n s a -> Bool
+null = (== 0) . length
+{-# inline null #-}
+
+-- ** Extracting subvectors
+
+-- | /O(1)/ Yield a slice of the mutable vector without copying it with an
+-- inferred length argument.
+slice :: forall v i n k s a p. (KnownNat i, KnownNat n, KnownNat k, VGM.MVector v a)
+      => p i -- ^ starting index
+      -> MVector v (i+n+k) s a
+      -> MVector v n s a
+slice start (MVector v) = MVector (VGM.unsafeSlice i n v)
+  where i = fromInteger (natVal start)
+        n = fromInteger (natVal (Proxy :: Proxy n))
+{-# inline slice #-}
+
+-- | /O(1)/ Yield a slice of the mutable vector without copying it with an
+-- explicit length argument.
+slice' :: forall v i n k s a p
+        . (KnownNat i, KnownNat n, KnownNat k, VGM.MVector v a)
+       => p i -- ^ starting index
+       -> p n -- ^ length
+       -> MVector v (i+n+k) s a
+       -> MVector v n s a
+slice' start _ = slice start
+{-# inline slice' #-}
+
+-- | /O(1)/ Yield all but the last element of a non-empty mutable vector
+-- without copying.
+init :: forall v n s a. (VGM.MVector v a)
+     => MVector v (n+1) s a -> MVector v n s a
+init (MVector v) = MVector (VGM.unsafeInit v)
+{-# inline init #-}
+
+-- | /O(1)/ Yield all but the first element of a non-empty mutable vector
+-- without copying.
+tail :: forall v n s a. (VGM.MVector v a)
+     => MVector v (1+n) s a -> MVector v n s a
+tail (MVector v) = MVector (VGM.unsafeTail v)
+{-# inline tail #-}
+
+-- | /O(1)/ Yield the first n elements. The resultant vector always contains
+-- this many elements. The length of the resultant vector is inferred from the
+-- type.
+take :: forall v n k s a. (KnownNat n, KnownNat k, VGM.MVector v a)
+     => MVector v (n+k) s a -> MVector v n s a
+take (MVector v) = MVector (VGM.unsafeTake i v)
+  where i = fromInteger (natVal (Proxy :: Proxy n))
+{-# inline take #-}
+
+-- | /O(1)/ Yield the first n elements. The resultant vector always contains
+-- this many elements. The length of the resultant vector is given explicitly
+-- as a 'Proxy' argument.
+take' :: forall v n k s a p. (KnownNat n, KnownNat k, VGM.MVector v a)
+      => p n -> MVector v (n+k) s a -> MVector v n s a
+take' _ = take
+{-# inline take' #-}
+
+-- | /O(1)/ Yield all but the the first n elements. The given vector must
+-- contain at least this many elements The length of the resultant vector is
+-- inferred from the type.
+drop :: forall v n k s a. (KnownNat n, KnownNat k, VGM.MVector v a)
+     => MVector v (n+k) s a -> MVector v k s a
+drop (MVector v) = MVector (VGM.unsafeDrop i v)
+  where i = fromInteger (natVal (Proxy :: Proxy n))
+{-# inline drop #-}
+
+-- | /O(1)/ Yield all but the the first n elements. The given vector must
+-- contain at least this many elements The length of the resultant vector is
+-- givel explicitly as a 'Proxy' argument.
+drop' :: forall v n k s a p. (KnownNat n, KnownNat k, VGM.MVector v a)
+      => p n -> MVector v (n+k) s a -> MVector v k s a
+drop' _ = drop
+{-# inline drop' #-}
+
+-- | /O(1)/ Yield the first n elements paired with the remainder without copying.
+-- The lengths of the resultant vector are inferred from the type.
+splitAt :: forall v n m s a. (KnownNat n, KnownNat m, VGM.MVector v a)
+        => MVector v (n+m) s a -> (MVector v n s a, MVector v m s a)
+splitAt (MVector v) = (MVector a, MVector b)
+  where i = fromInteger (natVal (Proxy :: Proxy n))
+        (a, b) = VGM.splitAt i v
+{-# inline splitAt #-}
+
+-- | /O(1)/ Yield the first n elements paired with the remainder without
+-- copying.  The length of the first resultant vector is passed explicitly as a
+-- 'Proxy' argument.
+splitAt' :: forall v n m s a p. (KnownNat n, KnownNat m, VGM.MVector v a)
+         => p n -> MVector v (n+m) s a -> (MVector v n s a, MVector v m s a)
+splitAt' _ = splitAt
+{-# inline splitAt' #-}
+
+-- ** Overlaps
+
+-- | /O(1)/ Yield all but the the first n elements. The given vector must
+-- contain at least this many elements The length of the resultant vector is
+-- inferred from the type.
+overlaps :: forall v n k s a. (KnownNat n, KnownNat k, VGM.MVector v a)
+         => MVector v n s a
+         -> MVector v k s a
+         -> Bool
+overlaps (MVector v) (MVector u) = VGM.overlaps v u
+{-# inline overlaps #-}
+
+-- * Construction
+
+-- ** Initialisation
+
+-- | Create a mutable vector where the length is inferred from the type.
+new :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+    => m (MVector v n (PrimState m) a)
+new = MVector <$> VGM.new (fromIntegral (natVal (Proxy :: Proxy n)))
+{-# inline new #-}
+
+-- | Create a mutable vector where the length is inferred from the type.
+-- The memory is not initialized.
+unsafeNew :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+          => m (MVector v n (PrimState m) a)
+unsafeNew = MVector <$> VGM.new (fromIntegral (natVal (Proxy :: Proxy n)))
+{-# inline unsafeNew #-}
+
+-- | Create a mutable vector where the length is inferred from the type and
+-- fill it with an initial value.
+replicate :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+          => a -> m (MVector v n (PrimState m) a)
+replicate = fmap MVector . VGM.replicate (fromIntegral (natVal (Proxy :: Proxy n)))
+{-# inline replicate #-}
+
+-- | Create a mutable vector where the length is given explicitly as
+-- a 'Proxy' argument and fill it with an initial value.
+replicate' :: forall v n m a p. (KnownNat n, PrimMonad m, VGM.MVector v a)
+           => p n -> a -> m (MVector v n (PrimState m) a)
+replicate' _ = replicate
+{-# inline replicate' #-}
+
+-- | Create a mutable vector where the length is inferred from the type and
+-- fill it with values produced by repeatedly executing the monadic action.
+replicateM :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+           => m a -> m (MVector v n (PrimState m) a)
+replicateM = fmap MVector . VGM.replicateM (fromIntegral (natVal (Proxy :: Proxy n)))
+{-# inline replicateM #-}
+
+-- | Create a mutable vector where the length is given explicitly as
+-- a 'Proxy' argument and fill it with values produced by repeatedly
+-- executing the monadic action.
+replicateM' :: forall v n m a p. (KnownNat n, PrimMonad m, VGM.MVector v a)
+           => p n -> m a -> m (MVector v n (PrimState m) a)
+replicateM' _ = replicateM
+{-# inline replicateM' #-}
+
+-- | Create a copy of a mutable vector.
+clone :: forall v n m a. (PrimMonad m, VGM.MVector v a)
+      => MVector v n (PrimState m) a -> m (MVector v n (PrimState m) a)
+clone (MVector v) = MVector <$> VGM.clone v
+{-# inline clone #-}
+
+-- ** Growing
+
+-- | Grow a mutable vector by an amount given explicitly as a 'Proxy'
+-- argument.
+grow :: forall v n k m a p. (KnownNat k, PrimMonad m, VGM.MVector v a)
+      => p k -> MVector v n (PrimState m) a -> m (MVector v (n + k) (PrimState m) a)
+grow _ (MVector v) = MVector <$> VGM.unsafeGrow v (fromIntegral (natVal (Proxy :: Proxy k)))
+{-# inline grow #-}
+
+-- | Grow a mutable vector (from the front) by an amount given explicitly
+-- as a 'Proxy' argument.
+growFront :: forall v n k m a p. (KnownNat k, PrimMonad m, VGM.MVector v a)
+      => p k -> MVector v n (PrimState m) a -> m (MVector v (n + k) (PrimState m) a)
+growFront _ (MVector v) = MVector <$>
+    VGM.unsafeGrowFront v (fromIntegral (natVal (Proxy :: Proxy k)))
+{-# inline growFront #-}
+
+-- ** Restricting memory usage
+
+-- | Reset all elements of the vector to some undefined value, clearing all
+-- references to external objects.
+clear :: (PrimMonad m, VGM.MVector v a) => MVector v n (PrimState m) a -> m ()
+clear (MVector v) = VGM.clear v
+{-# inline clear #-}
+
+-- * Accessing individual elements
+
+-- | /O(1)/ Yield the element at a given type-safe position using 'Finite'.
+read :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+      => MVector v n (PrimState m) a -> Finite n -> m a
+read (MVector v) i = v `VGM.unsafeRead` fromIntegral i
+{-# inline read #-}
+
+-- | /O(1)/ Yield the element at a given type-safe position using 'Proxy'.
+read' :: forall v n k a m p. (KnownNat n, KnownNat k, PrimMonad m, VGM.MVector v a)
+       => MVector v (n+k+1) (PrimState m) a -> p k -> m a
+read' (MVector v) p = v `VGM.unsafeRead` fromInteger (natVal p)
+{-# inline read' #-}
+
+-- | /O(1)/ Yield the element at a given 'Int' position without bounds
+-- checking.
+unsafeRead :: forall v n a m. (KnownNat n, PrimMonad m, VGM.MVector v a)
+           => MVector v n (PrimState m) a -> Int -> m a
+unsafeRead (MVector v) i = v `VGM.unsafeRead` i
+{-# inline unsafeRead #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position using 'Finite'.
+write :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+      => MVector v n (PrimState m) a -> Finite n -> a -> m ()
+write (MVector v) i = VGM.unsafeWrite v (fromIntegral i)
+{-# inline write #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position using 'Proxy'.
+write' :: forall v n k a m p. (KnownNat n, KnownNat k, PrimMonad m, VGM.MVector v a)
+       => MVector v (n+k+1) (PrimState m) a -> p k -> a -> m ()
+write' (MVector v) p = VGM.unsafeWrite v (fromInteger (natVal p))
+{-# inline write' #-}
+
+-- | /O(1)/ Replace the element at a given 'Int' position without bounds
+-- checking.
+unsafeWrite :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+      => MVector v n (PrimState m) a -> Int -> a -> m ()
+unsafeWrite (MVector v) = VGM.unsafeWrite v
+{-# inline unsafeWrite #-}
+
+-- | /O(1)/ Modify the element at a given type-safe position using 'Finite'.
+modify :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+       => MVector v n (PrimState m) a -> (a -> a) -> Finite n -> m ()
+modify (MVector v) f i = VGM.unsafeModify v f (fromIntegral i)
+{-# inline modify #-}
+
+-- | /O(1)/ Modify the element at a given type-safe position using 'Proxy'.
+modify' :: forall v n k a m p. (KnownNat n, KnownNat k, PrimMonad m, VGM.MVector v a)
+        => MVector v (n+k+1) (PrimState m) a -> (a -> a) -> p k -> m ()
+modify' (MVector v) f p = VGM.unsafeModify v f (fromInteger (natVal p))
+{-# inline modify' #-}
+
+-- | /O(1)/ Modify the element at a given 'Int' position without bounds
+-- checking.
+unsafeModify :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+       => MVector v n (PrimState m) a -> (a -> a) -> Int -> m ()
+unsafeModify (MVector v) = VGM.unsafeModify v
+{-# inline unsafeModify #-}
+
+-- | /O(1)/ Swap the elements at a given type-safe position using 'Finite's.
+swap :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+     => MVector v n (PrimState m) a -> Finite n -> Finite n -> m ()
+swap (MVector v) i j = VGM.unsafeSwap v (fromIntegral i) (fromIntegral j)
+{-# inline swap #-}
+
+-- | /O(1)/ Swap the elements at a given 'Int' position without bounds
+-- checking.
+unsafeSwap :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+           => MVector v n (PrimState m) a -> Int -> Int -> m ()
+unsafeSwap (MVector v) = VGM.unsafeSwap v
+{-# inline unsafeSwap #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position and return
+-- the old element, using 'Finite'.
+exchange :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+         => MVector v n (PrimState m) a -> Finite n -> a -> m a
+exchange (MVector v) i = VGM.unsafeExchange v (fromIntegral i)
+{-# inline exchange #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position and return
+-- the old element, using 'Finite'.
+exchange' :: forall v n k a m p. (KnownNat n, KnownNat k, PrimMonad m, VGM.MVector v a)
+          => MVector v (n+k+1) (PrimState m) a -> p k -> a -> m a
+exchange' (MVector v) p = VGM.unsafeExchange v (fromInteger (natVal p))
+{-# inline exchange' #-}
+
+-- | /O(1)/ Replace the element at a given 'Int' position and return
+-- the old element. No bounds checks are performed.
+unsafeExchange :: forall v n m a. (KnownNat n, PrimMonad m, VGM.MVector v a)
+         => MVector v n (PrimState m) a -> Int -> a -> m a
+unsafeExchange (MVector v) = VGM.unsafeExchange v
+{-# inline unsafeExchange #-}
+
+#if MIN_VERSION_vector(0,12,0)
+-- * Modifying vectors
+
+-- | Compute the next (lexicographically) permutation of a given vector
+-- in-place.  Returns 'False' when the input is the last permutation.
+nextPermutation :: forall v n e m. (KnownNat n, Ord e, PrimMonad m, VGM.MVector v e)
+                => MVector v n (PrimState m) e -> m Bool
+nextPermutation (MVector v) = VGM.nextPermutation v
+{-# inline nextPermutation #-}
+#endif
+
+-- ** Filling and copying
+
+-- | Set all elements of the vector to the given value.
+set :: (PrimMonad m, VGM.MVector v a) => MVector v n (PrimState m) a -> a -> m ()
+set (MVector v) = VGM.set v
+{-# inline set #-}
+
+-- | Copy a vector. The two vectors may not overlap.
+copy :: (PrimMonad m, VGM.MVector v a)
+     => MVector v n (PrimState m) a       -- ^ target
+     -> MVector v n (PrimState m) a       -- ^ source
+     -> m ()
+copy (MVector v) (MVector u)
+    | v `VGM.overlaps` u = error "copy: overlapping vectors"
+    | otherwise          = VGM.unsafeCopy v u
+{-# inline copy #-}
+
+-- | Copy a vector. The two vectors may not overlap. This is not checked.
+unsafeCopy :: (PrimMonad m, VGM.MVector v a)
+           => MVector v n (PrimState m) a       -- ^ target
+           -> MVector v n (PrimState m) a       -- ^ source
+           -> m ()
+unsafeCopy (MVector v) (MVector u) = VGM.unsafeCopy v u
+{-# inline unsafeCopy #-}
+
+-- | Move the contents of a vector.  If the two vectors do not overlap,
+-- this is equivalent to 'copy'.  Otherwise, the copying is performed as if
+-- the source vector were copied to a temporary vector and then the
+-- temporary vector was copied to the target vector.
+move :: (PrimMonad m, VGM.MVector v a)
+     => MVector v n (PrimState m) a       -- ^ target
+     -> MVector v n (PrimState m) a       -- ^ source
+     -> m ()
+move (MVector v) (MVector u) = VGM.unsafeMove v u
+{-# inline move #-}
+
+-- * Conversions
+
+-- ** Unsized Mutable Vectors
+
+-- | Convert a 'Data.Vector.Generic.Mutable.MVector' into
+-- a 'Data.Vector.Generic.Mutable.Sized.MVector' if it has the correct
+-- size, otherwise return Nothing.
+--
+-- Note that this does no copying; the returned 'MVector' is a reference to
+-- the exact same vector in memory as the given one, and any modifications
+-- to it are also reflected in the given
+-- 'Data.Vector.Generic.Mutable.MVector'.
+toSized :: forall v n s a. (VGM.MVector v a, KnownNat n)
+        => v s a -> Maybe (MVector v n s a)
+toSized v
+  | n' == fromIntegral (VGM.length v) = Just (MVector v)
+  | otherwise                         = Nothing
+  where n' = natVal (Proxy :: Proxy n)
+{-# inline toSized #-}
+
+-- | Takes a 'Data.Vector.Generic.Mutable.MVector' and returns
+-- a continuation providing a 'Data.Vector.Generic.Mutable.Sized.MVector'
+-- with a size parameter @n@ that is determined at runtime based on the
+-- length of the input vector.
+--
+-- Essentially converts a 'Data.Vector.Generic.Mutable.MVector' into
+-- a 'Data.Vector.Generic.Sized.MVector' with the correct size parameter
+-- @n@.
+--
+-- Note that this does no copying; the returned 'MVector' is a reference to
+-- the exact same vector in memory as the given one, and any modifications
+-- to it are also reflected in the given
+-- 'Data.Vector.Generic.Mutable.MVector'.
+withSized :: forall v s a r. VGM.MVector v a
+          => v s a -> (forall n. KnownNat n => MVector v n s a -> r) -> r
+withSized v f = case someNatVal (fromIntegral (VGM.length v)) of
+    Just (SomeNat (Proxy :: Proxy n)) -> f (MVector v :: MVector v n s a)
+    Nothing -> error "withSized: VGM.length returned negative length."
+
+-- | Convert a 'Data.Vector.Generic.Mutable.Sized.MVector' into a
+-- 'Data.Vector.Generic.Mutable.MVector'.
+--
+-- Note that this does no copying; the returned
+-- 'Data.Vector.Generic.Mutable.MVector' is a reference to the exact same
+-- vector in memory as the given one, and any modifications to it are also
+-- reflected in the given 'MVector'.
+fromSized :: MVector v n s a -> v s a
+fromSized (MVector v) = v
+{-# inline fromSized #-}
+
diff --git a/src/Data/Vector/Generic/Mutable/Sized/Internal.hs b/src/Data/Vector/Generic/Mutable/Sized/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Vector/Generic/Mutable/Sized/Internal.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE KindSignatures #-}
+
+module Data.Vector.Generic.Mutable.Sized.Internal
+  ( MVector(..)
+  ) where
+
+import GHC.Generics (Generic)
+import GHC.TypeLits
+import Control.DeepSeq (NFData)
+import Data.Data
+import Foreign.Storable
+
+-- | A wrapper to tag mutable vectors with a type level length.
+--
+-- Be careful when using the constructor here to not construct sized vectors
+-- which have a different length than that specified in the type parameter!
+newtype MVector v (n :: Nat) s a = MVector (v s a)
+  deriving ( Generic, Typeable, Data, Storable, NFData )
diff --git a/src/Data/Vector/Generic/Sized.hs b/src/Data/Vector/Generic/Sized.hs
--- a/src/Data/Vector/Generic/Sized.hs
+++ b/src/Data/Vector/Generic/Sized.hs
@@ -7,8 +7,12 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE CPP #-}
 
 {-|
 This module reexports the functionality in 'Data.Vector.Generic' which maps well
@@ -22,11 +26,14 @@
 -}
 
 module Data.Vector.Generic.Sized
- ( Vector
+  ( Vector
+  , MVector
    -- * Accessors
    -- ** Length information
   , length
   , length'
+  , knownLength
+  , knownLength'
     -- ** Indexing
   , index
   , index'
@@ -54,11 +61,13 @@
     -- ** Initialization
   , empty
   , singleton
+#if !MIN_VERSION_GLASGOW_HASKELL(8,3,0,0)
+  , fromTuple
+#endif
   , replicate
   , replicate'
   , generate
   , generate'
-  , generate_
   , iterateN
   , iterateN'
     -- ** Monadic initialization
@@ -66,7 +75,6 @@
   , replicateM'
   , generateM
   , generateM'
-  , generateM_
     -- ** Unfolding
   , unfoldrN
   , unfoldrN'
@@ -222,6 +230,12 @@
   , withSizedList
     -- ** Other Vector types
   , convert
+    -- ** Mutable vectors
+  , freeze
+  , thaw
+  , copy
+  , unsafeFreeze
+  , unsafeThaw
     -- ** Unsized Vectors
   , toSized
   , withSized
@@ -229,45 +243,57 @@
   , withVectorUnsafe
   ) where
 
+import Data.Vector.Generic.Sized.Internal
 import qualified Data.Vector.Generic as VG
 import qualified Data.Vector as Boxed
+import qualified Data.Vector.Generic.Mutable.Sized as SVGM
+import Data.Vector.Generic.Mutable.Sized.Internal
 import GHC.Generics (Generic)
 import GHC.TypeLits
+import Data.Bifunctor
 import Data.Finite
 import Data.Finite.Internal
 import Data.Proxy
 import Control.DeepSeq (NFData)
+import Control.Monad.Primitive
 import Foreign.Storable
 import Data.Data
+import Data.Functor.Classes
 import Foreign.Ptr (castPtr)
-import Prelude hiding ( length, null,
-                        replicate, (++), concat,
-                        head, last,
-                        init, tail, take, drop, splitAt, reverse,
-                        map, concat, concatMap,
-                        zipWith, zipWith3, zip, zip3, unzip, unzip3,
-                        filter, takeWhile, dropWhile, span, break,
-                        elem, notElem,
-                        foldl, foldl1, foldr, foldr1,
-                        all, any, and, or, sum, product, maximum, minimum,
-                        scanl, scanl1, scanr, scanr1,
-                        enumFromTo, enumFromThenTo,
-                        mapM, mapM_, sequence, sequence_,
-                        showsPrec )
+import Data.Semigroup
+import Text.Read.Lex
+import Text.ParserCombinators.ReadPrec
+import GHC.Read
+import Data.Type.Equality
+import Unsafe.Coerce
+import Prelude
+       hiding (length, replicate, (++), head, last, init, tail, take,
+               drop, splitAt, reverse, map, concatMap, zipWith, zipWith3, zip,
+               zip3, unzip, unzip3, elem, notElem, foldl, foldl1, foldr, foldr1,
+               all, any, and, or, sum, product, maximum, minimum, scanl, scanl1,
+               scanr, scanr1, mapM, mapM_, sequence, sequence_)
 
--- | A wrapper to tag vectors with a type level length.
-newtype Vector v (n :: Nat) a = Vector (v a)
-  deriving ( Show, Eq, Ord, Functor, Foldable, Traversable, NFData, Generic
-           , Data, Typeable
-           )
 
+#if !MIN_VERSION_GLASGOW_HASKELL(8,3,0,0)
+import Data.IndexedListLiterals hiding (toList)
+import qualified Data.IndexedListLiterals as ILL
+#endif
+
+instance (KnownNat n, VG.Vector v a, Read (v a)) => Read (Vector v n a) where
+  readPrec = parens $ prec 10 $ do
+      expectP (Ident "Vector")
+      vec <- readPrec
+      if VG.length vec == (fromIntegral $ natVal (Proxy :: Proxy n)) then return $ Vector vec else pfail
+
+type instance VG.Mutable (Vector v n) = MVector (VG.Mutable v) n
+
 -- | Any sized vector containing storable elements is itself storable.
 instance (KnownNat n, Storable a, VG.Vector v a)
       => Storable (Vector v n a) where
-  sizeOf _ = sizeOf (undefined :: a) * fromInteger (natVal (Proxy :: Proxy n))
+  sizeOf _ = sizeOf (undefined :: a) * fromIntegral (natVal (Proxy :: Proxy n))
   alignment _ = alignment (undefined :: a)
-  peek ptr = generateM (peekElemOff (castPtr ptr))
-  poke ptr = imapM_ (pokeElemOff (castPtr ptr))
+  peek ptr = generateM (peekElemOff (castPtr ptr) . fromIntegral)
+  poke ptr = imapM_ (pokeElemOff (castPtr ptr) . fromIntegral)
 
 -- | The 'Applicative' instance for sized vectors does not have the same
 -- behaviour as the 'Applicative' instance for the unsized vectors found in the
@@ -276,30 +302,64 @@
 instance KnownNat n => Applicative (Vector Boxed.Vector n) where
   pure = replicate
   (<*>) = zipWith ($)
+  (*>) = seq
+  (<*) = flip seq
 
+-- | The 'Semigroup' instance for sized vectors does not have the same
+-- behaviour as the 'Semigroup' instance for the unsized vectors found in the
+-- 'vectors' package. This instance has @(<>) = zipWith (<>)@, but 'vectors'
+-- uses concatentation.
+instance (Semigroup g, VG.Vector v g) => Semigroup (Vector v n g) where
+  (<>) = zipWith (<>)
+  stimes = map . stimes
+
 -- | The 'Monoid' instance for sized vectors does not have the same
 -- behaviour as the 'Monoid' instance for the unsized vectors found in the
--- 'vectors' package. Its @mempty@ is a vector of @mempty@s and its @mappend@
--- is @zipWith mappend@.
+-- 'vectors' package. This instance has @mempty = replicate mempty@ and
+-- @mappend = zipWith mappend@, where the 'vectors' instance uses the empty
+-- vector and concatenation.
+--
+-- If 'mempty' is not necessary, using the 'Semigroup' instance over this
+-- 'Monoid' will dodge the 'KnownNat' constraint.
 instance (Monoid m, VG.Vector v m, KnownNat n) => Monoid (Vector v n m) where
   mempty = replicate mempty
   mappend = zipWith mappend
-instance {-# OVERLAPPING #-} (VG.Vector v m) => Monoid (Vector v 0 m) where
-  mempty = empty
-  _empty1 `mappend` _empty2 = empty
+  mconcat vs = generate $ mconcat . flip fmap vs . flip index
 
--- | /O(1)/ Yield the length of the vector as an 'Int'.
-length :: forall v n a. (KnownNat n)
+-- | /O(1)/ Yield the length of the vector as an 'Int'. This is more like
+-- 'natVal' than 'Data.Vector.length', extracting the value from the 'KnownNat'
+-- instance and not looking at the vector itself.
+length :: forall v n a. KnownNat n
        => Vector v n a -> Int
-length _ = fromInteger (natVal (Proxy :: Proxy n))
+length _ = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline length #-}
 
--- | /O(1)/ Yield the length of the vector as a 'Proxy'.
-length' :: forall v n a. (KnownNat n)
-        => Vector v n a -> Proxy n
+-- | /O(1)/ Yield the length of the vector as a 'Proxy'. This function
+-- doesn't /do/ anything; it merely allows the size parameter of the vector
+-- to be passed around as a 'Proxy'.
+length' :: forall v n a.
+           Vector v n a -> Proxy n
 length' _ = Proxy
 {-# inline length' #-}
 
+-- | /O(1)/ Reveal a 'KnownNat' instance for a vector's length, determined
+-- at runtime.
+knownLength :: forall v n a r. VG.Vector v a
+            => Vector v n a -- ^ a vector of some (potentially unknown) length
+            -> (KnownNat n => r) -- ^ a value that depends on knowing the vector's length
+            -> r -- ^ the value computed with the length
+knownLength v x = knownLength' v $ const x
+
+-- | /O(1)/ Reveal a 'KnownNat' instance and 'Proxy' for a vector's length,
+-- determined at runtime.
+knownLength' :: forall v n a r. VG.Vector v a
+             => Vector v n a -- ^ a vector of some (potentially unknown) length
+             -> (KnownNat n => Proxy n -> r) -- ^ a value that depends on knowing the vector's length, which is given as a 'Proxy'
+             -> r -- ^ the value computed with the length
+knownLength' (Vector v) x = case someNatVal (fromIntegral (VG.length v)) of
+  Just (SomeNat (Proxy :: Proxy n')) -> case unsafeCoerce Refl :: n' :~: n of Refl -> x Proxy
+  Nothing -> error "impossible: Vector has negative length"
+
 -- | /O(1)/ Safe indexing using a 'Finite'.
 index :: forall v n a. (KnownNat n, VG.Vector v a)
       => Vector v n a -> Finite n -> a
@@ -310,7 +370,7 @@
 index' :: forall v n m a p. (KnownNat n, KnownNat m, VG.Vector v a)
        => Vector v (n+m+1) a -> p n -> a
 index' (Vector v) p = v `VG.unsafeIndex` i
-  where i = fromInteger (natVal p)
+  where i = fromIntegral (natVal p)
 {-# inline index' #-}
 
 -- | /O(1)/ Indexing using an Int without bounds checking.
@@ -361,7 +421,7 @@
 indexM' :: forall v n k a m p. (KnownNat n, KnownNat k, VG.Vector v a, Monad m)
       => Vector v (n+k) a -> p n -> m a
 indexM' (Vector v) p = v `VG.indexM` i
-  where i = fromInteger (natVal p)
+  where i = fromIntegral (natVal p)
 {-# inline indexM' #-}
 
 -- | /O(1)/ Indexing using an Int without bounds checking. See the
@@ -392,8 +452,8 @@
       -> Vector v (i+n+m) a
       -> Vector v n a
 slice start (Vector v) = Vector (VG.unsafeSlice i n v)
-  where i = fromInteger (natVal start)
-        n = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal start)
+        n = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline slice #-}
 
 -- | /O(1)/ Yield a slice of the vector without copying it with an explicit
@@ -427,7 +487,7 @@
 take :: forall v n m a. (KnownNat n, KnownNat m, VG.Vector v a)
      => Vector v (n+m) a -> Vector v n a
 take (Vector v) = Vector (VG.unsafeTake i v)
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline take #-}
 
 -- | /O(1)/ Yield the first n elements. The resultant vector always contains
@@ -444,7 +504,7 @@
 drop :: forall v n m a. (KnownNat n, KnownNat m, VG.Vector v a)
      => Vector v (n+m) a -> Vector v m a
 drop (Vector v) = Vector (VG.unsafeDrop i v)
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline drop #-}
 
 -- | /O(1)/ Yield all but the the first n elements. The given vector must
@@ -460,7 +520,7 @@
 splitAt :: forall v n m a. (KnownNat n, KnownNat m, VG.Vector v a)
         => Vector v (n+m) a -> (Vector v n a, Vector v m a)
 splitAt (Vector v) = (Vector a, Vector b)
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
         (a, b) = VG.splitAt i v
 {-# inline splitAt #-}
 
@@ -492,12 +552,22 @@
 singleton a = Vector (VG.singleton a)
 {-# inline singleton #-}
 
+#if !MIN_VERSION_GLASGOW_HASKELL(8,3,0,0)
+-- | /O(n)/ Construct a vector in a type safe manner
+--   fromTuple (1,2) :: Vector v 2 Int
+--   fromTuple ("hey", "what's", "going", "on") :: Vector v 4 String
+fromTuple :: forall v a input length.
+             (VG.Vector v a, IndexedListLiterals input length a, KnownNat length)
+          => input -> Vector v length a
+fromTuple = Vector . VG.fromListN (fromIntegral $ natVal $ Proxy @length) . ILL.toList
+#endif
+
 -- | /O(n)/ Construct a vector with the same element in each position where the
 -- length is inferred from the type.
 replicate :: forall v n a. (KnownNat n, VG.Vector v a)
           => a -> Vector v n a
 replicate a = Vector (VG.replicate i a)
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline replicate #-}
 
 -- | /O(n)/ Construct a vector with the same element in each position where the
@@ -510,35 +580,24 @@
 -- | /O(n)/ construct a vector of the given length by applying the function to
 -- each index where the length is inferred from the type.
 generate :: forall v n a. (KnownNat n, VG.Vector v a)
-         => (Int -> a) -> Vector v n a
-generate f = Vector (VG.generate i f)
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+         => (Finite n -> a) -> Vector v n a
+generate f = Vector (VG.generate i (f . Finite . fromIntegral))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline generate #-}
 
 -- | /O(n)/ construct a vector of the given length by applying the function to
 -- each index where the length is given explicitly as a 'Proxy' argument.
 generate' :: forall v n a p. (KnownNat n, VG.Vector v a)
-          => p n -> (Int -> a) -> Vector v n a
+          => p n -> (Finite n -> a) -> Vector v n a
 generate' _ = generate
 {-# inline generate' #-}
 
--- | /O(n)/ construct a vector of the given length by applying the function to
--- each index where the length is inferred from the type.
---
--- The function can expect a @'Finite' n@, meaning that its input will
--- always be between @0@ and @n - 1@.
-generate_ :: forall v n a. (KnownNat n, VG.Vector v a)
-          => (Finite n -> a) -> Vector v n a
-generate_ f = Vector (VG.generate i (f . Finite . fromIntegral))
-  where i = fromInteger (natVal (Proxy :: Proxy n))
-{-# inline generate_ #-}
-
 -- | /O(n)/ Apply function n times to value. Zeroth element is original value.
 -- The length is inferred from the type.
 iterateN :: forall v n a. (KnownNat n, VG.Vector v a)
          => (a -> a) -> a -> Vector v n a
 iterateN f z = Vector (VG.iterateN i f z)
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline iterateN #-}
 
 -- | /O(n)/ Apply function n times to value. Zeroth element is original value.
@@ -557,7 +616,7 @@
 replicateM :: forall v n m a. (KnownNat n, VG.Vector v a, Monad m)
            => m a -> m (Vector v n a)
 replicateM a = Vector <$> VG.replicateM i a
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline replicateM #-}
 
 -- | /O(n)/ Execute the monadic action @n@ times and store the results in a
@@ -570,30 +629,19 @@
 -- | /O(n)/ Construct a vector of length @n@ by applying the monadic action to
 -- each index where n is inferred from the type.
 generateM :: forall v n m a. (KnownNat n, VG.Vector v a, Monad m)
-          => (Int -> m a) -> m (Vector v n a)
-generateM f = Vector <$> VG.generateM i f
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+          => (Finite n -> m a) -> m (Vector v n a)
+generateM f = Vector <$> VG.generateM i (f . Finite . fromIntegral)
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline generateM #-}
 
 -- | /O(n)/ Construct a vector of length @n@ by applying the monadic action to
 -- each index where n is given explicitly as a 'Proxy' argument.
 generateM' :: forall v n m a p. (KnownNat n, VG.Vector v a, Monad m)
-           => p n -> (Int -> m a) -> m (Vector v n a)
+           => p n -> (Finite n -> m a) -> m (Vector v n a)
 generateM' _ = generateM
 {-# inline generateM' #-}
 
--- | /O(n)/ Construct a vector of length @n@ by applying the monadic action to
--- each index where n is inferred from the type.
 --
--- The function can expect a @'Finite' n@, meaning that its input will
--- always be between @0@ and @n - 1@.
-generateM_ :: forall v n m a. (KnownNat n, VG.Vector v a, Monad m)
-           => (Finite n -> m a) -> m (Vector v n a)
-generateM_ f = Vector <$> VG.generateM i (f . Finite . fromIntegral)
-  where i = fromInteger (natVal (Proxy :: Proxy n))
-{-# inline generateM_ #-}
-
---
 -- ** Unfolding
 --
 
@@ -603,7 +651,7 @@
 unfoldrN :: forall v n a b. (KnownNat n, VG.Vector v a)
          => (b -> (a, b)) -> b -> Vector v n a
 unfoldrN f z = Vector (VG.unfoldrN i (Just . f) z)
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline unfoldrN #-}
 
 -- | /O(n)/ Construct a vector with exactly @n@ elements by repeatedly applying
@@ -623,7 +671,7 @@
 enumFromN :: forall v n a. (KnownNat n, VG.Vector v a, Num a)
           => a -> Vector v n a
 enumFromN a = Vector (VG.enumFromN a i)
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline enumFromN #-}
 
 -- | /O(n)/ Yield a vector of length @n@ containing the values @x@, @x+1@
@@ -638,7 +686,7 @@
 enumFromStepN :: forall v n a. (KnownNat n, VG.Vector v a, Num a)
           => a -> a -> Vector v n a
 enumFromStepN a a' = Vector (VG.enumFromStepN a a' i)
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline enumFromStepN #-}
 
 -- | /O(n)/ Yield a vector of the given length containing the values @x@, @x+y@,
@@ -703,10 +751,10 @@
 -- > <5,9,2,7> // [(2,1),(0,3),(2,8)] = <3,9,8,7>
 --
 (//) :: (VG.Vector v a)
-     => Vector v m a -- ^ initial vector (of length @m@)
-     -> [(Int, a)]   -- ^ list of index/value pairs (of length @n@)
+     => Vector v m a    -- ^ initial vector (of length @m@)
+     -> [(Finite m, a)] -- ^ list of index/value pairs (of length @n@)
      -> Vector v m a
-Vector v // us = Vector (v VG.// us)
+Vector v // us = Vector (v VG.// (fmap . first) (fromIntegral . getFinite) us)
 {-# inline (//) #-}
 
 -- | /O(m+n)/ For each pair @(i,a)@ from the vector of index/value pairs,
@@ -883,9 +931,9 @@
 --
 
 -- | /O(n)/ Pair each element in a vector with its index
-indexed :: (VG.Vector v a, VG.Vector v (Int,a))
-        => Vector v n a -> Vector v n (Int,a)
-indexed (Vector v) = Vector (VG.indexed v)
+indexed :: (VG.Vector v a, VG.Vector v (Int, a), VG.Vector v (Finite n,a))
+        => Vector v n a -> Vector v n (Finite n,a)
+indexed (Vector v) = Vector ((VG.map . first) (Finite . fromIntegral) $ VG.indexed v)
 {-# inline indexed #-}
 
 --
@@ -900,8 +948,8 @@
 
 -- | /O(n)/ Apply a function to every element of a vector and its index
 imap :: (VG.Vector v a, VG.Vector v b)
-     => (Int -> a -> b) -> Vector v n a -> Vector v n b
-imap f (Vector v) = Vector (VG.imap f v)
+     => (Finite n -> a -> b) -> Vector v n a -> Vector v n b
+imap f (Vector v) = Vector (VG.imap (f . Finite . fromIntegral) v)
 {-# inline imap #-}
 
 -- | /O(n*m)/ Map a function over a vector and concatenate the results. The
@@ -925,8 +973,8 @@
 -- | /O(n)/ Apply the monadic action to every element of a vector and its
 -- index, yielding a vector of results
 imapM :: (Monad m, VG.Vector v a, VG.Vector v b)
-      => (Int -> a -> m b) -> Vector v n a -> m (Vector v n b)
-imapM f (Vector v) = Vector <$> (VG.imapM f v)
+      => (Finite n -> a -> m b) -> Vector v n a -> m (Vector v n b)
+imapM f (Vector v) = Vector <$> (VG.imapM (f . Finite . fromIntegral) v)
 {-# inline imapM #-}
 
 -- | /O(n)/ Apply the monadic action to all elements of a vector and ignore the
@@ -937,8 +985,8 @@
 
 -- | /O(n)/ Apply the monadic action to every element of a vector and its
 -- index, ignoring the results
-imapM_ :: (Monad m, VG.Vector v a) => (Int -> a -> m b) -> Vector v n a -> m ()
-imapM_ f (Vector v) = VG.imapM_ f v
+imapM_ :: (Monad m, VG.Vector v a) => (Finite n -> a -> m b) -> Vector v n a -> m ()
+imapM_ f (Vector v) = VG.imapM_ (f . Finite . fromIntegral) v
 {-# inline imapM_ #-}
 
 -- | /O(n)/ Apply the monadic action to all elements of the vector, yielding a
@@ -1009,37 +1057,37 @@
 -- | /O(n)/ Zip two vectors of the same length with a function that also takes
 -- the elements' indices).
 izipWith :: (VG.Vector v a,VG.Vector v b,VG.Vector v c)
-         => (Int -> a -> b -> c)
+         => (Finite n -> a -> b -> c)
          -> Vector v n a
          -> Vector v n b
          -> Vector v n c
 izipWith f (Vector xs) (Vector ys)
-  = Vector (VG.izipWith f xs ys)
+  = Vector (VG.izipWith (f . Finite . fromIntegral) xs ys)
 {-# inline izipWith #-}
 
 izipWith3 :: (VG.Vector v a,VG.Vector v b,VG.Vector v c,VG.Vector v d)
-          => (Int -> a -> b -> c -> d)
+          => (Finite n -> a -> b -> c -> d)
           -> Vector v n a
           -> Vector v n b
           -> Vector v n c
           -> Vector v n d
 izipWith3 f (Vector as) (Vector bs) (Vector cs)
-  = Vector (VG.izipWith3 f as bs cs)
+  = Vector (VG.izipWith3 (f . Finite . fromIntegral) as bs cs)
 {-# inline izipWith3 #-}
 
 izipWith4 :: (VG.Vector v a,VG.Vector v b,VG.Vector v c,VG.Vector v d,VG.Vector v e)
-          => (Int -> a -> b -> c -> d -> e)
+          => (Finite n -> a -> b -> c -> d -> e)
           -> Vector v n a
           -> Vector v n b
           -> Vector v n c
           -> Vector v n d
           -> Vector v n e
 izipWith4 f (Vector as) (Vector bs) (Vector cs) (Vector ds)
-  = Vector (VG.izipWith4 f as bs cs ds)
+  = Vector (VG.izipWith4 (f . Finite . fromIntegral) as bs cs ds)
 {-# inline izipWith4 #-}
 
 izipWith5 :: (VG.Vector v a,VG.Vector v b,VG.Vector v c,VG.Vector v d,VG.Vector v e,VG.Vector v f)
-          => (Int -> a -> b -> c -> d -> e -> f)
+          => (Finite n -> a -> b -> c -> d -> e -> f)
           -> Vector v n a
           -> Vector v n b
           -> Vector v n c
@@ -1047,11 +1095,11 @@
           -> Vector v n e
           -> Vector v n f
 izipWith5 f (Vector as) (Vector bs) (Vector cs) (Vector ds) (Vector es)
-  = Vector (VG.izipWith5 f as bs cs ds es)
+  = Vector (VG.izipWith5 (f . Finite . fromIntegral) as bs cs ds es)
 {-# inline izipWith5 #-}
 
 izipWith6 :: (VG.Vector v a,VG.Vector v b,VG.Vector v c,VG.Vector v d,VG.Vector v e,VG.Vector v f,VG.Vector v g)
-          => (Int -> a -> b -> c -> d -> e -> f -> g)
+          => (Finite n -> a -> b -> c -> d -> e -> f -> g)
           -> Vector v n a
           -> Vector v n b
           -> Vector v n c
@@ -1060,7 +1108,7 @@
           -> Vector v n f
           -> Vector v n g
 izipWith6 f (Vector as) (Vector bs) (Vector cs) (Vector ds) (Vector es) (Vector fs)
-  = Vector (VG.izipWith6 f as bs cs ds es fs)
+  = Vector (VG.izipWith6 (f . Finite . fromIntegral) as bs cs ds es fs)
 {-# inline izipWith6 #-}
 
 -- | /O(n)/ Zip two vectors of the same length
@@ -1118,8 +1166,8 @@
 -- | /O(n)/ Zip the two vectors with a monadic action that also takes the
 -- element index and yield a vector of results
 izipWithM :: (Monad m, VG.Vector v a, VG.Vector v b, VG.Vector v c)
-         => (Int -> a -> b -> m c) -> Vector v n a -> Vector v n b -> m (Vector v n c)
-izipWithM m (Vector as) (Vector bs) = Vector <$> VG.izipWithM m as bs
+         => (Finite n -> a -> b -> m c) -> Vector v n a -> Vector v n b -> m (Vector v n c)
+izipWithM m (Vector as) (Vector bs) = Vector <$> VG.izipWithM (m . Finite . fromIntegral) as bs
 {-# inline izipWithM #-}
 
 -- | /O(n)/ Zip the two vectors with the monadic action and ignore the results
@@ -1131,8 +1179,8 @@
 -- | /O(n)/ Zip the two vectors with a monadic action that also takes
 -- the element index and ignore the results
 izipWithM_ :: (Monad m, VG.Vector v a, VG.Vector v b)
-           => (Int -> a -> b -> m c) -> Vector v n a -> Vector v n b -> m ()
-izipWithM_ m (Vector as) (Vector bs) = VG.izipWithM_ m as bs
+           => (Finite n -> a -> b -> m c) -> Vector v n a -> Vector v n b -> m ()
+izipWithM_ m (Vector as) (Vector bs) = VG.izipWithM_ (m . Finite . fromIntegral) as bs
 {-# inline izipWithM_ #-}
 
 -- Unzipping
@@ -1210,15 +1258,15 @@
 
 -- | /O(n)/ Yield 'Just' the index of the first element matching the predicate
 -- or 'Nothing' if no such element exists.
-findIndex :: VG.Vector v a => (a -> Bool) -> Vector v n a -> Maybe Int
-findIndex f (Vector v) = VG.findIndex f v
+findIndex :: VG.Vector v a => (a -> Bool) -> Vector v n a -> Maybe (Finite n)
+findIndex f (Vector v) = Finite . fromIntegral <$> VG.findIndex f v
 {-# inline findIndex #-}
 
 -- | /O(n)/ Yield 'Just' the index of the first occurence of the given element or
 -- 'Nothing' if the vector does not contain the element. This is a specialised
 -- version of 'findIndex'.
-elemIndex :: (VG.Vector v a, Eq a) => a -> Vector v n a -> Maybe Int
-elemIndex x (Vector v) = VG.elemIndex x v
+elemIndex :: (VG.Vector v a, Eq a) => a -> Vector v n a -> Maybe (Finite n)
+elemIndex x (Vector v) = Finite . fromIntegral <$> VG.elemIndex x v
 {-# inline elemIndex #-}
 
 --------------------------------------------------------------------------------
@@ -1266,25 +1314,25 @@
 {-# inline foldr1' #-}
 
 -- | /O(n)/ Left fold (function applied to each element and its index)
-ifoldl :: VG.Vector v b => (a -> Int -> b -> a) -> a -> Vector v n b -> a
-ifoldl f z = VG.ifoldl f z . fromSized
+ifoldl :: VG.Vector v b => (a -> Finite n -> b -> a) -> a -> Vector v n b -> a
+ifoldl f z = VG.ifoldl (\x -> f x . Finite . fromIntegral) z . fromSized
 {-# inline ifoldl #-}
 
 -- | /O(n)/ Left fold with strict accumulator (function applied to each element
 -- and its index)
-ifoldl' :: VG.Vector v b => (a -> Int -> b -> a) -> a -> Vector v n b -> a
-ifoldl' f z = VG.ifoldl' f z . fromSized
+ifoldl' :: VG.Vector v b => (a -> Finite n -> b -> a) -> a -> Vector v n b -> a
+ifoldl' f z = VG.ifoldl' (\x -> f x . Finite . fromIntegral) z . fromSized
 {-# inline ifoldl' #-}
 
 -- | /O(n)/ Right fold (function applied to each element and its index)
-ifoldr :: VG.Vector v a => (Int -> a -> b -> b) -> b -> Vector v n a -> b
-ifoldr f z = VG.ifoldr f z . fromSized
+ifoldr :: VG.Vector v a => (Finite n -> a -> b -> b) -> b -> Vector v n a -> b
+ifoldr f z = VG.ifoldr (f . Finite . fromIntegral) z . fromSized
 {-# inline ifoldr #-}
 
 -- | /O(n)/ Right fold with strict accumulator (function applied to each
 -- element and its index)
-ifoldr' :: VG.Vector v a => (Int -> a -> b -> b) -> b -> Vector v n a -> b
-ifoldr' f z = VG.ifoldr' f z . fromSized
+ifoldr' :: VG.Vector v a => (Finite n -> a -> b -> b) -> b -> Vector v n a -> b
+ifoldr' f z = VG.ifoldr' (f . Finite . fromIntegral) z . fromSized
 {-# inline ifoldr' #-}
 
 -- ** Specialised folds
@@ -1344,27 +1392,27 @@
 {-# inline minimumBy #-}
 
 -- | /O(n)/ Yield the index of the maximum element of the non-empty vector.
-maxIndex :: (VG.Vector v a, Ord a, KnownNat n) => Vector v (n+1) a -> Int
-maxIndex = VG.maxIndex . fromSized
+maxIndex :: (VG.Vector v a, Ord a, KnownNat n) => Vector v (n+1) a -> Finite (n+1)
+maxIndex = Finite . fromIntegral . VG.maxIndex . fromSized
 {-# inline maxIndex #-}
 
 -- | /O(n)/ Yield the index of the maximum element of the non-empty vector
 -- according to the given comparison function.
 maxIndexBy :: (VG.Vector v a, KnownNat n)
-           => (a -> a -> Ordering) -> Vector v (n+1) a -> Int
-maxIndexBy cmpr = VG.maxIndexBy cmpr . fromSized
+           => (a -> a -> Ordering) -> Vector v (n+1) a -> Finite (n + 1)
+maxIndexBy cmpr = Finite . fromIntegral . VG.maxIndexBy cmpr . fromSized
 {-# inline maxIndexBy #-}
 
 -- | /O(n)/ Yield the index of the minimum element of the non-empty vector.
-minIndex :: (VG.Vector v a, Ord a, KnownNat n) => Vector v (n+1) a -> Int
-minIndex = VG.minIndex . fromSized
+minIndex :: (VG.Vector v a, Ord a, KnownNat n) => Vector v (n+1) a -> Finite (n+1)
+minIndex = Finite . fromIntegral . VG.minIndex . fromSized
 {-# inline minIndex #-}
 
 -- | /O(n)/ Yield the index of the minimum element of the non-empty vector
 -- according to the given comparison function.
 minIndexBy :: (VG.Vector v a, KnownNat n)
-           => (a -> a -> Ordering) -> Vector v (n+1) a -> Int
-minIndexBy cmpr = VG.minIndexBy cmpr . fromSized
+           => (a -> a -> Ordering) -> Vector v (n+1) a -> Finite (n + 1)
+minIndexBy cmpr = Finite . fromIntegral . VG.minIndexBy cmpr . fromSized
 {-# inline minIndexBy #-}
 
 -- ** Monadic folds
@@ -1375,8 +1423,8 @@
 {-# inline foldM #-}
 
 -- | /O(n)/ Monadic fold (action applied to each element and its index)
-ifoldM :: (Monad m, VG.Vector v b) => (a -> Int -> b -> m a) -> a -> Vector v n b -> m a
-ifoldM m z = VG.ifoldM m z . fromSized
+ifoldM :: (Monad m, VG.Vector v b) => (a -> Finite n -> b -> m a) -> a -> Vector v n b -> m a
+ifoldM m z = VG.ifoldM (\x -> m x . Finite . fromIntegral) z . fromSized
 {-# inline ifoldM #-}
 
 -- | /O(n)/ Monadic fold over non-empty vectors
@@ -1393,8 +1441,8 @@
 -- | /O(n)/ Monadic fold with strict accumulator (action applied to each
 -- element and its index)
 ifoldM' :: (Monad m, VG.Vector v b)
-        => (a -> Int -> b -> m a) -> a -> Vector v n b -> m a
-ifoldM' m z = VG.ifoldM' m z . fromSized
+        => (a -> Finite n -> b -> m a) -> a -> Vector v n b -> m a
+ifoldM' m z = VG.ifoldM' (\x -> m x . Finite . fromIntegral) z . fromSized
 {-# inline ifoldM' #-}
 
 -- | /O(n)/ Monadic fold over non-empty vectors with strict accumulator
@@ -1412,8 +1460,8 @@
 -- | /O(n)/ Monadic fold that discards the result (action applied to
 -- each element and its index)
 ifoldM_ :: (Monad m, VG.Vector v b)
-        => (a -> Int -> b -> m a) -> a -> Vector v n b -> m ()
-ifoldM_ m z = VG.ifoldM_ m z . fromSized
+        => (a -> Finite n -> b -> m a) -> a -> Vector v n b -> m ()
+ifoldM_ m z = VG.ifoldM_ (\x -> m x . Finite . fromIntegral)  z . fromSized
 {-# inline ifoldM_ #-}
 
 -- | /O(n)/ Monadic fold over non-empty vectors that discards the result
@@ -1431,8 +1479,8 @@
 -- | /O(n)/ Monadic fold with strict accumulator that discards the result
 -- (action applied to each element and its index)
 ifoldM'_ :: (Monad m, VG.Vector v b)
-         => (a -> Int -> b -> m a) -> a -> Vector v n b -> m ()
-ifoldM'_ m z = VG.ifoldM'_ m z . fromSized
+         => (a -> Finite n -> b -> m a) -> a -> Vector v n b -> m ()
+ifoldM'_ m z = VG.ifoldM'_ (\x -> m x . Finite . fromIntegral) z . fromSized
 {-# inline ifoldM'_ #-}
 
 -- | /O(n)/ Monad fold over non-empty vectors with strict accumulator
@@ -1567,7 +1615,7 @@
 fromListN :: forall v n a. (VG.Vector v a, KnownNat n)
           => [a] -> Maybe (Vector v n a)
 fromListN = toSized . VG.fromListN i
-  where i = fromInteger (natVal (Proxy :: Proxy n))
+  where i = fromIntegral (natVal (Proxy :: Proxy n))
 {-# inline fromListN #-}
 
 -- | /O(n)/ Convert the first @n@ elements of a list to a vector. The length of
@@ -1595,6 +1643,41 @@
 convert = withVectorUnsafe VG.convert
 {-# inline convert #-}
 
+-- ** Mutable vectors
+
+-- | /O(n)/ Yield an immutable copy of the mutable vector.
+freeze :: (PrimMonad m, VG.Vector v a)
+       => SVGM.MVector (VG.Mutable v) n (PrimState m) a
+       -> m (Vector v n a)
+freeze (MVector v) = Vector <$> VG.freeze v
+
+-- | /O(1)/ Unsafely convert a mutable vector to an immutable one withouy
+-- copying. The mutable vector may not be used after this operation.
+unsafeFreeze :: (PrimMonad m, VG.Vector v a)
+             => SVGM.MVector (VG.Mutable v) n (PrimState m) a
+             -> m (Vector v n a)
+unsafeFreeze (MVector v) = Vector <$> VG.unsafeFreeze v
+
+-- | /O(n)/ Yield a mutable copy of the immutable vector.
+thaw :: (PrimMonad m, VG.Vector v a)
+     => Vector v n a
+     -> m (SVGM.MVector (VG.Mutable v) n (PrimState m) a)
+thaw (Vector v) = MVector <$> VG.thaw v
+
+-- | /O(n)/ Unsafely convert an immutable vector to a mutable one without
+-- copying. The immutable vector may not be used after this operation.
+unsafeThaw :: (PrimMonad m, VG.Vector v a)
+           => Vector v n a
+           -> m (SVGM.MVector (VG.Mutable v) n (PrimState m) a)
+unsafeThaw (Vector v) = MVector <$> VG.unsafeThaw v
+
+-- | /O(n)/ Copy an immutable vector into a mutable one.
+copy :: (PrimMonad m, VG.Vector v a)
+     => SVGM.MVector (VG.Mutable v) n (PrimState m) a
+     -> Vector v n a
+     -> m ()
+copy (MVector v) (Vector u) = VG.unsafeCopy v u
+
 -- ** Unsized vectors
 
 -- | Convert a 'Data.Vector.Generic.Vector' into a
@@ -1618,8 +1701,8 @@
 withSized :: forall v a r. VG.Vector v a
           => v a -> (forall n. KnownNat n => Vector v n a -> r) -> r
 withSized v f = case someNatVal (fromIntegral (VG.length v)) of
-    Just (SomeNat (Proxy :: Proxy n)) -> f (Vector v :: Vector v n a)
-    Nothing -> error "withSized: VG.length returned negative length."
+  Just (SomeNat (Proxy :: Proxy n)) -> f (Vector v :: Vector v n a)
+  Nothing -> error "impossible: Vector has negative length"
 
 fromSized :: Vector v n a -> v a
 fromSized (Vector v) = v
diff --git a/src/Data/Vector/Generic/Sized/Internal.hs b/src/Data/Vector/Generic/Sized/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Vector/Generic/Sized/Internal.hs
@@ -0,0 +1,27 @@
+{-# LANGUAGE DataKinds                  #-}
+{-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE DeriveTraversable          #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE KindSignatures             #-}
+
+module Data.Vector.Generic.Sized.Internal
+  ( Vector(..)
+  ) where
+
+import           Control.DeepSeq      (NFData)
+import           Data.Data
+import           Data.Functor.Classes
+import           Foreign.Storable
+import           GHC.Generics         (Generic)
+import           GHC.TypeLits
+
+-- | A wrapper to tag vectors with a type level length.
+--
+-- Be careful when using the constructor here to not construct sized vectors
+-- which have a different length than that specified in the type parameter!
+newtype Vector v (n :: Nat) a = Vector (v a)
+  deriving ( Show, Eq, Ord, Functor, Foldable, Traversable, NFData, Generic
+           , Show1, Eq1, Ord1
+           , Data, Typeable
+           )
diff --git a/src/Data/Vector/Mutable/Sized.hs b/src/Data/Vector/Mutable/Sized.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Vector/Mutable/Sized.hs
@@ -0,0 +1,474 @@
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RankNTypes       #-}
+{-# LANGUAGE TypeOperators    #-}
+
+{-|
+This module re-exports the functionality in 'Data.Vector.Generic.Mutable.Sized'
+ specialized to 'Data.Vector.Mutable'
+
+Functions returning a vector determine the size from the type context unless
+they have a @'@ suffix in which case they take an explicit 'Proxy' argument.
+
+Functions where the resultant vector size is not know until compile time are
+not exported.
+-}
+
+module Data.Vector.Mutable.Sized
+ ( MVector
+   -- * Accessors
+   -- ** Length information
+  , length
+  , length'
+  , null
+   -- ** Extracting subvectors
+  , slice
+  , slice'
+  , init
+  , tail
+  , take
+  , take'
+  , drop
+  , drop'
+  , splitAt
+  , splitAt'
+  -- ** Overlaps
+  , overlaps
+  -- * Construction
+  -- ** Initialisation
+  , new
+  , unsafeNew
+  , replicate
+  , replicate'
+  , replicateM
+  , replicateM'
+  , clone
+  -- ** Growing
+  , grow
+  , growFront
+  -- ** Restricting memory usage
+  , clear
+  -- * Accessing individual elements
+  , read
+  , read'
+  , write
+  , write'
+  , modify
+  , modify'
+  , swap
+  , exchange
+  , exchange'
+  , unsafeRead
+  , unsafeWrite
+  , unsafeModify
+  , unsafeSwap
+  , unsafeExchange
+#if MIN_VERSION_vector(0,12,0)
+  -- * Modifying vectors
+  , nextPermutation
+#endif
+  -- ** Filling and copying
+  , set
+  , copy
+  , move
+  , unsafeCopy
+    -- * Conversions
+    -- ** Unsized Mutable Vectors
+  , toSized
+  , withSized
+  , fromSized
+  ) where
+
+import qualified Data.Vector.Generic.Mutable.Sized as VGM
+import qualified Data.Vector.Mutable as VM
+import GHC.TypeLits
+import Data.Finite
+import Data.Proxy
+import Control.Monad.Primitive
+import Prelude hiding ( length, null, replicate, init,
+                        tail, take, drop, splitAt, read )
+
+
+-- | 'Data.Vector.Generic.Mutable.Sized.Vector' specialized to use
+-- 'Data.Vector.Storable.Mutable'
+type MVector = VGM.MVector VM.MVector
+
+-- * Accessors
+
+-- ** Length information
+
+-- | /O(1)/ Yield the length of the mutable vector as an 'Int'.
+length :: forall n s a. (KnownNat n)
+       => MVector n s a -> Int
+length = VGM.length
+{-# inline length #-}
+
+-- | /O(1)/ Yield the length of the mutable vector as a 'Proxy'.
+length' :: forall n s a. (KnownNat n)
+        => MVector n s a -> Proxy n
+length' = VGM.length'
+{-# inline length' #-}
+
+-- | /O(1)/ Check whether the mutable vector is empty
+null :: forall n s a. (KnownNat n)
+       => MVector n s a -> Bool
+null = VGM.null
+{-# inline null #-}
+
+-- ** Extracting subvectors
+
+-- | /O(1)/ Yield a slice of the mutable vector without copying it with an
+-- inferred length argument.
+slice :: forall i n k s a p. (KnownNat i, KnownNat n, KnownNat k)
+      => p i -- ^ starting index
+      -> MVector (i+n+k) s a
+      -> MVector n s a
+slice = VGM.slice
+{-# inline slice #-}
+
+-- | /O(1)/ Yield a slice of the mutable vector without copying it with an
+-- explicit length argument.
+slice' :: forall i n k s a p
+        . (KnownNat i, KnownNat n, KnownNat k)
+       => p i -- ^ starting index
+       -> p n -- ^ length
+       -> MVector (i+n+k) s a
+       -> MVector n s a
+slice' = VGM.slice'
+{-# inline slice' #-}
+
+-- | /O(1)/ Yield all but the last element of a non-empty mutable vector
+-- without copying.
+init :: forall n s a. ()
+     => MVector (n+1) s a -> MVector n s a
+init = VGM.init
+{-# inline init #-}
+
+-- | /O(1)/ Yield all but the first element of a non-empty mutable vector
+-- without copying.
+tail :: forall n s a. ()
+     => MVector (1+n) s a -> MVector n s a
+tail = VGM.tail
+{-# inline tail #-}
+
+-- | /O(1)/ Yield the first n elements. The resultant vector always contains
+-- this many elements. The length of the resultant vector is inferred from the
+-- type.
+take :: forall n k s a. (KnownNat n, KnownNat k)
+     => MVector (n+k) s a -> MVector n s a
+take = VGM.take
+{-# inline take #-}
+
+-- | /O(1)/ Yield the first n elements. The resultant vector always contains
+-- this many elements. The length of the resultant vector is given explicitly
+-- as a 'Proxy' argument.
+take' :: forall n k s a p. (KnownNat n, KnownNat k)
+      => p n -> MVector (n+k) s a -> MVector n s a
+take' = VGM.take'
+{-# inline take' #-}
+
+-- | /O(1)/ Yield all but the the first n elements. The given vector must
+-- contain at least this many elements The length of the resultant vector is
+-- inferred from the type.
+drop :: forall n k s a. (KnownNat n, KnownNat k)
+     => MVector (n+k) s a -> MVector k s a
+drop = VGM.drop
+{-# inline drop #-}
+
+-- | /O(1)/ Yield all but the the first n elements. The given vector must
+-- contain at least this many elements The length of the resultant vector is
+-- givel explicitly as a 'Proxy' argument.
+drop' :: forall n k s a p. (KnownNat n, KnownNat k)
+      => p n -> MVector (n+k) s a -> MVector k s a
+drop' = VGM.drop'
+{-# inline drop' #-}
+
+-- | /O(1)/ Yield the first n elements paired with the remainder without copying.
+-- The lengths of the resultant vector are inferred from the type.
+splitAt :: forall n m s a. (KnownNat n, KnownNat m)
+        => MVector (n+m) s a -> (MVector n s a, MVector m s a)
+splitAt = VGM.splitAt
+{-# inline splitAt #-}
+
+-- | /O(1)/ Yield the first n elements paired with the remainder without
+-- copying.  The length of the first resultant vector is passed explicitly as a
+-- 'Proxy' argument.
+splitAt' :: forall n m s a p. (KnownNat n, KnownNat m)
+         => p n -> MVector (n+m) s a -> (MVector n s a, MVector m s a)
+splitAt' = VGM.splitAt'
+{-# inline splitAt' #-}
+
+-- ** Overlaps
+
+-- | /O(1)/ Yield all but the the first n elements. The given vector must
+-- contain at least this many elements The length of the resultant vector is
+-- inferred from the type.
+overlaps :: forall n k s a. (KnownNat n, KnownNat k)
+         => MVector n s a
+         -> MVector k s a
+         -> Bool
+overlaps = VGM.overlaps
+{-# inline overlaps #-}
+
+-- * Construction
+
+-- ** Initialisation
+
+-- | Create a mutable vector where the length is inferred from the type.
+new :: forall n m a. (KnownNat n, PrimMonad m)
+    => m (MVector n (PrimState m) a)
+new = VGM.new
+{-# inline new #-}
+
+-- | Create a mutable vector where the length is inferred from the type.
+-- The memory is not initialized.
+unsafeNew :: forall n m a. (KnownNat n, PrimMonad m)
+          => m (MVector n (PrimState m) a)
+unsafeNew = VGM.unsafeNew
+{-# inline unsafeNew #-}
+
+-- | Create a mutable vector where the length is inferred from the type and
+-- fill it with an initial value.
+replicate :: forall n m a. (KnownNat n, PrimMonad m)
+          => a -> m (MVector n (PrimState m) a)
+replicate = VGM.replicate
+{-# inline replicate #-}
+
+-- | Create a mutable vector where the length is given explicitly as
+-- a 'Proxy' argument and fill it with an initial value.
+replicate' :: forall n m a p. (KnownNat n, PrimMonad m)
+           => p n -> a -> m (MVector n (PrimState m) a)
+replicate' = VGM.replicate'
+{-# inline replicate' #-}
+
+-- | Create a mutable vector where the length is inferred from the type and
+-- fill it with values produced by repeatedly executing the monadic action.
+replicateM :: forall n m a. (KnownNat n, PrimMonad m)
+           => m a -> m (MVector n (PrimState m) a)
+replicateM = VGM.replicateM
+{-# inline replicateM #-}
+
+-- | Create a mutable vector where the length is given explicitly as
+-- a 'Proxy' argument and fill it with values produced by repeatedly
+-- executing the monadic action.
+replicateM' :: forall n m a p. (KnownNat n, PrimMonad m)
+           => p n -> m a -> m (MVector n (PrimState m) a)
+replicateM' = VGM.replicateM'
+{-# inline replicateM' #-}
+
+-- | Create a copy of a mutable vector.
+clone :: forall n m a. PrimMonad m
+      => MVector n (PrimState m) a -> m (MVector n (PrimState m) a)
+clone = VGM.clone
+{-# inline clone #-}
+
+-- ** Growing
+
+-- | Grow a mutable vector by an amount given explicitly as a 'Proxy'
+-- argument.
+grow :: forall n k m a p. (KnownNat k, PrimMonad m)
+      => p k -> MVector n (PrimState m) a -> m (MVector (n + k) (PrimState m) a)
+grow = VGM.grow
+{-# inline grow #-}
+
+-- | Grow a mutable vector (from the front) by an amount given explicitly
+-- as a 'Proxy' argument.
+growFront :: forall n k m a p. (KnownNat k, PrimMonad m)
+      => p k -> MVector n (PrimState m) a -> m (MVector (n + k) (PrimState m) a)
+growFront = VGM.growFront
+{-# inline growFront #-}
+
+-- ** Restricting memory usage
+
+-- | Reset all elements of the vector to some undefined value, clearing all
+-- references to external objects.
+clear :: PrimMonad m => MVector n (PrimState m) a -> m ()
+clear = VGM.clear
+{-# inline clear #-}
+
+-- * Accessing individual elements
+
+-- | /O(1)/ Yield the element at a given type-safe position using 'Finite'.
+read :: forall n m a. (KnownNat n, PrimMonad m)
+      => MVector n (PrimState m) a -> Finite n -> m a
+read = VGM.read
+{-# inline read #-}
+
+-- | /O(1)/ Yield the element at a given type-safe position using 'Proxy'.
+read' :: forall n k a m p. (KnownNat n, KnownNat k, PrimMonad m)
+       => MVector (n+k+1) (PrimState m) a -> p k -> m a
+read' = VGM.read'
+{-# inline read' #-}
+
+-- | /O(1)/ Yield the element at a given 'Int' position without bounds
+-- checking.
+unsafeRead :: forall n a m. (KnownNat n, PrimMonad m)
+           => MVector n (PrimState m) a -> Int -> m a
+unsafeRead = VGM.unsafeRead
+{-# inline unsafeRead #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position using 'Finite'.
+write :: forall n m a. (KnownNat n, PrimMonad m)
+      => MVector n (PrimState m) a -> Finite n -> a -> m ()
+write = VGM.write
+{-# inline write #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position using 'Proxy'.
+write' :: forall n k a m p. (KnownNat n, KnownNat k, PrimMonad m)
+       => MVector (n+k+1) (PrimState m) a -> p k -> a -> m ()
+write' = VGM.write'
+{-# inline write' #-}
+
+-- | /O(1)/ Replace the element at a given 'Int' position without bounds
+-- checking.
+unsafeWrite :: forall n m a. (KnownNat n, PrimMonad m)
+      => MVector n (PrimState m) a -> Int -> a -> m ()
+unsafeWrite = VGM.unsafeWrite
+{-# inline unsafeWrite #-}
+
+-- | /O(1)/ Modify the element at a given type-safe position using 'Finite'.
+modify :: forall n m a. (KnownNat n, PrimMonad m)
+       => MVector n (PrimState m) a -> (a -> a) -> Finite n -> m ()
+modify = VGM.modify
+{-# inline modify #-}
+
+-- | /O(1)/ Modify the element at a given type-safe position using 'Proxy'.
+modify' :: forall n k a m p. (KnownNat n, KnownNat k, PrimMonad m)
+        => MVector (n+k+1) (PrimState m) a -> (a -> a) -> p k -> m ()
+modify' = VGM.modify'
+{-# inline modify' #-}
+
+-- | /O(1)/ Modify the element at a given 'Int' position without bounds
+-- checking.
+unsafeModify :: forall n m a. (KnownNat n, PrimMonad m)
+       => MVector n (PrimState m) a -> (a -> a) -> Int -> m ()
+unsafeModify = VGM.unsafeModify
+{-# inline unsafeModify #-}
+
+-- | /O(1)/ Swap the elements at a given type-safe position using 'Finite's.
+swap :: forall n m a. (KnownNat n, PrimMonad m)
+     => MVector n (PrimState m) a -> Finite n -> Finite n -> m ()
+swap = VGM.swap
+{-# inline swap #-}
+
+-- | /O(1)/ Swap the elements at a given 'Int' position without bounds
+-- checking.
+unsafeSwap :: forall n m a. (KnownNat n, PrimMonad m)
+           => MVector n (PrimState m) a -> Int -> Int -> m ()
+unsafeSwap = VGM.unsafeSwap
+{-# inline unsafeSwap #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position and return
+-- the old element, using 'Finite'.
+exchange :: forall n m a. (KnownNat n, PrimMonad m)
+         => MVector n (PrimState m) a -> Finite n -> a -> m a
+exchange = VGM.exchange
+{-# inline exchange #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position and return
+-- the old element, using 'Finite'.
+exchange' :: forall n k a m p. (KnownNat n, KnownNat k, PrimMonad m)
+          => MVector (n+k+1) (PrimState m) a -> p k -> a -> m a
+exchange' = VGM.exchange'
+{-# inline exchange' #-}
+
+-- | /O(1)/ Replace the element at a given 'Int' position and return
+-- the old element. No bounds checks are performed.
+unsafeExchange :: forall n m a. (KnownNat n, PrimMonad m)
+         => MVector n (PrimState m) a -> Int -> a -> m a
+unsafeExchange = VGM.unsafeExchange
+{-# inline unsafeExchange #-}
+
+#if MIN_VERSION_vector(0,12,0)
+-- * Modifying vectors
+
+-- | Compute the next (lexicographically) permutation of a given vector
+-- in-place.  Returns 'False' when the input is the last permutation.
+nextPermutation :: forall n e m. (KnownNat n, Ord e, PrimMonad m)
+                => MVector n (PrimState m) e -> m Bool
+nextPermutation = VGM.nextPermutation
+{-# inline nextPermutation #-}
+#endif
+
+-- ** Filling and copying
+
+-- | Set all elements of the vector to the given value.
+set :: PrimMonad m => MVector n (PrimState m) a -> a -> m ()
+set = VGM.set
+{-# inline set #-}
+
+-- | Copy a vector. The two vectors may not overlap.
+copy :: PrimMonad m
+     => MVector n (PrimState m) a       -- ^ target
+     -> MVector n (PrimState m) a       -- ^ source
+     -> m ()
+copy = VGM.copy
+{-# inline copy #-}
+
+-- | Copy a vector. The two vectors may not overlap. This is not checked.
+unsafeCopy :: PrimMonad m
+           => MVector n (PrimState m) a       -- ^ target
+           -> MVector n (PrimState m) a       -- ^ source
+           -> m ()
+unsafeCopy = VGM.unsafeCopy
+{-# inline unsafeCopy #-}
+
+-- | Move the contents of a vector.  If the two vectors do not overlap,
+-- this is equivalent to 'copy'.  Otherwise, the copying is performed as if
+-- the source vector were copied to a temporary vector and then the
+-- temporary vector was copied to the target vector.
+move :: PrimMonad m
+     => MVector n (PrimState m) a       -- ^ target
+     -> MVector n (PrimState m) a       -- ^ source
+     -> m ()
+move = VGM.move
+{-# inline move #-}
+
+-- * Conversions
+
+-- ** Unsized Mutable Vectors
+
+-- | Convert a 'Data.Vector.Generic.Mutable.MVector' into
+-- a 'Data.Vector.Generic.Mutable.Sized.MVector' if it has the correct
+-- size, otherwise return Nothing.
+--
+-- Note that this does no copying; the returned 'MVector' is a reference to
+-- the exact same vector in memory as the given one, and any modifications
+-- to it are also reflected in the given
+-- 'Data.Vector.Generic.Mutable.MVector'.
+toSized :: forall n a s. KnownNat n
+        => VM.MVector s a -> Maybe (MVector n s a)
+toSized = VGM.toSized
+{-# inline toSized #-}
+
+-- | Takes a 'Data.Vector.Mutable.MVector' and returns
+-- a continuation providing a 'Data.Vector.Mutable.Sized.MVector'
+-- with a size parameter @n@ that is determined at runtime based on the
+-- length of the input vector.
+--
+-- Essentially converts a 'Data.Vector.Mutable.MVector' into
+-- a 'Data.Vector.Sized.MVector' with the correct size parameter
+-- @n@.
+--
+-- Note that this does no copying; the returned 'MVector' is a reference to
+-- the exact same vector in memory as the given one, and any modifications
+-- to it are also reflected in the given
+-- 'Data.Vector.Mutable.MVector'.
+withSized :: forall s a r. ()
+          => VM.MVector s a -> (forall n. KnownNat n => MVector n s a -> r) -> r
+withSized = VGM.withSized
+{-# inline withSized #-}
+
+-- | Convert a 'Data.Vector.Generic.Mutable.Sized.MVector' into a
+-- 'Data.Vector.Generic.Mutable.MVector'.
+--
+-- Note that this does no copying; the returned
+-- 'Data.Vector.Generic.Mutable.MVector' is a reference to the exact same
+-- vector in memory as the given one, and any modifications to it are also
+-- reflected in the given 'MVector'.
+fromSized :: MVector n s a -> VM.MVector s a
+fromSized = VGM.fromSized
+{-# inline fromSized #-}
+
+
diff --git a/src/Data/Vector/Sized.hs b/src/Data/Vector/Sized.hs
--- a/src/Data/Vector/Sized.hs
+++ b/src/Data/Vector/Sized.hs
@@ -1,12 +1,12 @@
 {-# LANGUAGE DataKinds                  #-}
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE KindSignatures             #-}
 {-# LANGUAGE RankNTypes                 #-}
 {-# LANGUAGE ScopedTypeVariables        #-}
 {-# LANGUAGE TypeOperators              #-}
+{-# LANGUAGE CPP                        #-}
 
+
 {-|
 This module re-exports the functionality in 'Data.Vector.Generic.Sized'
  specialized to 'Data.Vector'.
@@ -20,10 +20,13 @@
 
 module Data.Vector.Sized
  ( Vector
+  , VM.MVector
    -- * Accessors
    -- ** Length information
   , length
   , length'
+  , knownLength
+  , knownLength'
     -- ** Indexing
   , index
   , index'
@@ -51,11 +54,13 @@
     -- ** Initialization
   , empty
   , singleton
+#if !MIN_VERSION_GLASGOW_HASKELL(8,3,0,0)
+  , fromTuple
+#endif
   , replicate
   , replicate'
   , generate
   , generate'
-  , generate_
   , iterateN
   , iterateN'
     -- ** Monadic initialization
@@ -63,7 +68,6 @@
   , replicateM'
   , generateM
   , generateM'
-  , generateM_
     -- ** Unfolding
   , unfoldrN
   , unfoldrN'
@@ -217,6 +221,12 @@
   , fromListN
   , fromListN'
   , withSizedList
+    -- ** Mutable vectors
+  , freeze
+  , thaw
+  , copy
+  , unsafeFreeze
+  , unsafeThaw
     -- ** Unsized Vectors
   , toSized
   , withSized
@@ -226,9 +236,14 @@
 
 import qualified Data.Vector.Generic.Sized as V
 import qualified Data.Vector as VU
+import qualified Data.Vector.Mutable.Sized as VM
 import GHC.TypeLits
 import Data.Finite
 import Data.Proxy
+#if !MIN_VERSION_GLASGOW_HASKELL(8,3,0,0)
+import Data.IndexedListLiterals hiding (toList)
+#endif
+import Control.Monad.Primitive
 import Prelude hiding ( length, null,
                         replicate, (++), concat,
                         head, last,
@@ -248,18 +263,38 @@
 -- 'Data.Vector'
 type Vector = V.Vector VU.Vector
 
--- | /O(1)/ Yield the length of the vector as an 'Int'.
+-- | /O(1)/ Yield the length of the vector as an 'Int'. This is more like
+-- 'natVal' than 'Data.Vector.length', extracting the value from the 'KnownNat'
+-- instance and not looking at the vector itself.
 length :: forall n a. KnownNat n
        => Vector n a -> Int
 length = V.length
 {-# inline length #-}
 
--- | /O(1)/ Yield the length of the vector as a 'Proxy'.
-length' :: forall n a. KnownNat n
-        => Vector n a -> Proxy n
+-- | /O(1)/ Yield the length of the vector as a 'Proxy'. This function
+-- doesn't /do/ anything; it merely allows the size parameter of the vector
+-- to be passed around as a 'Proxy'.
+length' :: forall n a.
+           Vector n a -> Proxy n
 length' = V.length'
 {-# inline length' #-}
 
+-- | /O(1)/ Reveal a 'KnownNat' instance for a vector's length, determined
+-- at runtime.
+knownLength :: forall n a r.
+               Vector n a -- ^ a vector of some (potentially unknown) length
+            -> (KnownNat n => r) -- ^ a value that depends on knowing the vector's length
+            -> r -- ^ the value computed with the length
+knownLength = V.knownLength
+
+-- | /O(1)/ Reveal a 'KnownNat' instance and 'Proxy' for a vector's length,
+-- determined at runtime.
+knownLength' :: forall n a r.
+                Vector n a -- ^ a vector of some (potentially unknown) length
+             -> (KnownNat n => Proxy n -> r) -- ^ a value that depends on knowing the vector's length, which is given as a 'Proxy'
+             -> r -- ^ the value computed with the length
+knownLength' = V.knownLength'
+
 -- | /O(1)/ Safe indexing using a 'Finite'.
 index :: forall n a. KnownNat n
       => Vector n a -> Finite n -> a
@@ -437,6 +472,16 @@
 singleton = V.singleton
 {-# inline singleton #-}
 
+#if !MIN_VERSION_GLASGOW_HASKELL(8,3,0,0)
+-- | /O(n)/ Construct a vector in a type safe manner
+--   fromTuple (1,2) :: Vector 2 Int
+--   fromTuple ("hey", "what's", "going", "on") :: Vector 4 String
+fromTuple :: forall input length ty.
+             (IndexedListLiterals input length ty, KnownNat length)
+          => input -> Vector length ty
+fromTuple = V.fromTuple
+#endif
+
 -- | /O(n)/ Construct a vector with the same element in each position where the
 -- length is inferred from the type.
 replicate :: forall n a. KnownNat n
@@ -454,27 +499,17 @@
 -- | /O(n)/ construct a vector of the given length by applying the function to
 -- each index where the length is inferred from the type.
 generate :: forall n a. KnownNat n
-         => (Int -> a) -> Vector n a
+         => (Finite n -> a) -> Vector n a
 generate = V.generate
 {-# inline generate #-}
 
 -- | /O(n)/ construct a vector of the given length by applying the function to
 -- each index where the length is given explicitly as a 'Proxy' argument.
 generate' :: forall n a p. KnownNat n
-          => p n -> (Int -> a) -> Vector n a
+          => p n -> (Finite n -> a) -> Vector n a
 generate' = V.generate'
 {-# inline generate' #-}
 
--- | /O(n)/ construct a vector of the given length by applying the function to
--- each index where the length is inferred from the type.
---
--- The function can expect a @'Finite' n@, meaning that its input will
--- always be between @0@ and @n - 1@.
-generate_ :: forall n a. KnownNat n
-          => (Finite n -> a) -> Vector n a
-generate_ = V.generate_
-{-# inline generate_ #-}
-
 -- | /O(n)/ Apply function n times to value. Zeroth element is original value.
 -- The length is inferred from the type.
 iterateN :: forall n a. KnownNat n
@@ -510,24 +545,14 @@
 -- | /O(n)/ Construct a vector of length @n@ by applying the monadic action to
 -- each index where n is inferred from the type.
 generateM :: forall n m a. (KnownNat n, Monad m)
-          => (Int -> m a) -> m (Vector n a)
+          => (Finite n -> m a) -> m (Vector n a)
 generateM = V.generateM
 {-# inline generateM #-}
 
 -- | /O(n)/ Construct a vector of length @n@ by applying the monadic action to
--- each index where n is inferred from the type.
---
--- The function can expect a @'Finite' n@, meaning that its input will
--- always be between @0@ and @n - 1@.
-generateM_ :: forall n m a. (KnownNat n, Monad m)
-           => (Finite n -> m a) -> m (Vector n a)
-generateM_ = V.generateM_
-{-# inline generateM_ #-}
-
--- | /O(n)/ Construct a vector of length @n@ by applying the monadic action to
 -- each index where n is given explicitly as a 'Proxy' argument.
 generateM' :: forall n m a p. (KnownNat n, Monad m)
-           => p n -> (Int -> m a) -> m (Vector n a)
+           => p n -> (Finite n -> m a) -> m (Vector n a)
 generateM' = V.generateM'
 {-# inline generateM' #-}
 
@@ -634,8 +659,8 @@
 --
 -- > <5,9,2,7> // [(2,1),(0,3),(2,8)] = <3,9,8,7>
 --
-(//) :: Vector m a -- ^ initial vector (of length @m@)
-     -> [(Int, a)]   -- ^ list of index/value pairs (of length @n@)
+(//) :: Vector m a      -- ^ initial vector (of length @m@)
+     -> [(Finite m, a)] -- ^ list of index/value pairs (of length @n@)
      -> Vector m a
 (//) = (V.//)
 {-# inline (//) #-}
@@ -800,7 +825,7 @@
 --
 
 -- | /O(n)/ Pair each element in a vector with its index
-indexed :: Vector n a -> Vector n (Int,a)
+indexed :: Vector n a -> Vector n (Finite n,a)
 indexed = V.indexed
 {-# inline indexed #-}
 
@@ -814,7 +839,7 @@
 {-# inline map #-}
 
 -- | /O(n)/ Apply a function to every element of a vector and its index
-imap :: (Int -> a -> b) -> Vector n a -> Vector n b
+imap :: (Finite n -> a -> b) -> Vector n a -> Vector n b
 imap = V.imap
 {-# inline imap #-}
 
@@ -836,7 +861,7 @@
 
 -- | /O(n)/ Apply the monadic action to every element of a vector and its
 -- index, yielding a vector of results
-imapM :: Monad m => (Int -> a -> m b) -> Vector n a -> m (Vector n b)
+imapM :: Monad m => (Finite n -> a -> m b) -> Vector n a -> m (Vector n b)
 imapM = V.imapM
 {-# inline imapM #-}
 
@@ -848,7 +873,7 @@
 
 -- | /O(n)/ Apply the monadic action to every element of a vector and its
 -- index, ignoring the results
-imapM_ :: Monad m => (Int -> a -> m b) -> Vector n a -> m ()
+imapM_ :: Monad m => (Finite n -> a -> m b) -> Vector n a -> m ()
 imapM_ = V.imapM_
 {-# inline imapM_ #-}
 
@@ -910,14 +935,14 @@
 
 -- | /O(n)/ Zip two vectors of the same length with a function that also takes
 -- the elements' indices).
-izipWith :: (Int -> a -> b -> c)
+izipWith :: (Finite n -> a -> b -> c)
          -> Vector n a
          -> Vector n b
          -> Vector n c
 izipWith = V.izipWith
 {-# inline izipWith #-}
 
-izipWith3 :: (Int -> a -> b -> c -> d)
+izipWith3 :: (Finite n -> a -> b -> c -> d)
           -> Vector n a
           -> Vector n b
           -> Vector n c
@@ -925,7 +950,7 @@
 izipWith3 = V.izipWith3
 {-# inline izipWith3 #-}
 
-izipWith4 :: (Int -> a -> b -> c -> d -> e)
+izipWith4 :: (Finite n -> a -> b -> c -> d -> e)
           -> Vector n a
           -> Vector n b
           -> Vector n c
@@ -934,7 +959,7 @@
 izipWith4 = V.izipWith4
 {-# inline izipWith4 #-}
 
-izipWith5 :: (Int -> a -> b -> c -> d -> e -> f)
+izipWith5 :: (Finite n -> a -> b -> c -> d -> e -> f)
           -> Vector n a
           -> Vector n b
           -> Vector n c
@@ -944,7 +969,7 @@
 izipWith5 = V.izipWith5
 {-# inline izipWith5 #-}
 
-izipWith6 :: (Int -> a -> b -> c -> d -> e -> f -> g)
+izipWith6 :: (Finite n -> a -> b -> c -> d -> e -> f -> g)
           -> Vector n a
           -> Vector n b
           -> Vector n c
@@ -1005,7 +1030,7 @@
 -- | /O(n)/ Zip the two vectors with a monadic action that also takes the
 -- element index and yield a vector of results
 izipWithM :: Monad m
-         => (Int -> a -> b -> m c) -> Vector n a -> Vector n b -> m (Vector n c)
+         => (Finite n -> a -> b -> m c) -> Vector n a -> Vector n b -> m (Vector n c)
 izipWithM = V.izipWithM
 {-# inline izipWithM #-}
 
@@ -1018,7 +1043,7 @@
 -- | /O(n)/ Zip the two vectors with a monadic action that also takes
 -- the element index and ignore the results
 izipWithM_ :: Monad m
-           => (Int -> a -> b -> m c) -> Vector n a -> Vector n b -> m ()
+           => (Finite n -> a -> b -> m c) -> Vector n a -> Vector n b -> m ()
 izipWithM_ = V.izipWithM_
 {-# inline izipWithM_ #-}
 
@@ -1075,14 +1100,14 @@
 
 -- | /O(n)/ Yield 'Just' the index of the first element matching the predicate
 -- or 'Nothing' if no such element exists.
-findIndex :: (a -> Bool) -> Vector n a -> Maybe Int
+findIndex :: (a -> Bool) -> Vector n a -> Maybe (Finite n)
 findIndex = V.findIndex
 {-# inline findIndex #-}
 
 -- | /O(n)/ Yield 'Just' the index of the first occurence of the given element or
 -- 'Nothing' if the vector does not contain the element. This is a specialised
 -- version of 'findIndex'.
-elemIndex :: (Eq a) => a -> Vector n a -> Maybe Int
+elemIndex :: (Eq a) => a -> Vector n a -> Maybe (Finite n)
 elemIndex = V.elemIndex
 {-# inline elemIndex #-}
 
@@ -1131,24 +1156,24 @@
 {-# inline foldr1' #-}
 
 -- | /O(n)/ Left fold (function applied to each element and its index)
-ifoldl :: (a -> Int -> b -> a) -> a -> Vector n b -> a
+ifoldl :: (a -> Finite n -> b -> a) -> a -> Vector n b -> a
 ifoldl = V.ifoldl
 {-# inline ifoldl #-}
 
 -- | /O(n)/ Left fold with strict accumulator (function applied to each element
 -- and its index)
-ifoldl' :: (a -> Int -> b -> a) -> a -> Vector n b -> a
+ifoldl' :: (a -> Finite n -> b -> a) -> a -> Vector n b -> a
 ifoldl' = V.ifoldl'
 {-# inline ifoldl' #-}
 
 -- | /O(n)/ Right fold (function applied to each element and its index)
-ifoldr :: (Int -> a -> b -> b) -> b -> Vector n a -> b
+ifoldr :: (Finite n -> a -> b -> b) -> b -> Vector n a -> b
 ifoldr = V.ifoldr
 {-# inline ifoldr #-}
 
 -- | /O(n)/ Right fold with strict accumulator (function applied to each
 -- element and its index)
-ifoldr' :: (Int -> a -> b -> b) -> b -> Vector n a -> b
+ifoldr' :: (Finite n -> a -> b -> b) -> b -> Vector n a -> b
 ifoldr' = V.ifoldr'
 {-# inline ifoldr' #-}
 
@@ -1209,26 +1234,26 @@
 {-# inline minimumBy #-}
 
 -- | /O(n)/ Yield the index of the maximum element of the non-empty vector.
-maxIndex :: (Ord a, KnownNat n) => Vector (n+1) a -> Int
+maxIndex :: (Ord a, KnownNat n) => Vector (n+1) a -> Finite (n + 1)
 maxIndex = V.maxIndex
 {-# inline maxIndex #-}
 
 -- | /O(n)/ Yield the index of the maximum element of the non-empty vector
 -- according to the given comparison function.
 maxIndexBy :: KnownNat n
-           => (a -> a -> Ordering) -> Vector (n+1) a -> Int
+           => (a -> a -> Ordering) -> Vector (n+1) a -> Finite (n + 1)
 maxIndexBy = V.maxIndexBy
 {-# inline maxIndexBy #-}
 
 -- | /O(n)/ Yield the index of the minimum element of the non-empty vector.
-minIndex :: (Ord a, KnownNat n) => Vector (n+1) a -> Int
+minIndex :: (Ord a, KnownNat n) => Vector (n+1) a -> Finite (n + 1)
 minIndex = V.minIndex
 {-# inline minIndex #-}
 
 -- | /O(n)/ Yield the index of the minimum element of the non-empty vector
 -- according to the given comparison function.
 minIndexBy :: KnownNat n
-           => (a -> a -> Ordering) -> Vector (n+1) a -> Int
+           => (a -> a -> Ordering) -> Vector (n+1) a -> Finite (n + 1)
 minIndexBy = V.minIndexBy
 {-# inline minIndexBy #-}
 
@@ -1240,7 +1265,7 @@
 {-# inline foldM #-}
 
 -- | /O(n)/ Monadic fold (action applied to each element and its index)
-ifoldM :: Monad m => (a -> Int -> b -> m a) -> a -> Vector n b -> m a
+ifoldM :: Monad m => (a -> Finite n -> b -> m a) -> a -> Vector n b -> m a
 ifoldM = V.ifoldM
 {-# inline ifoldM #-}
 
@@ -1258,7 +1283,7 @@
 -- | /O(n)/ Monadic fold with strict accumulator (action applied to each
 -- element and its index)
 ifoldM' :: Monad m
-        => (a -> Int -> b -> m a) -> a -> Vector n b -> m a
+        => (a -> Finite n -> b -> m a) -> a -> Vector n b -> m a
 ifoldM' = V.ifoldM'
 {-# inline ifoldM' #-}
 
@@ -1277,7 +1302,7 @@
 -- | /O(n)/ Monadic fold that discards the result (action applied to
 -- each element and its index)
 ifoldM_ :: Monad m
-        => (a -> Int -> b -> m a) -> a -> Vector n b -> m ()
+        => (a -> Finite n -> b -> m a) -> a -> Vector n b -> m ()
 ifoldM_ = V.ifoldM_
 {-# inline ifoldM_ #-}
 
@@ -1296,7 +1321,7 @@
 -- | /O(n)/ Monadic fold with strict accumulator that discards the result
 -- (action applied to each element and its index)
 ifoldM'_ :: Monad m
-         => (a -> Int -> b -> m a) -> a -> Vector n b -> m ()
+         => (a -> Finite n -> b -> m a) -> a -> Vector n b -> m ()
 ifoldM'_ = V.ifoldM'_
 {-# inline ifoldM'_ #-}
 
@@ -1451,6 +1476,41 @@
 withSizedList xs = withSized (VU.fromList xs)
 {-# inline withSizedList #-}
 
+-- ** Mutable vectors
+
+-- | /O(n)/ Yield an immutable copy of the mutable vector.
+freeze :: PrimMonad m
+       => VM.MVector n (PrimState m) a
+       -> m (Vector n a)
+freeze = V.freeze
+
+-- | /O(1)/ Unsafely convert a mutable vector to an immutable one withouy
+-- copying. The mutable vector may not be used after this operation.
+unsafeFreeze :: PrimMonad m
+             => VM.MVector n (PrimState m) a
+             -> m (Vector n a)
+unsafeFreeze = V.unsafeFreeze
+
+-- | /O(n)/ Yield a mutable copy of the immutable vector.
+thaw :: PrimMonad m
+     => Vector n a
+     -> m (VM.MVector n (PrimState m) a)
+thaw = V.thaw
+
+-- | /O(n)/ Unsafely convert an immutable vector to a mutable one without
+-- copying. The immutable vector may not be used after this operation.
+unsafeThaw :: PrimMonad m
+           => Vector n a
+           -> m (VM.MVector n (PrimState m) a)
+unsafeThaw = V.unsafeThaw
+
+-- | /O(n)/ Copy an immutable vector into a mutable one.
+copy :: PrimMonad m
+     => VM.MVector n (PrimState m) a
+     -> Vector n a
+     -> m ()
+copy = V.copy
+
 -- ** Unsized vectors
 
 -- | Convert a 'Data.Vector.Generic.Vector' into a
@@ -1481,4 +1541,3 @@
 withVectorUnsafe :: (VU.Vector a -> VU.Vector b) -> Vector n a -> Vector n b
 withVectorUnsafe = V.withVectorUnsafe
 {-# inline withVectorUnsafe #-}
-
diff --git a/src/Data/Vector/Storable/Mutable/Sized.hs b/src/Data/Vector/Storable/Mutable/Sized.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Vector/Storable/Mutable/Sized.hs
@@ -0,0 +1,475 @@
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RankNTypes       #-}
+{-# LANGUAGE TypeOperators    #-}
+
+{-|
+This module re-exports the functionality in 'Data.Vector.Generic.Mutable.Sized'
+ specialized to 'Data.Vector.Storable.Mutable'
+
+Functions returning a vector determine the size from the type context unless
+they have a @'@ suffix in which case they take an explicit 'Proxy' argument.
+
+Functions where the resultant vector size is not know until compile time are
+not exported.
+-}
+
+module Data.Vector.Storable.Mutable.Sized
+ ( MVector
+   -- * Accessors
+   -- ** Length information
+  , length
+  , length'
+  , null
+   -- ** Extracting subvectors
+  , slice
+  , slice'
+  , init
+  , tail
+  , take
+  , take'
+  , drop
+  , drop'
+  , splitAt
+  , splitAt'
+  -- ** Overlaps
+  , overlaps
+  -- * Construction
+  -- ** Initialisation
+  , new
+  , unsafeNew
+  , replicate
+  , replicate'
+  , replicateM
+  , replicateM'
+  , clone
+  -- ** Growing
+  , grow
+  , growFront
+  -- ** Restricting memory usage
+  , clear
+  -- * Accessing individual elements
+  , read
+  , read'
+  , write
+  , write'
+  , modify
+  , modify'
+  , swap
+  , exchange
+  , exchange'
+  , unsafeRead
+  , unsafeWrite
+  , unsafeModify
+  , unsafeSwap
+  , unsafeExchange
+#if MIN_VERSION_vector(0,12,0)
+  -- * Modifying vectors
+  , nextPermutation
+#endif
+  -- ** Filling and copying
+  , set
+  , copy
+  , move
+  , unsafeCopy
+    -- * Conversions
+    -- ** Unsized Mutable Vectors
+  , toSized
+  , withSized
+  , fromSized
+  ) where
+
+import qualified Data.Vector.Generic.Mutable.Sized as VGM
+import qualified Data.Vector.Storable.Mutable as VSM
+import Foreign.Storable
+import GHC.TypeLits
+import Data.Finite
+import Data.Proxy
+import Control.Monad.Primitive
+import Prelude hiding ( length, null, replicate, init,
+                        tail, take, drop, splitAt, read )
+
+
+-- | 'Data.Vector.Generic.Mutable.Sized.Vector' specialized to use
+-- 'Data.Vector.Storable.Mutable'
+type MVector = VGM.MVector VSM.MVector
+
+-- * Accessors
+
+-- ** Length information
+
+-- | /O(1)/ Yield the length of the mutable vector as an 'Int'.
+length :: forall n s a. (KnownNat n)
+       => MVector n s a -> Int
+length = VGM.length
+{-# inline length #-}
+
+-- | /O(1)/ Yield the length of the mutable vector as a 'Proxy'.
+length' :: forall n s a. (KnownNat n)
+        => MVector n s a -> Proxy n
+length' = VGM.length'
+{-# inline length' #-}
+
+-- | /O(1)/ Check whether the mutable vector is empty
+null :: forall n s a. (KnownNat n)
+       => MVector n s a -> Bool
+null = VGM.null
+{-# inline null #-}
+
+-- ** Extracting subvectors
+
+-- | /O(1)/ Yield a slice of the mutable vector without copying it with an
+-- inferred length argument.
+slice :: forall i n k s a p. (KnownNat i, KnownNat n, KnownNat k, Storable a)
+      => p i -- ^ starting index
+      -> MVector (i+n+k) s a
+      -> MVector n s a
+slice = VGM.slice
+{-# inline slice #-}
+
+-- | /O(1)/ Yield a slice of the mutable vector without copying it with an
+-- explicit length argument.
+slice' :: forall i n k s a p
+        . (KnownNat i, KnownNat n, KnownNat k, Storable a)
+       => p i -- ^ starting index
+       -> p n -- ^ length
+       -> MVector (i+n+k) s a
+       -> MVector n s a
+slice' = VGM.slice'
+{-# inline slice' #-}
+
+-- | /O(1)/ Yield all but the last element of a non-empty mutable vector
+-- without copying.
+init :: forall n s a. Storable a
+     => MVector (n+1) s a -> MVector n s a
+init = VGM.init
+{-# inline init #-}
+
+-- | /O(1)/ Yield all but the first element of a non-empty mutable vector
+-- without copying.
+tail :: forall n s a. Storable a
+     => MVector (1+n) s a -> MVector n s a
+tail = VGM.tail
+{-# inline tail #-}
+
+-- | /O(1)/ Yield the first n elements. The resultant vector always contains
+-- this many elements. The length of the resultant vector is inferred from the
+-- type.
+take :: forall n k s a. (KnownNat n, KnownNat k, Storable a)
+     => MVector (n+k) s a -> MVector n s a
+take = VGM.take
+{-# inline take #-}
+
+-- | /O(1)/ Yield the first n elements. The resultant vector always contains
+-- this many elements. The length of the resultant vector is given explicitly
+-- as a 'Proxy' argument.
+take' :: forall n k s a p. (KnownNat n, KnownNat k, Storable a)
+      => p n -> MVector (n+k) s a -> MVector n s a
+take' = VGM.take'
+{-# inline take' #-}
+
+-- | /O(1)/ Yield all but the the first n elements. The given vector must
+-- contain at least this many elements The length of the resultant vector is
+-- inferred from the type.
+drop :: forall n k s a. (KnownNat n, KnownNat k, Storable a)
+     => MVector (n+k) s a -> MVector k s a
+drop = VGM.drop
+{-# inline drop #-}
+
+-- | /O(1)/ Yield all but the the first n elements. The given vector must
+-- contain at least this many elements The length of the resultant vector is
+-- givel explicitly as a 'Proxy' argument.
+drop' :: forall n k s a p. (KnownNat n, KnownNat k, Storable a)
+      => p n -> MVector (n+k) s a -> MVector k s a
+drop' = VGM.drop'
+{-# inline drop' #-}
+
+-- | /O(1)/ Yield the first n elements paired with the remainder without copying.
+-- The lengths of the resultant vector are inferred from the type.
+splitAt :: forall n m s a. (KnownNat n, KnownNat m, Storable a)
+        => MVector (n+m) s a -> (MVector n s a, MVector m s a)
+splitAt = VGM.splitAt
+{-# inline splitAt #-}
+
+-- | /O(1)/ Yield the first n elements paired with the remainder without
+-- copying.  The length of the first resultant vector is passed explicitly as a
+-- 'Proxy' argument.
+splitAt' :: forall n m s a p. (KnownNat n, KnownNat m, Storable a)
+         => p n -> MVector (n+m) s a -> (MVector n s a, MVector m s a)
+splitAt' = VGM.splitAt'
+{-# inline splitAt' #-}
+
+-- ** Overlaps
+
+-- | /O(1)/ Yield all but the the first n elements. The given vector must
+-- contain at least this many elements The length of the resultant vector is
+-- inferred from the type.
+overlaps :: forall n k s a. (KnownNat n, KnownNat k, Storable a)
+         => MVector n s a
+         -> MVector k s a
+         -> Bool
+overlaps = VGM.overlaps
+{-# inline overlaps #-}
+
+-- * Construction
+
+-- ** Initialisation
+
+-- | Create a mutable vector where the length is inferred from the type.
+new :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+    => m (MVector n (PrimState m) a)
+new = VGM.new
+{-# inline new #-}
+
+-- | Create a mutable vector where the length is inferred from the type.
+-- The memory is not initialized.
+unsafeNew :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+          => m (MVector n (PrimState m) a)
+unsafeNew = VGM.unsafeNew
+{-# inline unsafeNew #-}
+
+-- | Create a mutable vector where the length is inferred from the type and
+-- fill it with an initial value.
+replicate :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+          => a -> m (MVector n (PrimState m) a)
+replicate = VGM.replicate
+{-# inline replicate #-}
+
+-- | Create a mutable vector where the length is given explicitly as
+-- a 'Proxy' argument and fill it with an initial value.
+replicate' :: forall n m a p. (KnownNat n, PrimMonad m, Storable a)
+           => p n -> a -> m (MVector n (PrimState m) a)
+replicate' = VGM.replicate'
+{-# inline replicate' #-}
+
+-- | Create a mutable vector where the length is inferred from the type and
+-- fill it with values produced by repeatedly executing the monadic action.
+replicateM :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+           => m a -> m (MVector n (PrimState m) a)
+replicateM = VGM.replicateM
+{-# inline replicateM #-}
+
+-- | Create a mutable vector where the length is given explicitly as
+-- a 'Proxy' argument and fill it with values produced by repeatedly
+-- executing the monadic action.
+replicateM' :: forall n m a p. (KnownNat n, PrimMonad m, Storable a)
+           => p n -> m a -> m (MVector n (PrimState m) a)
+replicateM' = VGM.replicateM'
+{-# inline replicateM' #-}
+
+-- | Create a copy of a mutable vector.
+clone :: forall n m a. (PrimMonad m, Storable a)
+      => MVector n (PrimState m) a -> m (MVector n (PrimState m) a)
+clone = VGM.clone
+{-# inline clone #-}
+
+-- ** Growing
+
+-- | Grow a mutable vector by an amount given explicitly as a 'Proxy'
+-- argument.
+grow :: forall n k m a p. (KnownNat k, PrimMonad m, Storable a)
+      => p k -> MVector n (PrimState m) a -> m (MVector (n + k) (PrimState m) a)
+grow = VGM.grow
+{-# inline grow #-}
+
+-- | Grow a mutable vector (from the front) by an amount given explicitly
+-- as a 'Proxy' argument.
+growFront :: forall n k m a p. (KnownNat k, PrimMonad m, Storable a)
+      => p k -> MVector n (PrimState m) a -> m (MVector (n + k) (PrimState m) a)
+growFront = VGM.growFront
+{-# inline growFront #-}
+
+-- ** Restricting memory usage
+
+-- | Reset all elements of the vector to some undefined value, clearing all
+-- references to external objects.
+clear :: (PrimMonad m, Storable a) => MVector n (PrimState m) a -> m ()
+clear = VGM.clear
+{-# inline clear #-}
+
+-- * Accessing individual elements
+
+-- | /O(1)/ Yield the element at a given type-safe position using 'Finite'.
+read :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+      => MVector n (PrimState m) a -> Finite n -> m a
+read = VGM.read
+{-# inline read #-}
+
+-- | /O(1)/ Yield the element at a given type-safe position using 'Proxy'.
+read' :: forall n k a m p. (KnownNat n, KnownNat k, PrimMonad m, Storable a)
+       => MVector (n+k+1) (PrimState m) a -> p k -> m a
+read' = VGM.read'
+{-# inline read' #-}
+
+-- | /O(1)/ Yield the element at a given 'Int' position without bounds
+-- checking.
+unsafeRead :: forall n a m. (KnownNat n, PrimMonad m, Storable a)
+           => MVector n (PrimState m) a -> Int -> m a
+unsafeRead = VGM.unsafeRead
+{-# inline unsafeRead #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position using 'Finite'.
+write :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+      => MVector n (PrimState m) a -> Finite n -> a -> m ()
+write = VGM.write
+{-# inline write #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position using 'Proxy'.
+write' :: forall n k a m p. (KnownNat n, KnownNat k, PrimMonad m, Storable a)
+       => MVector (n+k+1) (PrimState m) a -> p k -> a -> m ()
+write' = VGM.write'
+{-# inline write' #-}
+
+-- | /O(1)/ Replace the element at a given 'Int' position without bounds
+-- checking.
+unsafeWrite :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+      => MVector n (PrimState m) a -> Int -> a -> m ()
+unsafeWrite = VGM.unsafeWrite
+{-# inline unsafeWrite #-}
+
+-- | /O(1)/ Modify the element at a given type-safe position using 'Finite'.
+modify :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+       => MVector n (PrimState m) a -> (a -> a) -> Finite n -> m ()
+modify = VGM.modify
+{-# inline modify #-}
+
+-- | /O(1)/ Modify the element at a given type-safe position using 'Proxy'.
+modify' :: forall n k a m p. (KnownNat n, KnownNat k, PrimMonad m, Storable a)
+        => MVector (n+k+1) (PrimState m) a -> (a -> a) -> p k -> m ()
+modify' = VGM.modify'
+{-# inline modify' #-}
+
+-- | /O(1)/ Modify the element at a given 'Int' position without bounds
+-- checking.
+unsafeModify :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+       => MVector n (PrimState m) a -> (a -> a) -> Int -> m ()
+unsafeModify = VGM.unsafeModify
+{-# inline unsafeModify #-}
+
+-- | /O(1)/ Swap the elements at a given type-safe position using 'Finite's.
+swap :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+     => MVector n (PrimState m) a -> Finite n -> Finite n -> m ()
+swap = VGM.swap
+{-# inline swap #-}
+
+-- | /O(1)/ Swap the elements at a given 'Int' position without bounds
+-- checking.
+unsafeSwap :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+           => MVector n (PrimState m) a -> Int -> Int -> m ()
+unsafeSwap = VGM.unsafeSwap
+{-# inline unsafeSwap #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position and return
+-- the old element, using 'Finite'.
+exchange :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+         => MVector n (PrimState m) a -> Finite n -> a -> m a
+exchange = VGM.exchange
+{-# inline exchange #-}
+
+-- | /O(1)/ Replace the element at a given type-safe position and return
+-- the old element, using 'Finite'.
+exchange' :: forall n k a m p. (KnownNat n, KnownNat k, PrimMonad m, Storable a)
+          => MVector (n+k+1) (PrimState m) a -> p k -> a -> m a
+exchange' = VGM.exchange'
+{-# inline exchange' #-}
+
+-- | /O(1)/ Replace the element at a given 'Int' position and return
+-- the old element. No bounds checks are performed.
+unsafeExchange :: forall n m a. (KnownNat n, PrimMonad m, Storable a)
+         => MVector n (PrimState m) a -> Int -> a -> m a
+unsafeExchange = VGM.unsafeExchange
+{-# inline unsafeExchange #-}
+
+#if MIN_VERSION_vector(0,12,0)
+-- * Modifying vectors
+
+-- | Compute the next (lexicographically) permutation of a given vector
+-- in-place.  Returns 'False' when the input is the last permutation.
+nextPermutation :: forall n e m. (KnownNat n, Ord e, PrimMonad m, Storable e)
+                => MVector n (PrimState m) e -> m Bool
+nextPermutation = VGM.nextPermutation
+{-# inline nextPermutation #-}
+#endif
+
+-- ** Filling and copying
+
+-- | Set all elements of the vector to the given value.
+set :: (PrimMonad m, Storable a) => MVector n (PrimState m) a -> a -> m ()
+set = VGM.set
+{-# inline set #-}
+
+-- | Copy a vector. The two vectors may not overlap.
+copy :: (PrimMonad m, Storable a)
+     => MVector n (PrimState m) a       -- ^ target
+     -> MVector n (PrimState m) a       -- ^ source
+     -> m ()
+copy = VGM.copy
+{-# inline copy #-}
+
+-- * Conversions
+
+-- ** Unsized Mutable Vectors
+
+-- | Copy a vector. The two vectors may not overlap. This is not checked.
+unsafeCopy :: (PrimMonad m, Storable a)
+           => MVector n (PrimState m) a       -- ^ target
+           -> MVector n (PrimState m) a       -- ^ source
+           -> m ()
+unsafeCopy = VGM.unsafeCopy
+{-# inline unsafeCopy #-}
+
+-- | Move the contents of a vector.  If the two vectors do not overlap,
+-- this is equivalent to 'copy'.  Otherwise, the copying is performed as if
+-- the source vector were copied to a temporary vector and then the
+-- temporary vector was copied to the target vector.
+move :: (PrimMonad m, Storable a)
+     => MVector n (PrimState m) a       -- ^ target
+     -> MVector n (PrimState m) a       -- ^ source
+     -> m ()
+move = VGM.move
+{-# inline move #-}
+
+-- | Convert a 'Data.Vector.Storable.Mutable.MVector' into
+-- a 'Data.Vector.Storable.Mutable.Sized.MVector' if it has the correct
+-- size, otherwise return Nothing.
+--
+-- Note that this does no copying; the returned 'MVector' is a reference to
+-- the exact same vector in memory as the given one, and any modifications
+-- to it are also reflected in the given
+-- 'Data.Vector.Storable.Mutable.MVector'.
+toSized :: forall n a s. (KnownNat n, Storable a)
+        => VSM.MVector s a -> Maybe (MVector n s a)
+toSized = VGM.toSized
+{-# inline toSized #-}
+
+-- | Takes a 'Data.Vector.Storable.Mutable.MVector' and returns
+-- a continuation providing a 'Data.Vector.Storable.Mutable.Sized.MVector'
+-- with a size parameter @n@ that is determined at runtime based on the
+-- length of the input vector.
+--
+-- Essentially converts a 'Data.Vector.Storable.Mutable.MVector' into
+-- a 'Data.Vector.Storable.Sized.MVector' with the correct size parameter
+-- @n@.
+--
+-- Note that this does no copying; the returned 'MVector' is a reference to
+-- the exact same vector in memory as the given one, and any modifications
+-- to it are also reflected in the given
+-- 'Data.Vector.Storable.Mutable.MVector'.
+withSized :: forall s a r. Storable a
+          => VSM.MVector s a -> (forall n. KnownNat n => MVector n s a -> r) -> r
+withSized = VGM.withSized
+{-# inline withSized #-}
+
+-- | Convert a 'Data.Vector.Storable.Mutable.Sized.MVector' into a
+-- 'Data.Vector.Storable.Mutable.MVector'.
+--
+-- Note that this does no copying; the returned
+-- 'Data.Vector.Storable.Mutable.MVector' is a reference to the exact same
+-- vector in memory as the given one, and any modifications to it are also
+-- reflected in the given 'MVector'.
+fromSized :: MVector n s a -> VSM.MVector s a
+fromSized = VGM.fromSized
+{-# inline fromSized #-}
+
+
diff --git a/src/Data/Vector/Storable/Sized.hs b/src/Data/Vector/Storable/Sized.hs
--- a/src/Data/Vector/Storable/Sized.hs
+++ b/src/Data/Vector/Storable/Sized.hs
@@ -1,10 +1,11 @@
+{-# LANGUAGE KindSignatures      #-}
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE FlexibleInstances   #-}
-{-# LANGUAGE KindSignatures      #-}
 {-# LANGUAGE RankNTypes          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeOperators       #-}
+{-# LANGUAGE CPP                 #-}
 
 {-|
 This module re-exports the functionality in 'Data.Vector.Generic.Sized'
@@ -19,10 +20,13 @@
 
 module Data.Vector.Storable.Sized
  ( Vector
+  , VSM.MVector
    -- * Accessors
    -- ** Length information
   , length
   , length'
+  , knownLength
+  , knownLength'
     -- ** Indexing
   , index
   , index'
@@ -50,11 +54,13 @@
     -- ** Initialization
   , empty
   , singleton
+#if !MIN_VERSION_GLASGOW_HASKELL(8,3,0,0)
+  , fromTuple
+#endif
   , replicate
   , replicate'
   , generate
   , generate'
-  , generate_
   , iterateN
   , iterateN'
     -- ** Monadic initialization
@@ -62,7 +68,6 @@
   , replicateM'
   , generateM
   , generateM'
-  , generateM_
     -- ** Unfolding
   , unfoldrN
   , unfoldrN'
@@ -216,6 +221,12 @@
   , fromListN
   , fromListN'
   , withSizedList
+    -- ** Mutable vectors
+  , freeze
+  , thaw
+  , copy
+  , unsafeFreeze
+  , unsafeThaw
     -- ** Unsized Vectors
   , toSized
   , withSized
@@ -225,9 +236,14 @@
 
 import qualified Data.Vector.Generic.Sized as V
 import qualified Data.Vector.Storable as VS
+#if !MIN_VERSION_GLASGOW_HASKELL(8,3,0,0)
+import Data.IndexedListLiterals (IndexedListLiterals)
+#endif
+import qualified Data.Vector.Storable.Mutable.Sized as VSM
 import GHC.TypeLits
 import Data.Finite
 import Data.Proxy
+import Control.Monad.Primitive
 import Foreign.Storable
 import Prelude hiding ( length, null,
                         replicate, (++), concat,
@@ -248,18 +264,38 @@
 -- 'Data.Vector.Storable'
 type Vector = V.Vector VS.Vector
 
--- | /O(1)/ Yield the length of the vector as an 'Int'.
-length :: forall n a. (KnownNat n)
+-- | /O(1)/ Yield the length of the vector as an 'Int'. This is more like
+-- 'natVal' than 'Data.Vector.length', extracting the value from the 'KnownNat'
+-- instance and not looking at the vector itself.
+length :: forall n a. KnownNat n
        => Vector n a -> Int
 length = V.length
 {-# inline length #-}
 
--- | /O(1)/ Yield the length of the vector as a 'Proxy'.
-length' :: forall n a. (KnownNat n)
-        => Vector n a -> Proxy n
+-- | /O(1)/ Yield the length of the vector as a 'Proxy'. This function
+-- doesn't /do/ anything; it merely allows the size parameter of the vector
+-- to be passed around as a 'Proxy'.
+length' :: forall n a.
+           Vector n a -> Proxy n
 length' = V.length'
 {-# inline length' #-}
 
+-- | /O(1)/ Reveal a 'KnownNat' instance for a vector's length, determined
+-- at runtime.
+knownLength :: forall n a r. Storable a
+            => Vector n a -- ^ a vector of some (potentially unknown) length
+            -> (KnownNat n => r) -- ^ a value that depends on knowing the vector's length
+            -> r -- ^ the value computed with the length
+knownLength = V.knownLength
+
+-- | /O(1)/ Reveal a 'KnownNat' instance and 'Proxy' for a vector's length,
+-- determined at runtime.
+knownLength' :: forall n a r. Storable a
+             => Vector n a -- ^ a vector of some (potentially unknown) length
+             -> (KnownNat n => Proxy n -> r) -- ^ a value that depends on knowing the vector's length, which is given as a 'Proxy'
+             -> r -- ^ the value computed with the length
+knownLength' = V.knownLength'
+
 -- | /O(1)/ Safe indexing using a 'Finite'.
 index :: forall n a. (KnownNat n, Storable a)
       => Vector n a -> Finite n -> a
@@ -444,6 +480,17 @@
 singleton = V.singleton
 {-# inline singleton #-}
 
+#if !MIN_VERSION_GLASGOW_HASKELL(8,3,0,0)
+-- | /O(n)/ Construct a vector in a type safe manner
+--   fromTuple (1,2) :: Vector 2 Int
+--   fromTuple ("hey", "what's", "going", "on") :: Vector 4 String
+fromTuple :: forall a input length.
+             (Storable a, IndexedListLiterals input length a, KnownNat length)
+          => input -> Vector length a
+fromTuple = V.fromTuple
+{-# inline fromTuple #-}
+#endif
+
 -- | /O(n)/ Construct a vector with the same element in each position where the
 -- length is inferred from the type.
 replicate :: forall n a. (KnownNat n, Storable a)
@@ -461,27 +508,17 @@
 -- | /O(n)/ construct a vector of the given length by applying the function to
 -- each index where the length is inferred from the type.
 generate :: forall n a. (KnownNat n, Storable a)
-         => (Int -> a) -> Vector n a
+         => (Finite n -> a) -> Vector n a
 generate = V.generate
 {-# inline generate #-}
 
 -- | /O(n)/ construct a vector of the given length by applying the function to
 -- each index where the length is given explicitly as a 'Proxy' argument.
 generate' :: forall n a p. (KnownNat n, Storable a)
-          => p n -> (Int -> a) -> Vector n a
+          => p n -> (Finite n -> a) -> Vector n a
 generate' = V.generate'
 {-# inline generate' #-}
 
--- | /O(n)/ construct a vector of the given length by applying the function to
--- each index where the length is inferred from the type.
---
--- The function can expect a @'Finite' n@, meaning that its input will
--- always be between @0@ and @n - 1@.
-generate_ :: forall n a. (KnownNat n, Storable a)
-          => (Finite n -> a) -> Vector n a
-generate_ = V.generate_
-{-# inline generate_ #-}
-
 -- | /O(n)/ Apply function n times to value. Zeroth element is original value.
 -- The length is inferred from the type.
 iterateN :: forall n a. (KnownNat n, Storable a)
@@ -517,28 +554,18 @@
 -- | /O(n)/ Construct a vector of length @n@ by applying the monadic action to
 -- each index where n is inferred from the type.
 generateM :: forall n m a. (KnownNat n, Storable a, Monad m)
-          => (Int -> m a) -> m (Vector n a)
+          => (Finite n -> m a) -> m (Vector n a)
 generateM = V.generateM
 {-# inline generateM #-}
 
 -- | /O(n)/ Construct a vector of length @n@ by applying the monadic action to
 -- each index where n is given explicitly as a 'Proxy' argument.
 generateM' :: forall n m a p. (KnownNat n, Storable a, Monad m)
-           => p n -> (Int -> m a) -> m (Vector n a)
+           => p n -> (Finite n -> m a) -> m (Vector n a)
 generateM' = V.generateM'
 {-# inline generateM' #-}
 
--- | /O(n)/ Construct a vector of length @n@ by applying the monadic action to
--- each index where n is inferred from the type.
 --
--- The function can expect a @'Finite' n@, meaning that its input will
--- always be between @0@ and @n - 1@.
-generateM_ :: forall n m a. (KnownNat n, Storable a, Monad m)
-           => (Finite n -> m a) -> m (Vector n a)
-generateM_ = V.generateM_
-{-# inline generateM_ #-}
-
---
 -- ** Unfolding
 --
 
@@ -645,8 +672,8 @@
 -- > <5,9,2,7> // [(2,1),(0,3),(2,8)] = <3,9,8,7>
 --
 (//) :: (Storable a)
-     => Vector m a -- ^ initial vector (of length @m@)
-     -> [(Int, a)]   -- ^ list of index/value pairs (of length @n@)
+     => Vector m a      -- ^ initial vector (of length @m@)
+     -> [(Finite m, a)] -- ^ list of index/value pairs (of length @n@)
      -> Vector m a
 (//) = (V.//)
 {-# inline (//) #-}
@@ -824,8 +851,8 @@
 --
 
 -- | /O(n)/ Pair each element in a vector with its index
-indexed :: (Storable a, Storable (Int,a))
-        => Vector n a -> Vector n (Int,a)
+indexed :: (Storable a, Storable (Int, a), Storable (Finite n, a))
+        => Vector n a -> Vector n (Finite n,a)
 indexed = V.indexed
 {-# inline indexed #-}
 
@@ -841,7 +868,7 @@
 
 -- | /O(n)/ Apply a function to every element of a vector and its index
 imap :: (Storable a, Storable b)
-     => (Int -> a -> b) -> Vector n a -> Vector n b
+     => (Finite n -> a -> b) -> Vector n a -> Vector n b
 imap = V.imap
 {-# inline imap #-}
 
@@ -866,7 +893,7 @@
 -- | /O(n)/ Apply the monadic action to every element of a vector and its
 -- index, yielding a vector of results
 imapM :: (Monad m, Storable a, Storable b)
-      => (Int -> a -> m b) -> Vector n a -> m (Vector n b)
+      => (Finite n -> a -> m b) -> Vector n a -> m (Vector n b)
 imapM = V.imapM
 {-# inline imapM #-}
 
@@ -878,7 +905,7 @@
 
 -- | /O(n)/ Apply the monadic action to every element of a vector and its
 -- index, ignoring the results
-imapM_ :: (Monad m, Storable a) => (Int -> a -> m b) -> Vector n a -> m ()
+imapM_ :: (Monad m, Storable a) => (Finite n -> a -> m b) -> Vector n a -> m ()
 imapM_ = V.imapM_
 {-# inline imapM_ #-}
 
@@ -947,7 +974,7 @@
 -- | /O(n)/ Zip two vectors of the same length with a function that also takes
 -- the elements' indices).
 izipWith :: (Storable a,Storable b,Storable c)
-         => (Int -> a -> b -> c)
+         => (Finite n -> a -> b -> c)
          -> Vector n a
          -> Vector n b
          -> Vector n c
@@ -955,7 +982,7 @@
 {-# inline izipWith #-}
 
 izipWith3 :: (Storable a,Storable b,Storable c,Storable d)
-          => (Int -> a -> b -> c -> d)
+          => (Finite n -> a -> b -> c -> d)
           -> Vector n a
           -> Vector n b
           -> Vector n c
@@ -964,7 +991,7 @@
 {-# inline izipWith3 #-}
 
 izipWith4 :: (Storable a,Storable b,Storable c,Storable d,Storable e)
-          => (Int -> a -> b -> c -> d -> e)
+          => (Finite n -> a -> b -> c -> d -> e)
           -> Vector n a
           -> Vector n b
           -> Vector n c
@@ -974,7 +1001,7 @@
 {-# inline izipWith4 #-}
 
 izipWith5 :: (Storable a,Storable b,Storable c,Storable d,Storable e,Storable f)
-          => (Int -> a -> b -> c -> d -> e -> f)
+          => (Finite n -> a -> b -> c -> d -> e -> f)
           -> Vector n a
           -> Vector n b
           -> Vector n c
@@ -985,7 +1012,7 @@
 {-# inline izipWith5 #-}
 
 izipWith6 :: (Storable a,Storable b,Storable c,Storable d,Storable e,Storable f,Storable g)
-          => (Int -> a -> b -> c -> d -> e -> f -> g)
+          => (Finite n -> a -> b -> c -> d -> e -> f -> g)
           -> Vector n a
           -> Vector n b
           -> Vector n c
@@ -1051,7 +1078,7 @@
 -- | /O(n)/ Zip the two vectors with a monadic action that also takes the
 -- element index and yield a vector of results
 izipWithM :: (Monad m, Storable a, Storable b, Storable c)
-         => (Int -> a -> b -> m c) -> Vector n a -> Vector n b -> m (Vector n c)
+         => (Finite n -> a -> b -> m c) -> Vector n a -> Vector n b -> m (Vector n c)
 izipWithM = V.izipWithM
 {-# inline izipWithM #-}
 
@@ -1064,7 +1091,7 @@
 -- | /O(n)/ Zip the two vectors with a monadic action that also takes
 -- the element index and ignore the results
 izipWithM_ :: (Monad m, Storable a, Storable b)
-           => (Int -> a -> b -> m c) -> Vector n a -> Vector n b -> m ()
+           => (Finite n -> a -> b -> m c) -> Vector n a -> Vector n b -> m ()
 izipWithM_ = V.izipWithM_
 {-# inline izipWithM_ #-}
 
@@ -1129,14 +1156,14 @@
 
 -- | /O(n)/ Yield 'Just' the index of the first element matching the predicate
 -- or 'Nothing' if no such element exists.
-findIndex :: Storable a => (a -> Bool) -> Vector n a -> Maybe Int
+findIndex :: Storable a => (a -> Bool) -> Vector n a -> Maybe (Finite n)
 findIndex = V.findIndex
 {-# inline findIndex #-}
 
 -- | /O(n)/ Yield 'Just' the index of the first occurence of the given element or
 -- 'Nothing' if the vector does not contain the element. This is a specialised
 -- version of 'findIndex'.
-elemIndex :: (Storable a, Eq a) => a -> Vector n a -> Maybe Int
+elemIndex :: (Storable a, Eq a) => a -> Vector n a -> Maybe (Finite n)
 elemIndex = V.elemIndex
 {-# inline elemIndex #-}
 
@@ -1185,24 +1212,24 @@
 {-# inline foldr1' #-}
 
 -- | /O(n)/ Left fold (function applied to each element and its index)
-ifoldl :: Storable b => (a -> Int -> b -> a) -> a -> Vector n b -> a
+ifoldl :: Storable b => (a -> Finite n -> b -> a) -> a -> Vector n b -> a
 ifoldl = V.ifoldl
 {-# inline ifoldl #-}
 
 -- | /O(n)/ Left fold with strict accumulator (function applied to each element
 -- and its index)
-ifoldl' :: Storable b => (a -> Int -> b -> a) -> a -> Vector n b -> a
+ifoldl' :: Storable b => (a -> Finite n -> b -> a) -> a -> Vector n b -> a
 ifoldl' = V.ifoldl'
 {-# inline ifoldl' #-}
 
 -- | /O(n)/ Right fold (function applied to each element and its index)
-ifoldr :: Storable a => (Int -> a -> b -> b) -> b -> Vector n a -> b
+ifoldr :: Storable a => (Finite n -> a -> b -> b) -> b -> Vector n a -> b
 ifoldr = V.ifoldr
 {-# inline ifoldr #-}
 
 -- | /O(n)/ Right fold with strict accumulator (function applied to each
 -- element and its index)
-ifoldr' :: Storable a => (Int -> a -> b -> b) -> b -> Vector n a -> b
+ifoldr' :: Storable a => (Finite n -> a -> b -> b) -> b -> Vector n a -> b
 ifoldr' = V.ifoldr'
 {-# inline ifoldr' #-}
 
@@ -1263,26 +1290,26 @@
 {-# inline minimumBy #-}
 
 -- | /O(n)/ Yield the index of the maximum element of the non-empty vector.
-maxIndex :: (Storable a, Ord a, KnownNat n) => Vector (n+1) a -> Int
+maxIndex :: (Storable a, Ord a, KnownNat n) => Vector (n+1) a -> Finite (n + 1)
 maxIndex = V.maxIndex
 {-# inline maxIndex #-}
 
 -- | /O(n)/ Yield the index of the maximum element of the non-empty vector
 -- according to the given comparison function.
 maxIndexBy :: (Storable a, KnownNat n)
-           => (a -> a -> Ordering) -> Vector (n+1) a -> Int
+           => (a -> a -> Ordering) -> Vector (n+1) a -> Finite (n + 1)
 maxIndexBy = V.maxIndexBy
 {-# inline maxIndexBy #-}
 
 -- | /O(n)/ Yield the index of the minimum element of the non-empty vector.
-minIndex :: (Storable a, Ord a, KnownNat n) => Vector (n+1) a -> Int
+minIndex :: (Storable a, Ord a, KnownNat n) => Vector (n+1) a -> Finite (n + 1)
 minIndex = V.minIndex
 {-# inline minIndex #-}
 
 -- | /O(n)/ Yield the index of the minimum element of the non-empty vector
 -- according to the given comparison function.
 minIndexBy :: (Storable a, KnownNat n)
-           => (a -> a -> Ordering) -> Vector (n+1) a -> Int
+           => (a -> a -> Ordering) -> Vector (n+1) a -> Finite (n + 1)
 minIndexBy = V.minIndexBy
 {-# inline minIndexBy #-}
 
@@ -1294,7 +1321,7 @@
 {-# inline foldM #-}
 
 -- | /O(n)/ Monadic fold (action applied to each element and its index)
-ifoldM :: (Monad m, Storable b) => (a -> Int -> b -> m a) -> a -> Vector n b -> m a
+ifoldM :: (Monad m, Storable b) => (a -> Finite n -> b -> m a) -> a -> Vector n b -> m a
 ifoldM = V.ifoldM
 {-# inline ifoldM #-}
 
@@ -1312,7 +1339,7 @@
 -- | /O(n)/ Monadic fold with strict accumulator (action applied to each
 -- element and its index)
 ifoldM' :: (Monad m, Storable b)
-        => (a -> Int -> b -> m a) -> a -> Vector n b -> m a
+        => (a -> Finite n -> b -> m a) -> a -> Vector n b -> m a
 ifoldM' = V.ifoldM'
 {-# inline ifoldM' #-}
 
@@ -1331,7 +1358,7 @@
 -- | /O(n)/ Monadic fold that discards the result (action applied to
 -- each element and its index)
 ifoldM_ :: (Monad m, Storable b)
-        => (a -> Int -> b -> m a) -> a -> Vector n b -> m ()
+        => (a -> Finite n -> b -> m a) -> a -> Vector n b -> m ()
 ifoldM_ = V.ifoldM_
 {-# inline ifoldM_ #-}
 
@@ -1350,7 +1377,7 @@
 -- | /O(n)/ Monadic fold with strict accumulator that discards the result
 -- (action applied to each element and its index)
 ifoldM'_ :: (Monad m, Storable b)
-         => (a -> Int -> b -> m a) -> a -> Vector n b -> m ()
+         => (a -> Finite n -> b -> m a) -> a -> Vector n b -> m ()
 ifoldM'_ = V.ifoldM'_
 {-# inline ifoldM'_ #-}
 
@@ -1506,6 +1533,41 @@
               => [a] -> (forall n. KnownNat n => Vector n a -> r) -> r
 withSizedList xs = withSized (VS.fromList xs)
 {-# inline withSizedList #-}
+
+-- ** Mutable vectors
+
+-- | /O(n)/ Yield an immutable copy of the mutable vector.
+freeze :: (PrimMonad m, Storable a)
+       => VSM.MVector n (PrimState m) a
+       -> m (Vector n a)
+freeze = V.freeze
+
+-- | /O(1)/ Unsafely convert a mutable vector to an immutable one withouy
+-- copying. The mutable vector may not be used after this operation.
+unsafeFreeze :: (PrimMonad m, Storable a)
+             => VSM.MVector n (PrimState m) a
+             -> m (Vector n a)
+unsafeFreeze = V.unsafeFreeze
+
+-- | /O(n)/ Yield a mutable copy of the immutable vector.
+thaw :: (PrimMonad m, Storable a)
+     => Vector n a
+     -> m (VSM.MVector n (PrimState m) a)
+thaw = V.thaw
+
+-- | /O(n)/ Unsafely convert an immutable vector to a mutable one without
+-- copying. The immutable vector may not be used after this operation.
+unsafeThaw :: (PrimMonad m, Storable a)
+           => Vector n a
+           -> m (VSM.MVector n (PrimState m) a)
+unsafeThaw = V.unsafeThaw
+
+-- | /O(n)/ Copy an immutable vector into a mutable one.
+copy :: (PrimMonad m, Storable a)
+     => VSM.MVector n (PrimState m) a
+     -> Vector n a
+     -> m ()
+copy = V.copy
 
 -- ** Unsized vectors
 
diff --git a/vector-sized.cabal b/vector-sized.cabal
--- a/vector-sized.cabal
+++ b/vector-sized.cabal
@@ -1,5 +1,5 @@
 name:                vector-sized
-version:             0.6.1.0
+version:             1.0.0.0
 synopsis:            Size tagged vectors
 description:         Please see README.md
 homepage:            http://github.com/expipiplus1/vector-sized#readme
@@ -14,15 +14,26 @@
                    , changelog.md
 cabal-version:       >=1.10
 
+-- nice literals are not enabled on GHC 8.4; see
+-- https://github.com/DavidM-D/indexed-list-literals/issues/1
+
 library
   hs-source-dirs:      src
   exposed-modules:     Data.Vector.Sized
                      , Data.Vector.Generic.Sized
+                     , Data.Vector.Generic.Sized.Internal
                      , Data.Vector.Storable.Sized
+                     , Data.Vector.Mutable.Sized
+                     , Data.Vector.Generic.Mutable.Sized
+                     , Data.Vector.Storable.Mutable.Sized
+                     , Data.Vector.Generic.Mutable.Sized.Internal
   build-depends:       base >= 4.9 && < 5
                      , vector >= 0.11 && < 0.13
                      , deepseq >= 1.1 && < 1.5
                      , finite-typelits >= 0.1
+                     , primitive >= 0.5 && < 0.7
+  if impl(ghc < 8.3)
+    build-depends: indexed-list-literals >= 0.1.0.1
   default-language:    Haskell2010
 
 source-repository head
