diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 0.3.4
+
+* Switch to gauge
+
 ## 0.3.3
 
 * Move into mono-traversable repo
diff --git a/Data/Mutable.hs b/Data/Mutable.hs
deleted file mode 100644
--- a/Data/Mutable.hs
+++ /dev/null
@@ -1,68 +0,0 @@
--- | Classes and concrete implementations for mutable data structures.
---
--- For more information on the design of this library, see the README file,
--- also available at <http://www.stackage.org/package/mutable-containers>.
-module Data.Mutable
-    ( -- * Data types
-      -- ** Single-cell mutable references
-      PRef
-    , IOPRef
-    , asPRef
-    , URef
-    , IOURef
-    , asURef
-    , SRef
-    , IOSRef
-    , asSRef
-    , BRef
-    , IOBRef
-    , asBRef
-      -- *** Standard re-exports
-    , IORef
-    , asIORef
-    , STRef
-    , asSTRef
-    , MutVar
-    , asMutVar
-      -- ** Collections/queues
-    , Deque
-    , UDeque
-    , asUDeque
-    , SDeque
-    , asSDeque
-    , BDeque
-    , asBDeque
-    , DLList
-    , asDLList
-      -- * Type classes
-    , MutableContainer (..)
-    , MutableRef (..)
-    , MutableAtomicRef (..)
-    , MutableCollection (..)
-    , MutablePushFront (..)
-    , MutablePushBack (..)
-    , MutablePopFront (..)
-    , MutablePopBack (..)
-      -- * Constraint kinds
-    , MutableQueue
-    , MutableStack
-    , MutableDeque
-      -- * Convenience re-exports
-    , PrimMonad
-    , PrimState
-    , RealWorld
-    , Prim
-    , Unbox
-    , Storable
-    ) where
-
-import Data.Mutable.Class
-import Data.Mutable.URef
-import Data.Mutable.SRef
-import Data.Mutable.PRef
-import Data.Mutable.BRef
-import Data.Mutable.Deque
-import Data.Mutable.DLList
-import Data.Vector.Unboxed (Unbox)
-import Data.Primitive (Prim)
-import Data.Vector.Storable (Storable)
diff --git a/Data/Mutable/BRef.hs b/Data/Mutable/BRef.hs
deleted file mode 100644
--- a/Data/Mutable/BRef.hs
+++ /dev/null
@@ -1,71 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
--- | Use 1-length mutable boxed vectors for mutable references.
---
--- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.
-module Data.Mutable.BRef
-    ( -- * Types
-      BRef
-    , IOBRef
-      -- * Functions
-    , asBRef
-    , MutableRef (..)
-    ) where
-
-import           Control.Monad               (liftM)
-import           Data.Monoid                 (Monoid, mempty)
-import           Data.MonoTraversable        (Element)
-import           Data.Mutable.Class
-import           Data.Sequences              (IsSequence)
-import qualified Data.Vector.Generic.Mutable as V
-import qualified Data.Vector.Mutable         as VB
-
--- | A boxed vector reference, supporting any monad.
---
--- Since 0.2.0
-newtype BRef s a = BRef (VB.MVector s a)
-
--- |
--- Since 0.2.0
-asBRef :: BRef s a -> BRef s a
-asBRef x = x
-{-# INLINE asBRef #-}
-
--- | A boxed IO vector reference.
-type IOBRef = BRef (PrimState IO)
-
-instance MutableContainer (BRef s a) where
-    type MCState (BRef s a) = s
-instance MutableRef (BRef s a) where
-    type RefElement (BRef s a) = a
-
-    newRef = liftM BRef . V.replicate 1
-    {-# INLINE newRef#-}
-
-    readRef (BRef v) = V.unsafeRead v 0
-    {-# INLINE readRef #-}
-
-    writeRef (BRef v) = V.unsafeWrite v 0
-    {-# INLINE writeRef #-}
-
-    modifyRef (BRef v) f = V.unsafeRead v 0 >>= V.unsafeWrite v 0 . f
-    {-# INLINE modifyRef #-}
-
-    modifyRef' = modifyRef
-    {-# INLINE modifyRef' #-}
-
-instance Monoid w => MutableCollection (BRef s w) where
-    type CollElement (BRef s w) = Element w
-    newColl = newRef mempty
-    {-# INLINE newColl #-}
-instance IsSequence seq => MutablePushFront (BRef s seq) where
-    pushFront = pushFrontRef
-    {-# INLINE pushFront #-}
-instance IsSequence seq => MutablePushBack (BRef s seq) where
-    pushBack = pushBackRef
-    {-# INLINE pushBack #-}
-instance IsSequence seq => MutablePopFront (BRef s seq) where
-    popFront = popFrontRef
-    {-# INLINE popFront #-}
-instance IsSequence seq => MutablePopBack (BRef s seq) where
-    popBack = popBackRef
-    {-# INLINE popBack #-}
diff --git a/Data/Mutable/Class.hs b/Data/Mutable/Class.hs
deleted file mode 100644
--- a/Data/Mutable/Class.hs
+++ /dev/null
@@ -1,373 +0,0 @@
-{-# LANGUAGE ConstraintKinds   #-}
-{-# LANGUAGE FlexibleContexts  #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE TypeFamilies      #-}
--- | Various typeclasses for mutable containers.
-module Data.Mutable.Class
-    ( PrimMonad
-    , PrimState
-    , RealWorld
-    , MutableQueue
-    , MutableStack
-    , MutableDeque
-    , IORef
-    , asIORef
-    , STRef
-    , asSTRef
-    , MutVar
-    , asMutVar
-    , MutableContainer (..)
-    , MutableRef (..)
-    , MutableAtomicRef (..)
-    , MutableCollection (..)
-    , MutablePushFront (..)
-    , MutablePushBack (..)
-    , MutablePopFront (..)
-    , MutablePopBack (..)
-    , pushFrontRef
-    , pushBackRef
-    , popFrontRef
-    , popBackRef
-    ) where
-
-import           Control.Monad.Primitive
-import           Data.IORef
-import           Data.Monoid
-import           Data.MonoTraversable    (Element)
-import           Data.Primitive.MutVar
-import qualified Data.Sequences          as Seqs
-import           Data.STRef
-
--- | The parent typeclass for all mutable containers.
---
--- Since 0.2.0
-class MutableContainer c where
-    -- | Associated type giving the primitive state token for the given
-    -- container, much like 'PrimState' from primitive.
-    --
-    -- Since 0.2.0
-    type MCState c
-
-instance MutableContainer (IORef a) where
-    type MCState (IORef a) = PrimState IO
-instance MutableContainer (STRef s a) where
-    type MCState (STRef s a) = s
-instance MutableContainer (MutVar s a) where
-    type MCState (MutVar s a) = s
-
--- | Typeclass for single-cell mutable references.
---
--- Since 0.2.0
-class MutableContainer c => MutableRef c where
-    -- | Associated type giving the type of the value inside the mutable
-    -- reference.
-    --
-    -- Since 0.2.0
-    type RefElement c
-
-    -- | Create a new mutable reference with the given value.
-    --
-    -- Since 0.2.0
-    newRef :: (PrimMonad m, PrimState m ~ MCState c)
-           => RefElement c
-           -> m c
-
-    -- | Read the current value in the mutable reference.
-    --
-    -- Since 0.2.0
-    readRef :: (PrimMonad m, PrimState m ~ MCState c)
-            => c
-            -> m (RefElement c)
-
-    -- | Write a new value to the mutable reference.
-    --
-    -- Since 0.2.0
-    writeRef :: (PrimMonad m, PrimState m ~ MCState c)
-             => c
-             -> RefElement c
-             -> m ()
-
-    -- | Modify the value in the mutable reference, without necessarily forcing the result.
-    --
-    -- Note: some implementations /will/ force the result, in particular
-    -- @PRef@, @SRef@, and @URef@.
-    --
-    -- Since 0.2.0
-    modifyRef :: (PrimMonad m, PrimState m ~ MCState c)
-              => c
-              -> (RefElement c -> RefElement c)
-              -> m ()
-
-    -- | Modify the value in the mutable reference, forcing the result.
-    --
-    -- Since 0.2.0
-    modifyRef' :: (PrimMonad m, PrimState m ~ MCState c)
-               => c
-               -> (RefElement c -> RefElement c)
-               -> m ()
-
-instance MutableRef (IORef a) where
-    type RefElement (IORef a) = a
-    newRef = primToPrim . newIORef
-    {-# INLINE newRef #-}
-    readRef = primToPrim . readIORef
-    {-# INLINE readRef #-}
-    writeRef c = primToPrim . writeIORef c
-    {-# INLINE writeRef #-}
-    modifyRef c = primToPrim . modifyIORef c
-    {-# INLINE modifyRef #-}
-    modifyRef' c = primToPrim . modifyIORef' c
-    {-# INLINE modifyRef' #-}
-instance MutableRef (STRef s a) where
-    type RefElement (STRef s a) = a
-    newRef = primToPrim . newSTRef
-    {-# INLINE newRef #-}
-    readRef = primToPrim . readSTRef
-    {-# INLINE readRef #-}
-    writeRef c = primToPrim . writeSTRef c
-    {-# INLINE writeRef #-}
-    modifyRef c = primToPrim . modifySTRef c
-    {-# INLINE modifyRef #-}
-    modifyRef' c = primToPrim . modifySTRef' c
-    {-# INLINE modifyRef' #-}
-instance MutableRef (MutVar s a) where
-    type RefElement (MutVar s a) = a
-    newRef = newMutVar
-    {-# INLINE newRef #-}
-    readRef = readMutVar
-    {-# INLINE readRef #-}
-    writeRef = writeMutVar
-    {-# INLINE writeRef #-}
-    modifyRef = modifyMutVar
-    {-# INLINE modifyRef #-}
-    modifyRef' = modifyMutVar'
-    {-# INLINE modifyRef' #-}
-
--- | @MutableRef@s that provide for atomic modifications of their contents.
---
--- Since 0.2.0
-class MutableRef c => MutableAtomicRef c where
-    -- | Modify the value without necessarily forcing the result.
-    --
-    -- Since 0.2.0
-    atomicModifyRef
-        :: (PrimMonad m, PrimState m ~ MCState c)
-        => c
-        -> (RefElement c -> (RefElement c, a))
-        -> m a
-
-    -- | Modify the value, forcing the result.
-    --
-    -- Since 0.2.0
-    atomicModifyRef'
-        :: (PrimMonad m, PrimState m ~ MCState c)
-        => c
-        -> (RefElement c -> (RefElement c, a))
-        -> m a
-instance MutableAtomicRef (IORef a) where
-    atomicModifyRef c = primToPrim . atomicModifyIORef c
-    {-# INLINE atomicModifyRef #-}
-    atomicModifyRef' c = primToPrim . atomicModifyIORef' c
-    {-# INLINE atomicModifyRef' #-}
-instance MutableAtomicRef (MutVar s a) where
-    atomicModifyRef = atomicModifyMutVar
-    {-# INLINE atomicModifyRef #-}
-    atomicModifyRef' = atomicModifyMutVar'
-    {-# INLINE atomicModifyRef' #-}
-
--- | Containers which contain 0 or more values.
---
--- Since 0.2.0
-class MutableContainer c => MutableCollection c where
-    -- | The type of each value in the collection.
-    --
-    -- Since 0.2.0
-    type CollElement c
-
-    -- | Create a new, empty collection.
-    --
-    -- Since 0.2.0
-    newColl :: (PrimMonad m, PrimState m ~ MCState c)
-            => m c
-instance Monoid w => MutableCollection (IORef w) where
-    type CollElement (IORef w) = Element w
-    newColl = newRef mempty
-    {-# INLINE newColl #-}
-instance Monoid w => MutableCollection (STRef s w) where
-    type CollElement (STRef s w) = Element w
-    newColl = newRef mempty
-    {-# INLINE newColl #-}
-instance Monoid w => MutableCollection (MutVar s w) where
-    type CollElement (MutVar s w) = Element w
-    newColl = newRef mempty
-    {-# INLINE newColl #-}
-
--- | Take a value from the front of the collection, if available.
---
--- Since 0.2.0
-class MutableCollection c => MutablePopFront c where
-    -- | Take a value from the front of the collection, if available.
-    --
-    -- Since 0.2.0
-    popFront :: (PrimMonad m, PrimState m ~ MCState c)
-             => c
-             -> m (Maybe (CollElement c))
-popFrontRef
-    :: ( PrimMonad m
-       , PrimState m ~ MCState c
-       , MutableRef c
-       , CollElement c ~ Element (RefElement c)
-       , Seqs.IsSequence (RefElement c)
-       )
-    => c
-    -> m (Maybe (CollElement c))
-popFrontRef c = do
-    l <- readRef c
-    case Seqs.uncons l of
-        Nothing -> return Nothing
-        Just (x, xs) -> do
-            writeRef c xs
-            return (Just x)
-{-# INLINE popFrontRef #-}
-instance Seqs.IsSequence a => MutablePopFront (IORef a) where
-    popFront = popFrontRef
-    {-# INLINE popFront #-}
-instance Seqs.IsSequence a => MutablePopFront (STRef s a) where
-    popFront = popFrontRef
-    {-# INLINE popFront #-}
-instance Seqs.IsSequence a => MutablePopFront (MutVar s a) where
-    popFront = popFrontRef
-    {-# INLINE popFront #-}
-
--- | Place a value at the front of the collection.
---
--- Since 0.2.0
-class MutableCollection c => MutablePushFront c where
-    -- | Place a value at the front of the collection.
-    --
-    -- Since 0.2.0
-    pushFront :: (PrimMonad m, PrimState m ~ MCState c)
-              => c
-              -> CollElement c
-              -> m ()
-pushFrontRef
-    :: ( PrimMonad m
-       , PrimState m ~ MCState c
-       , MutableRef c
-       , CollElement c ~ Element (RefElement c)
-       , Seqs.IsSequence (RefElement c)
-       )
-    => c
-    -> CollElement c
-    -> m ()
-pushFrontRef c e = modifyRef' c (Seqs.cons e)
-{-# INLINE pushFrontRef #-}
-instance Seqs.IsSequence a => MutablePushFront (IORef a) where
-    pushFront = pushFrontRef
-    {-# INLINE pushFront #-}
-instance Seqs.IsSequence a => MutablePushFront (STRef s a) where
-    pushFront = pushFrontRef
-    {-# INLINE pushFront #-}
-instance Seqs.IsSequence a => MutablePushFront (MutVar s a) where
-    pushFront = pushFrontRef
-    {-# INLINE pushFront #-}
-
--- | Take a value from the back of the collection, if available.
---
--- Since 0.2.0
-class MutableCollection c => MutablePopBack c where
-    -- | Take a value from the back of the collection, if available.
-    --
-    -- Since 0.2.0
-    popBack :: (PrimMonad m, PrimState m ~ MCState c)
-            => c
-            -> m (Maybe (CollElement c))
-popBackRef
-    :: ( PrimMonad m
-       , PrimState m ~ MCState c
-       , MutableRef c
-       , CollElement c ~ Element (RefElement c)
-       , Seqs.IsSequence (RefElement c)
-       )
-    => c
-    -> m (Maybe (CollElement c))
-popBackRef c = do
-    l <- readRef c
-    case Seqs.unsnoc l of
-        Nothing -> return Nothing
-        Just (xs, x) -> do
-            writeRef c xs
-            return (Just x)
-{-# INLINE popBackRef #-}
-instance Seqs.IsSequence a => MutablePopBack (IORef a) where
-    popBack = popBackRef
-    {-# INLINE popBack #-}
-instance Seqs.IsSequence a => MutablePopBack (STRef s a) where
-    popBack = popBackRef
-    {-# INLINE popBack #-}
-instance Seqs.IsSequence a => MutablePopBack (MutVar s a) where
-    popBack = popBackRef
-    {-# INLINE popBack #-}
-
--- | Place a value at the back of the collection.
---
--- Since 0.2.0
-class MutableCollection c => MutablePushBack c where
-    -- | Place a value at the back of the collection.
-    --
-    -- Since 0.2.0
-    pushBack :: (PrimMonad m, PrimState m ~ MCState c)
-             => c
-             -> CollElement c
-             -> m ()
-pushBackRef
-    :: ( PrimMonad m
-       , PrimState m ~ MCState c
-       , MutableRef c
-       , CollElement c ~ Element (RefElement c)
-       , Seqs.IsSequence (RefElement c)
-       )
-    => c
-    -> CollElement c
-    -> m ()
-pushBackRef c e = modifyRef' c (`Seqs.snoc` e)
-{-# INLINE pushBackRef #-}
-instance Seqs.IsSequence a => MutablePushBack (IORef a) where
-    pushBack = pushBackRef
-    {-# INLINE pushBack #-}
-instance Seqs.IsSequence a => MutablePushBack (STRef s a) where
-    pushBack = pushBackRef
-    {-# INLINE pushBack #-}
-instance Seqs.IsSequence a => MutablePushBack (MutVar s a) where
-    pushBack = pushBackRef
-    {-# INLINE pushBack #-}
-
--- | Collections which allow pushing and popping at the front (aka FIFOs).
---
--- Since 0.2.0
-type MutableQueue c = (MutablePopFront c, MutablePushBack c)
-
--- | Collections which allow pushing at the back and popping at the front (aka FILOs).
---
--- Since 0.2.0
-type MutableStack c = (MutablePopFront c, MutablePushFront c)
-
--- | Collections which allow pushing and popping at the front and back.
---
--- Since 0.2.0
-type MutableDeque c = (MutableQueue c, MutablePushFront c, MutablePopBack c)
-
--- |
--- Since 0.2.0
-asIORef :: IORef a -> IORef a
-asIORef = id
-
--- |
--- Since 0.2.0
-asSTRef :: STRef s a -> STRef s a
-asSTRef = id
-
--- |
--- Since 0.2.0
-asMutVar :: MutVar s a -> MutVar s a
-asMutVar = id
diff --git a/Data/Mutable/DLList.hs b/Data/Mutable/DLList.hs
deleted file mode 100644
--- a/Data/Mutable/DLList.hs
+++ /dev/null
@@ -1,101 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
--- | Doubly-linked list
-module Data.Mutable.DLList
-    ( DLList
-    , asDLList
-    , module Data.Mutable.Class
-    ) where
-
-import Data.Mutable.Class
-
-data Node s a = Node
-    a
-    (MutVar s (Maybe (Node s a))) -- previous
-    (MutVar s (Maybe (Node s a))) -- next
-
--- | A doubly-linked list.
---
--- Since 0.3.0
-data DLList s a = DLList (MutVar s (Maybe (Node s a))) (MutVar s (Maybe (Node s a)))
-
--- |
--- Since 0.2.0
-asDLList :: DLList s a -> DLList s a
-asDLList = id
-{-# INLINE asDLList #-}
-
-instance MutableContainer (DLList s a) where
-    type MCState (DLList s a) = s
-instance MutableCollection (DLList s a) where
-    type CollElement (DLList s a) = a
-    newColl = do
-        x <- newRef $! Nothing
-        y <- newRef $! Nothing
-        return $! DLList x y
-    {-# INLINE newColl #-}
-instance MutablePopFront (DLList s a) where
-    popFront (DLList frontRef backRef) = do
-        mfront <- readRef frontRef
-        case mfront of
-            Nothing -> return Nothing
-            Just (Node val _ nextRef) -> do
-                mnext <- readRef nextRef
-                case mnext of
-                    Nothing -> do
-                        writeRef frontRef $! Nothing
-                        writeRef backRef $! Nothing
-                    Just next@(Node _ prevRef _) -> do
-                        writeRef prevRef $! Nothing
-                        writeRef frontRef $! Just next
-                return $ Just val
-    {-# INLINE popFront #-}
-instance MutablePopBack (DLList s a) where
-    popBack (DLList frontRef backRef) = do
-        mback <- readRef backRef
-        case mback of
-            Nothing -> return Nothing
-            Just (Node val prevRef _) -> do
-                mprev <- readRef prevRef
-                case mprev of
-                    Nothing -> do
-                        writeRef frontRef $! Nothing
-                        writeRef backRef $! Nothing
-                    Just prev@(Node _ _ nextRef) -> do
-                        writeRef nextRef $! Nothing
-                        writeRef backRef (Just prev)
-                return $ Just val
-    {-# INLINE popBack #-}
-instance MutablePushFront (DLList s a) where
-    pushFront (DLList frontRef backRef) val = do
-        mfront <- readRef frontRef
-        case mfront of
-            Nothing -> do
-                prevRef <- newRef $! Nothing
-                nextRef <- newRef $! Nothing
-                let node = Just $ Node val prevRef nextRef
-                writeRef frontRef node
-                writeRef backRef node
-            Just front@(Node _ prevRef _) -> do
-                prevRefNew <- newRef $! Nothing
-                nextRef <- newRef $ Just front
-                let node = Just $ Node val prevRefNew nextRef
-                writeRef prevRef node
-                writeRef frontRef node
-    {-# INLINE pushFront #-}
-instance MutablePushBack (DLList s a) where
-    pushBack (DLList frontRef backRef) val = do
-        mback <- readRef backRef
-        case mback of
-            Nothing -> do
-                prevRef <- newRef $! Nothing
-                nextRef <- newRef $! Nothing
-                let node = Just $! Node val prevRef nextRef
-                writeRef frontRef $! node
-                writeRef backRef $! node
-            Just back@(Node _ _ nextRef) -> do
-                nextRefNew <- newRef $! Nothing
-                prevRef <- newRef $! Just back
-                let node = Just $! Node val prevRef nextRefNew
-                writeRef nextRef $! node
-                writeRef backRef $! node
-    {-# INLINE pushBack #-}
diff --git a/Data/Mutable/Deque.hs b/Data/Mutable/Deque.hs
deleted file mode 100644
--- a/Data/Mutable/Deque.hs
+++ /dev/null
@@ -1,152 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-module Data.Mutable.Deque
-    ( Deque
-    , UDeque
-    , asUDeque
-    , SDeque
-    , asSDeque
-    , BDeque
-    , asBDeque
-    , module Data.Mutable.Class
-    ) where
-
-import           Control.Exception            (assert)
-import           Control.Monad                (liftM)
-import           Data.Mutable.Class
-import qualified Data.Vector.Generic.Mutable  as V
-import qualified Data.Vector.Mutable          as B
-import qualified Data.Vector.Storable.Mutable as S
-import qualified Data.Vector.Unboxed.Mutable  as U
-
-data DequeState v s a = DequeState
-    (v s a)
-    {-# UNPACK #-} !Int -- start
-    {-# UNPACK #-} !Int -- size
-
--- | A double-ended queue supporting any underlying vector type and any monad.
---
--- This implements a circular double-ended queue with exponential growth.
---
--- Since 0.2.0
-newtype Deque v s a = Deque (MutVar s (DequeState v s a))
-
--- | A 'Deque' specialized to unboxed vectors.
---
--- Since 0.2.0
-type UDeque = Deque U.MVector
-
--- | A 'Deque' specialized to storable vectors.
---
--- Since 0.2.0
-type SDeque = Deque S.MVector
-
--- | A 'Deque' specialized to boxed vectors.
---
--- Since 0.2.0
-type BDeque = Deque B.MVector
-
--- |
--- Since 0.2.0
-asUDeque :: UDeque s a -> UDeque s a
-asUDeque = id
-
--- |
--- Since 0.2.0
-asSDeque :: SDeque s a -> SDeque s a
-asSDeque = id
-
--- |
--- Since 0.2.0
-asBDeque :: BDeque s a -> BDeque s a
-asBDeque = id
-
-instance MutableContainer (Deque v s a) where
-    type MCState (Deque v s a) = s
-instance V.MVector v a => MutableCollection (Deque v s a) where
-    type CollElement (Deque v s a) = a
-    newColl = do
-        v <- V.new baseSize
-        liftM Deque $ newRef (DequeState v 0 0)
-      where
-        baseSize = 32
-    {-# INLINE newColl #-}
-instance V.MVector v a => MutablePopFront (Deque v s a) where
-    popFront (Deque var) = do
-        DequeState v start size <- readRef var
-        if size == 0
-            then return Nothing
-            else do
-                x <- V.unsafeRead v start
-                let start' = start + 1
-                    start''
-                        | start' >= V.length v = 0
-                        | otherwise = start'
-                writeRef var $! DequeState v start'' (size - 1)
-                return $! Just x
-    {-# INLINE popFront #-}
-instance V.MVector v a => MutablePopBack (Deque v s a) where
-    popBack (Deque var) = do
-        DequeState v start size <- readRef var
-        if size == 0
-            then return Nothing
-            else do
-                let size' = size - 1
-                    end = start + size'
-                    end'
-                        | end >= V.length v = end - V.length v
-                        | otherwise = end
-                x <- V.unsafeRead v end'
-                writeRef var $! DequeState v start size'
-                return $! Just x
-    {-# INLINE popBack #-}
-instance V.MVector v a => MutablePushFront (Deque v s a) where
-    pushFront (Deque var) x = do
-        DequeState v start size <- readRef var
-        inner v start size
-      where
-        inner v start size = do
-            if size >= V.length v
-                then newVector v start size inner
-                else do
-                    let size' = size + 1
-                        start' = (start - 1) `rem` V.length v
-                        start''
-                            | start' < 0 = V.length v + start'
-                            | otherwise = start'
-                    V.unsafeWrite v start'' x
-                    writeRef var $! DequeState v start'' size'
-    {-# INLINE pushFront #-}
-instance V.MVector v a => MutablePushBack (Deque v s a) where
-    pushBack (Deque var) x = do
-        DequeState v start size <- readRef var
-        inner v start size
-      where
-        inner v start size = do
-            if size >= V.length v
-                then newVector v start size inner
-                else do
-                    let end = start + size
-                        end'
-                            | end >= V.length v = end - V.length v
-                            | otherwise = end
-                    V.unsafeWrite v end' x
-                    writeRef var $! DequeState v start (size + 1)
-    {-# INLINE pushBack #-}
-
-newVector :: (PrimMonad m, V.MVector v a)
-          => v (PrimState m) a
-          -> Int
-          -> Int
-          -> (v (PrimState m) a -> Int -> Int -> m b)
-          -> m b
-newVector v size2 sizeOrig f = assert (sizeOrig == V.length v) $ do
-    v' <- V.unsafeNew (V.length v * 2)
-    let size1 = V.length v - size2
-    V.unsafeCopy
-        (V.unsafeTake size1 v')
-        (V.unsafeSlice size2 size1 v)
-    V.unsafeCopy
-        (V.unsafeSlice size1 size2 v')
-        (V.unsafeTake size2 v)
-    f v' 0 sizeOrig
-{-# INLINE newVector #-}
diff --git a/Data/Mutable/PRef.hs b/Data/Mutable/PRef.hs
deleted file mode 100644
--- a/Data/Mutable/PRef.hs
+++ /dev/null
@@ -1,64 +0,0 @@
-{-# LANGUAGE MagicHash    #-}
-{-# LANGUAGE TypeFamilies #-}
--- | Use @ByteArray@s containing one element for mutable references.
---
--- This is similar to @URef@s, but avoids the overhead of storing the length of
--- the @Vector@, which we statically know will always be 1. This allows it to
--- be a bit faster.
---
--- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.
-module Data.Mutable.PRef
-    ( -- * Types
-      PRef
-    , IOPRef
-      -- * Functions
-    , asPRef
-    , MutableRef (..)
-    ) where
-
-import Control.Monad            (liftM)
-import Data.Mutable.Class
-import Data.Primitive           (sizeOf)
-import Data.Primitive.ByteArray (MutableByteArray, newByteArray, readByteArray,
-                                 writeByteArray)
-import Data.Primitive.Types     (Prim)
-import GHC.Types                (Int (..))
-
--- | A primitive ByteArray reference, supporting any monad.
---
--- Since 0.2.0
-newtype PRef s a = PRef (MutableByteArray s)
-
--- |
--- Since 0.2.0
-asPRef :: PRef s a -> PRef s a
-asPRef x = x
-{-# INLINE asPRef #-}
-
--- | A primitive ByteArray IO reference.
-type IOPRef = PRef (PrimState IO)
-
-instance MutableContainer (PRef s a) where
-    type MCState (PRef s a) = s
-instance Prim a => MutableRef (PRef s a) where
-    type RefElement (PRef s a) = a
-
-    newRef x = do
-        ba <- newByteArray (sizeOf $! x)
-        writeByteArray ba 0 x
-        return $! PRef ba
-    {-# INLINE newRef #-}
-
-    readRef (PRef ba) = readByteArray ba 0
-    {-# INLINE readRef #-}
-
-    writeRef (PRef ba) = writeByteArray ba 0
-    {-# INLINE writeRef #-}
-
-    modifyRef (PRef ba) f = do
-        x <- readByteArray ba 0
-        writeByteArray ba 0 $! f x
-    {-# INLINE modifyRef #-}
-
-    modifyRef' = modifyRef
-    {-# INLINE modifyRef' #-}
diff --git a/Data/Mutable/SRef.hs b/Data/Mutable/SRef.hs
deleted file mode 100644
--- a/Data/Mutable/SRef.hs
+++ /dev/null
@@ -1,55 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
--- | Use 1-length mutable storable vectors for mutable references.
---
--- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.
-module Data.Mutable.SRef
-    ( -- * Types
-      SRef
-    , IOSRef
-      -- * Functions
-    , asSRef
-    , MutableRef (..)
-    ) where
-
-import           Data.Mutable.Class
-import Foreign.ForeignPtr
-import Foreign.Storable
-import Control.Monad.Primitive
-
--- | A storable vector reference, supporting any monad.
---
--- Since 0.2.0
-newtype SRef s a = SRef (ForeignPtr a)
-
--- |
--- Since 0.2.0
-asSRef :: SRef s a -> SRef s a
-asSRef x = x
-{-# INLINE asSRef #-}
-
--- | A storable IO vector reference.
-type IOSRef = SRef (PrimState IO)
-
-instance MutableContainer (SRef s a) where
-    type MCState (SRef s a) = s
-instance Storable a => MutableRef (SRef s a) where
-    type RefElement (SRef s a) = a
-
-    newRef x = unsafePrimToPrim $ do
-        fptr <- mallocForeignPtr
-        withForeignPtr fptr $ flip poke x
-        return $! SRef fptr
-    {-# INLINE newRef#-}
-
-    readRef (SRef fptr) = unsafePrimToPrim $ withForeignPtr fptr peek
-    {-# INLINE readRef #-}
-
-    writeRef (SRef fptr) x = unsafePrimToPrim $ withForeignPtr fptr $ flip poke x
-    {-# INLINE writeRef #-}
-
-    modifyRef (SRef fptr) f = unsafePrimToPrim $ withForeignPtr fptr $ \ptr ->
-        peek ptr >>= poke ptr . f
-    {-# INLINE modifyRef #-}
-
-    modifyRef' = modifyRef
-    {-# INLINE modifyRef' #-}
diff --git a/Data/Mutable/URef.hs b/Data/Mutable/URef.hs
deleted file mode 100644
--- a/Data/Mutable/URef.hs
+++ /dev/null
@@ -1,51 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
--- | Use 1-length mutable unboxed vectors for mutable references.
---
--- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.
-module Data.Mutable.URef
-    ( -- * Types
-      URef
-    , IOURef
-      -- * Functions
-    , asURef
-    , MutableRef (..)
-    ) where
-
-import           Control.Monad               (liftM)
-import           Data.Mutable.Class
-import qualified Data.Vector.Generic.Mutable as V
-import qualified Data.Vector.Unboxed.Mutable as VU
-
--- | An unboxed vector reference, supporting any monad.
---
--- Since 0.2.0
-newtype URef s a = URef (VU.MVector s a)
-
--- |
--- Since 0.2.0
-asURef :: URef s a -> URef s a
-asURef x = x
-{-# INLINE asURef #-}
-
--- | An unboxed IO vector reference.
-type IOURef = URef (PrimState IO)
-
-instance MutableContainer (URef s a) where
-    type MCState (URef s a) = s
-instance VU.Unbox a => MutableRef (URef s a) where
-    type RefElement (URef s a) = a
-
-    newRef = liftM URef . V.replicate 1
-    {-# INLINE newRef#-}
-
-    readRef (URef v) = V.unsafeRead v 0
-    {-# INLINE readRef #-}
-
-    writeRef (URef v) = V.unsafeWrite v 0
-    {-# INLINE writeRef #-}
-
-    modifyRef (URef v) f = V.unsafeRead v 0 >>= V.unsafeWrite v 0 . f
-    {-# INLINE modifyRef #-}
-
-    modifyRef' = modifyRef
-    {-# INLINE modifyRef' #-}
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -115,7 +115,7 @@
 additional data structures: double-ended queues and doubly-linked lists. The
 former is based around mutable vectors, and therefore as unboxed (`UDeque`),
 storable (`SDeque`), and boxed (`BDeque`) variants. Doubly-linked lists have no
-such variety, and are simply `DList`s.
+such variety, and are simply `DLList`s.
 
 For general purpose queue-like structures, `UDeque` or `SDeque` is likely to
 give you best performance. As usual, benchmark your own program to be certain,
@@ -174,6 +174,7 @@
 ### Deque benchmark
 
 ```
+benchmarking IORef [Int]
 time                 8.371 ms   (8.362 ms .. 8.382 ms)
                      1.000 R²   (1.000 R² .. 1.000 R²)
 mean                 8.386 ms   (8.378 ms .. 8.398 ms)
diff --git a/bench/deque.hs b/bench/deque.hs
--- a/bench/deque.hs
+++ b/bench/deque.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE TypeFamilies    #-}
 import Control.Monad
-import Criterion.Main
+import Gauge.Main
 import Data.Mutable
 import Data.Sequence      (Seq)
 
diff --git a/bench/ref.hs b/bench/ref.hs
--- a/bench/ref.hs
+++ b/bench/ref.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE TypeFamilies #-}
 import Control.Monad
-import Criterion.Main
+import Gauge.Main
 import Data.Mutable
 
 test :: (MCState c ~ PrimState IO, RefElement c ~ Int, MutableRef c)
diff --git a/mutable-containers.cabal b/mutable-containers.cabal
--- a/mutable-containers.cabal
+++ b/mutable-containers.cabal
@@ -1,69 +1,100 @@
-name:                mutable-containers
-version:             0.3.3
-synopsis:            Abstactions and concrete implementations of mutable containers
-description:         See docs and README at <http://www.stackage.org/package/mutable-containers>
-homepage:            https://github.com/snoyberg/mono-traversable
-license:             MIT
-license-file:        LICENSE
-author:              Michael Snoyman
-maintainer:          michael@fpcomplete.com
-category:            Data
-build-type:          Simple
-extra-source-files:  README.md ChangeLog.md
-cabal-version:       >=1.10
+-- This file has been generated from package.yaml by hpack version 0.20.0.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: 40dea8fdbd3dd312e239092feaa21012ad064fac2c05429d687759366016cfe7
 
+name:           mutable-containers
+version:        0.3.4
+synopsis:       Abstactions and concrete implementations of mutable containers
+description:    See docs and README at <http://www.stackage.org/package/mutable-containers>
+category:       Data
+homepage:       https://github.com/snoyberg/mono-traversable#readme
+bug-reports:    https://github.com/snoyberg/mono-traversable/issues
+author:         Michael Snoyman
+maintainer:     michael@fpcomplete.com
+license:        MIT
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+
+extra-source-files:
+    ChangeLog.md
+    README.md
+
+source-repository head
+  type: git
+  location: https://github.com/snoyberg/mono-traversable
+
 library
-  exposed-modules:     Data.Mutable
-  other-modules:       Data.Mutable.SRef
-                       Data.Mutable.Class
-                       Data.Mutable.URef
-                       Data.Mutable.PRef
-                       Data.Mutable.BRef
-                       Data.Mutable.DLList
-                       Data.Mutable.Deque
-  build-depends:       base >= 4.7 && < 5
-                     , primitive >= 0.5.2.1
-                     , containers
-                     , vector
-                     , mono-traversable
-                     , ghc-prim
-  default-language:    Haskell2010
-  ghc-options:         -O2
+  hs-source-dirs:
+      src
+  ghc-options: -O2
+  build-depends:
+      base >=4.9 && <5
+    , containers
+    , ghc-prim
+    , mono-traversable
+    , primitive >=0.5.2.1
+    , vector
+  exposed-modules:
+      Data.Mutable
+  other-modules:
+      Data.Mutable.BRef
+      Data.Mutable.Class
+      Data.Mutable.Deque
+      Data.Mutable.DLList
+      Data.Mutable.PRef
+      Data.Mutable.SRef
+      Data.Mutable.URef
+      Paths_mutable_containers
+  default-language: Haskell2010
 
 test-suite test
-  type:                exitcode-stdio-1.0
-  hs-source-dirs:      test
-  main-is:             Spec.hs
-  build-depends:       base
-                     , mutable-containers
-                     , hspec
-                     , QuickCheck
-                     , vector
-                     , primitive
-                     , containers
-  default-language:    Haskell2010
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  hs-source-dirs:
+      test
+  build-depends:
+      QuickCheck
+    , base >=4.9 && <5
+    , containers
+    , hspec
+    , mutable-containers
+    , primitive
+    , vector
+  other-modules:
+      Paths_mutable_containers
+  default-language: Haskell2010
 
 benchmark deque
-  type:                exitcode-stdio-1.0
-  hs-source-dirs:      bench
-  main-is:             deque.hs
-  build-depends:       base
-                     , mutable-containers
-                     , criterion
-                     , containers
-  ghc-options:         -Wall -O2 -rtsopts
-  default-language:    Haskell2010
+  type: exitcode-stdio-1.0
+  main-is: deque.hs
+  hs-source-dirs:
+      bench
+  ghc-options: -Wall -O2 -rtsopts
+  build-depends:
+      base >=4.9 && <5
+    , containers
+    , gauge
+    , mutable-containers
+    , vector
+  other-modules:
+      Paths_mutable_containers
+  default-language: Haskell2010
 
 benchmark ref
-  type:                exitcode-stdio-1.0
-  hs-source-dirs:      bench
-  main-is:             ref.hs
-  build-depends:       base
-                     , mutable-containers
-                     , criterion
-  ghc-options:         -Wall -O2 -rtsopts
-  default-language:    Haskell2010
-
-source-repository head
-  type:     git
-  location: https://github.com/snoyberg/mono-traversable.git
+  type: exitcode-stdio-1.0
+  main-is: ref.hs
+  hs-source-dirs:
+      bench
+  ghc-options: -Wall -O2 -rtsopts
+  build-depends:
+      base >=4.9 && <5
+    , containers
+    , gauge
+    , mutable-containers
+    , vector
+  other-modules:
+      Paths_mutable_containers
+  default-language: Haskell2010
diff --git a/src/Data/Mutable.hs b/src/Data/Mutable.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Mutable.hs
@@ -0,0 +1,68 @@
+-- | Classes and concrete implementations for mutable data structures.
+--
+-- For more information on the design of this library, see the README file,
+-- also available at <http://www.stackage.org/package/mutable-containers>.
+module Data.Mutable
+    ( -- * Data types
+      -- ** Single-cell mutable references
+      PRef
+    , IOPRef
+    , asPRef
+    , URef
+    , IOURef
+    , asURef
+    , SRef
+    , IOSRef
+    , asSRef
+    , BRef
+    , IOBRef
+    , asBRef
+      -- *** Standard re-exports
+    , IORef
+    , asIORef
+    , STRef
+    , asSTRef
+    , MutVar
+    , asMutVar
+      -- ** Collections/queues
+    , Deque
+    , UDeque
+    , asUDeque
+    , SDeque
+    , asSDeque
+    , BDeque
+    , asBDeque
+    , DLList
+    , asDLList
+      -- * Type classes
+    , MutableContainer (..)
+    , MutableRef (..)
+    , MutableAtomicRef (..)
+    , MutableCollection (..)
+    , MutablePushFront (..)
+    , MutablePushBack (..)
+    , MutablePopFront (..)
+    , MutablePopBack (..)
+      -- * Constraint kinds
+    , MutableQueue
+    , MutableStack
+    , MutableDeque
+      -- * Convenience re-exports
+    , PrimMonad
+    , PrimState
+    , RealWorld
+    , Prim
+    , Unbox
+    , Storable
+    ) where
+
+import Data.Mutable.Class
+import Data.Mutable.URef
+import Data.Mutable.SRef
+import Data.Mutable.PRef
+import Data.Mutable.BRef
+import Data.Mutable.Deque
+import Data.Mutable.DLList
+import Data.Vector.Unboxed (Unbox)
+import Data.Primitive (Prim)
+import Data.Vector.Storable (Storable)
diff --git a/src/Data/Mutable/BRef.hs b/src/Data/Mutable/BRef.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Mutable/BRef.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE TypeFamilies #-}
+-- | Use 1-length mutable boxed vectors for mutable references.
+--
+-- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.
+module Data.Mutable.BRef
+    ( -- * Types
+      BRef
+    , IOBRef
+      -- * Functions
+    , asBRef
+    , MutableRef (..)
+    ) where
+
+import           Control.Monad               (liftM)
+import           Data.Monoid                 (Monoid, mempty)
+import           Data.MonoTraversable        (Element)
+import           Data.Mutable.Class
+import           Data.Sequences              (IsSequence)
+import qualified Data.Vector.Generic.Mutable as V
+import qualified Data.Vector.Mutable         as VB
+
+-- | A boxed vector reference, supporting any monad.
+--
+-- Since 0.2.0
+newtype BRef s a = BRef (VB.MVector s a)
+
+-- |
+-- Since 0.2.0
+asBRef :: BRef s a -> BRef s a
+asBRef x = x
+{-# INLINE asBRef #-}
+
+-- | A boxed IO vector reference.
+type IOBRef = BRef (PrimState IO)
+
+instance MutableContainer (BRef s a) where
+    type MCState (BRef s a) = s
+instance MutableRef (BRef s a) where
+    type RefElement (BRef s a) = a
+
+    newRef = liftM BRef . V.replicate 1
+    {-# INLINE newRef#-}
+
+    readRef (BRef v) = V.unsafeRead v 0
+    {-# INLINE readRef #-}
+
+    writeRef (BRef v) = V.unsafeWrite v 0
+    {-# INLINE writeRef #-}
+
+    modifyRef (BRef v) f = V.unsafeRead v 0 >>= V.unsafeWrite v 0 . f
+    {-# INLINE modifyRef #-}
+
+    modifyRef' = modifyRef
+    {-# INLINE modifyRef' #-}
+
+instance Monoid w => MutableCollection (BRef s w) where
+    type CollElement (BRef s w) = Element w
+    newColl = newRef mempty
+    {-# INLINE newColl #-}
+instance IsSequence seq => MutablePushFront (BRef s seq) where
+    pushFront = pushFrontRef
+    {-# INLINE pushFront #-}
+instance IsSequence seq => MutablePushBack (BRef s seq) where
+    pushBack = pushBackRef
+    {-# INLINE pushBack #-}
+instance IsSequence seq => MutablePopFront (BRef s seq) where
+    popFront = popFrontRef
+    {-# INLINE popFront #-}
+instance IsSequence seq => MutablePopBack (BRef s seq) where
+    popBack = popBackRef
+    {-# INLINE popBack #-}
diff --git a/src/Data/Mutable/Class.hs b/src/Data/Mutable/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Mutable/Class.hs
@@ -0,0 +1,373 @@
+{-# LANGUAGE ConstraintKinds   #-}
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TypeFamilies      #-}
+-- | Various typeclasses for mutable containers.
+module Data.Mutable.Class
+    ( PrimMonad
+    , PrimState
+    , RealWorld
+    , MutableQueue
+    , MutableStack
+    , MutableDeque
+    , IORef
+    , asIORef
+    , STRef
+    , asSTRef
+    , MutVar
+    , asMutVar
+    , MutableContainer (..)
+    , MutableRef (..)
+    , MutableAtomicRef (..)
+    , MutableCollection (..)
+    , MutablePushFront (..)
+    , MutablePushBack (..)
+    , MutablePopFront (..)
+    , MutablePopBack (..)
+    , pushFrontRef
+    , pushBackRef
+    , popFrontRef
+    , popBackRef
+    ) where
+
+import           Control.Monad.Primitive
+import           Data.IORef
+import           Data.Monoid
+import           Data.MonoTraversable    (Element)
+import           Data.Primitive.MutVar
+import qualified Data.Sequences          as Seqs
+import           Data.STRef
+
+-- | The parent typeclass for all mutable containers.
+--
+-- Since 0.2.0
+class MutableContainer c where
+    -- | Associated type giving the primitive state token for the given
+    -- container, much like 'PrimState' from primitive.
+    --
+    -- Since 0.2.0
+    type MCState c
+
+instance MutableContainer (IORef a) where
+    type MCState (IORef a) = PrimState IO
+instance MutableContainer (STRef s a) where
+    type MCState (STRef s a) = s
+instance MutableContainer (MutVar s a) where
+    type MCState (MutVar s a) = s
+
+-- | Typeclass for single-cell mutable references.
+--
+-- Since 0.2.0
+class MutableContainer c => MutableRef c where
+    -- | Associated type giving the type of the value inside the mutable
+    -- reference.
+    --
+    -- Since 0.2.0
+    type RefElement c
+
+    -- | Create a new mutable reference with the given value.
+    --
+    -- Since 0.2.0
+    newRef :: (PrimMonad m, PrimState m ~ MCState c)
+           => RefElement c
+           -> m c
+
+    -- | Read the current value in the mutable reference.
+    --
+    -- Since 0.2.0
+    readRef :: (PrimMonad m, PrimState m ~ MCState c)
+            => c
+            -> m (RefElement c)
+
+    -- | Write a new value to the mutable reference.
+    --
+    -- Since 0.2.0
+    writeRef :: (PrimMonad m, PrimState m ~ MCState c)
+             => c
+             -> RefElement c
+             -> m ()
+
+    -- | Modify the value in the mutable reference, without necessarily forcing the result.
+    --
+    -- Note: some implementations /will/ force the result, in particular
+    -- @PRef@, @SRef@, and @URef@.
+    --
+    -- Since 0.2.0
+    modifyRef :: (PrimMonad m, PrimState m ~ MCState c)
+              => c
+              -> (RefElement c -> RefElement c)
+              -> m ()
+
+    -- | Modify the value in the mutable reference, forcing the result.
+    --
+    -- Since 0.2.0
+    modifyRef' :: (PrimMonad m, PrimState m ~ MCState c)
+               => c
+               -> (RefElement c -> RefElement c)
+               -> m ()
+
+instance MutableRef (IORef a) where
+    type RefElement (IORef a) = a
+    newRef = primToPrim . newIORef
+    {-# INLINE newRef #-}
+    readRef = primToPrim . readIORef
+    {-# INLINE readRef #-}
+    writeRef c = primToPrim . writeIORef c
+    {-# INLINE writeRef #-}
+    modifyRef c = primToPrim . modifyIORef c
+    {-# INLINE modifyRef #-}
+    modifyRef' c = primToPrim . modifyIORef' c
+    {-# INLINE modifyRef' #-}
+instance MutableRef (STRef s a) where
+    type RefElement (STRef s a) = a
+    newRef = primToPrim . newSTRef
+    {-# INLINE newRef #-}
+    readRef = primToPrim . readSTRef
+    {-# INLINE readRef #-}
+    writeRef c = primToPrim . writeSTRef c
+    {-# INLINE writeRef #-}
+    modifyRef c = primToPrim . modifySTRef c
+    {-# INLINE modifyRef #-}
+    modifyRef' c = primToPrim . modifySTRef' c
+    {-# INLINE modifyRef' #-}
+instance MutableRef (MutVar s a) where
+    type RefElement (MutVar s a) = a
+    newRef = newMutVar
+    {-# INLINE newRef #-}
+    readRef = readMutVar
+    {-# INLINE readRef #-}
+    writeRef = writeMutVar
+    {-# INLINE writeRef #-}
+    modifyRef = modifyMutVar
+    {-# INLINE modifyRef #-}
+    modifyRef' = modifyMutVar'
+    {-# INLINE modifyRef' #-}
+
+-- | @MutableRef@s that provide for atomic modifications of their contents.
+--
+-- Since 0.2.0
+class MutableRef c => MutableAtomicRef c where
+    -- | Modify the value without necessarily forcing the result.
+    --
+    -- Since 0.2.0
+    atomicModifyRef
+        :: (PrimMonad m, PrimState m ~ MCState c)
+        => c
+        -> (RefElement c -> (RefElement c, a))
+        -> m a
+
+    -- | Modify the value, forcing the result.
+    --
+    -- Since 0.2.0
+    atomicModifyRef'
+        :: (PrimMonad m, PrimState m ~ MCState c)
+        => c
+        -> (RefElement c -> (RefElement c, a))
+        -> m a
+instance MutableAtomicRef (IORef a) where
+    atomicModifyRef c = primToPrim . atomicModifyIORef c
+    {-# INLINE atomicModifyRef #-}
+    atomicModifyRef' c = primToPrim . atomicModifyIORef' c
+    {-# INLINE atomicModifyRef' #-}
+instance MutableAtomicRef (MutVar s a) where
+    atomicModifyRef = atomicModifyMutVar
+    {-# INLINE atomicModifyRef #-}
+    atomicModifyRef' = atomicModifyMutVar'
+    {-# INLINE atomicModifyRef' #-}
+
+-- | Containers which contain 0 or more values.
+--
+-- Since 0.2.0
+class MutableContainer c => MutableCollection c where
+    -- | The type of each value in the collection.
+    --
+    -- Since 0.2.0
+    type CollElement c
+
+    -- | Create a new, empty collection.
+    --
+    -- Since 0.2.0
+    newColl :: (PrimMonad m, PrimState m ~ MCState c)
+            => m c
+instance Data.Monoid.Monoid w => MutableCollection (IORef w) where
+    type CollElement (IORef w) = Element w
+    newColl = newRef mempty
+    {-# INLINE newColl #-}
+instance Monoid w => MutableCollection (STRef s w) where
+    type CollElement (STRef s w) = Element w
+    newColl = newRef mempty
+    {-# INLINE newColl #-}
+instance Monoid w => MutableCollection (MutVar s w) where
+    type CollElement (MutVar s w) = Element w
+    newColl = newRef mempty
+    {-# INLINE newColl #-}
+
+-- | Take a value from the front of the collection, if available.
+--
+-- Since 0.2.0
+class MutableCollection c => MutablePopFront c where
+    -- | Take a value from the front of the collection, if available.
+    --
+    -- Since 0.2.0
+    popFront :: (PrimMonad m, PrimState m ~ MCState c)
+             => c
+             -> m (Maybe (CollElement c))
+popFrontRef
+    :: ( PrimMonad m
+       , PrimState m ~ MCState c
+       , MutableRef c
+       , CollElement c ~ Element (RefElement c)
+       , Seqs.IsSequence (RefElement c)
+       )
+    => c
+    -> m (Maybe (CollElement c))
+popFrontRef c = do
+    l <- readRef c
+    case Seqs.uncons l of
+        Nothing -> return Nothing
+        Just (x, xs) -> do
+            writeRef c xs
+            return (Just x)
+{-# INLINE popFrontRef #-}
+instance Seqs.IsSequence a => MutablePopFront (IORef a) where
+    popFront = popFrontRef
+    {-# INLINE popFront #-}
+instance Seqs.IsSequence a => MutablePopFront (STRef s a) where
+    popFront = popFrontRef
+    {-# INLINE popFront #-}
+instance Seqs.IsSequence a => MutablePopFront (MutVar s a) where
+    popFront = popFrontRef
+    {-# INLINE popFront #-}
+
+-- | Place a value at the front of the collection.
+--
+-- Since 0.2.0
+class MutableCollection c => MutablePushFront c where
+    -- | Place a value at the front of the collection.
+    --
+    -- Since 0.2.0
+    pushFront :: (PrimMonad m, PrimState m ~ MCState c)
+              => c
+              -> CollElement c
+              -> m ()
+pushFrontRef
+    :: ( PrimMonad m
+       , PrimState m ~ MCState c
+       , MutableRef c
+       , CollElement c ~ Element (RefElement c)
+       , Seqs.IsSequence (RefElement c)
+       )
+    => c
+    -> CollElement c
+    -> m ()
+pushFrontRef c e = modifyRef' c (Seqs.cons e)
+{-# INLINE pushFrontRef #-}
+instance Seqs.IsSequence a => MutablePushFront (IORef a) where
+    pushFront = pushFrontRef
+    {-# INLINE pushFront #-}
+instance Seqs.IsSequence a => MutablePushFront (STRef s a) where
+    pushFront = pushFrontRef
+    {-# INLINE pushFront #-}
+instance Seqs.IsSequence a => MutablePushFront (MutVar s a) where
+    pushFront = pushFrontRef
+    {-# INLINE pushFront #-}
+
+-- | Take a value from the back of the collection, if available.
+--
+-- Since 0.2.0
+class MutableCollection c => MutablePopBack c where
+    -- | Take a value from the back of the collection, if available.
+    --
+    -- Since 0.2.0
+    popBack :: (PrimMonad m, PrimState m ~ MCState c)
+            => c
+            -> m (Maybe (CollElement c))
+popBackRef
+    :: ( PrimMonad m
+       , PrimState m ~ MCState c
+       , MutableRef c
+       , CollElement c ~ Element (RefElement c)
+       , Seqs.IsSequence (RefElement c)
+       )
+    => c
+    -> m (Maybe (CollElement c))
+popBackRef c = do
+    l <- readRef c
+    case Seqs.unsnoc l of
+        Nothing -> return Nothing
+        Just (xs, x) -> do
+            writeRef c xs
+            return (Just x)
+{-# INLINE popBackRef #-}
+instance Seqs.IsSequence a => MutablePopBack (IORef a) where
+    popBack = popBackRef
+    {-# INLINE popBack #-}
+instance Seqs.IsSequence a => MutablePopBack (STRef s a) where
+    popBack = popBackRef
+    {-# INLINE popBack #-}
+instance Seqs.IsSequence a => MutablePopBack (MutVar s a) where
+    popBack = popBackRef
+    {-# INLINE popBack #-}
+
+-- | Place a value at the back of the collection.
+--
+-- Since 0.2.0
+class MutableCollection c => MutablePushBack c where
+    -- | Place a value at the back of the collection.
+    --
+    -- Since 0.2.0
+    pushBack :: (PrimMonad m, PrimState m ~ MCState c)
+             => c
+             -> CollElement c
+             -> m ()
+pushBackRef
+    :: ( PrimMonad m
+       , PrimState m ~ MCState c
+       , MutableRef c
+       , CollElement c ~ Element (RefElement c)
+       , Seqs.IsSequence (RefElement c)
+       )
+    => c
+    -> CollElement c
+    -> m ()
+pushBackRef c e = modifyRef' c (`Seqs.snoc` e)
+{-# INLINE pushBackRef #-}
+instance Seqs.IsSequence a => MutablePushBack (IORef a) where
+    pushBack = pushBackRef
+    {-# INLINE pushBack #-}
+instance Seqs.IsSequence a => MutablePushBack (STRef s a) where
+    pushBack = pushBackRef
+    {-# INLINE pushBack #-}
+instance Seqs.IsSequence a => MutablePushBack (MutVar s a) where
+    pushBack = pushBackRef
+    {-# INLINE pushBack #-}
+
+-- | Collections which allow pushing and popping at the front (aka FIFOs).
+--
+-- Since 0.2.0
+type MutableQueue c = (MutablePopFront c, MutablePushBack c)
+
+-- | Collections which allow pushing at the back and popping at the front (aka FILOs).
+--
+-- Since 0.2.0
+type MutableStack c = (MutablePopFront c, MutablePushFront c)
+
+-- | Collections which allow pushing and popping at the front and back.
+--
+-- Since 0.2.0
+type MutableDeque c = (MutableQueue c, MutablePushFront c, MutablePopBack c)
+
+-- |
+-- Since 0.2.0
+asIORef :: IORef a -> IORef a
+asIORef = id
+
+-- |
+-- Since 0.2.0
+asSTRef :: STRef s a -> STRef s a
+asSTRef = id
+
+-- |
+-- Since 0.2.0
+asMutVar :: MutVar s a -> MutVar s a
+asMutVar = id
diff --git a/src/Data/Mutable/DLList.hs b/src/Data/Mutable/DLList.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Mutable/DLList.hs
@@ -0,0 +1,101 @@
+{-# LANGUAGE TypeFamilies #-}
+-- | Doubly-linked list
+module Data.Mutable.DLList
+    ( DLList
+    , asDLList
+    , module Data.Mutable.Class
+    ) where
+
+import Data.Mutable.Class
+
+data Node s a = Node
+    a
+    (MutVar s (Maybe (Node s a))) -- previous
+    (MutVar s (Maybe (Node s a))) -- next
+
+-- | A doubly-linked list.
+--
+-- Since 0.3.0
+data DLList s a = DLList (MutVar s (Maybe (Node s a))) (MutVar s (Maybe (Node s a)))
+
+-- |
+-- Since 0.2.0
+asDLList :: DLList s a -> DLList s a
+asDLList = id
+{-# INLINE asDLList #-}
+
+instance MutableContainer (DLList s a) where
+    type MCState (DLList s a) = s
+instance MutableCollection (DLList s a) where
+    type CollElement (DLList s a) = a
+    newColl = do
+        x <- newRef $! Nothing
+        y <- newRef $! Nothing
+        return $! DLList x y
+    {-# INLINE newColl #-}
+instance MutablePopFront (DLList s a) where
+    popFront (DLList frontRef backRef) = do
+        mfront <- readRef frontRef
+        case mfront of
+            Nothing -> return Nothing
+            Just (Node val _ nextRef) -> do
+                mnext <- readRef nextRef
+                case mnext of
+                    Nothing -> do
+                        writeRef frontRef $! Nothing
+                        writeRef backRef $! Nothing
+                    Just next@(Node _ prevRef _) -> do
+                        writeRef prevRef $! Nothing
+                        writeRef frontRef $! Just next
+                return $ Just val
+    {-# INLINE popFront #-}
+instance MutablePopBack (DLList s a) where
+    popBack (DLList frontRef backRef) = do
+        mback <- readRef backRef
+        case mback of
+            Nothing -> return Nothing
+            Just (Node val prevRef _) -> do
+                mprev <- readRef prevRef
+                case mprev of
+                    Nothing -> do
+                        writeRef frontRef $! Nothing
+                        writeRef backRef $! Nothing
+                    Just prev@(Node _ _ nextRef) -> do
+                        writeRef nextRef $! Nothing
+                        writeRef backRef (Just prev)
+                return $ Just val
+    {-# INLINE popBack #-}
+instance MutablePushFront (DLList s a) where
+    pushFront (DLList frontRef backRef) val = do
+        mfront <- readRef frontRef
+        case mfront of
+            Nothing -> do
+                prevRef <- newRef $! Nothing
+                nextRef <- newRef $! Nothing
+                let node = Just $ Node val prevRef nextRef
+                writeRef frontRef node
+                writeRef backRef node
+            Just front@(Node _ prevRef _) -> do
+                prevRefNew <- newRef $! Nothing
+                nextRef <- newRef $ Just front
+                let node = Just $ Node val prevRefNew nextRef
+                writeRef prevRef node
+                writeRef frontRef node
+    {-# INLINE pushFront #-}
+instance MutablePushBack (DLList s a) where
+    pushBack (DLList frontRef backRef) val = do
+        mback <- readRef backRef
+        case mback of
+            Nothing -> do
+                prevRef <- newRef $! Nothing
+                nextRef <- newRef $! Nothing
+                let node = Just $! Node val prevRef nextRef
+                writeRef frontRef $! node
+                writeRef backRef $! node
+            Just back@(Node _ _ nextRef) -> do
+                nextRefNew <- newRef $! Nothing
+                prevRef <- newRef $! Just back
+                let node = Just $! Node val prevRef nextRefNew
+                writeRef nextRef $! node
+                writeRef backRef $! node
+    {-# INLINE pushBack #-}
diff --git a/src/Data/Mutable/Deque.hs b/src/Data/Mutable/Deque.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Mutable/Deque.hs
@@ -0,0 +1,152 @@
+{-# LANGUAGE TypeFamilies #-}
+module Data.Mutable.Deque
+    ( Deque
+    , UDeque
+    , asUDeque
+    , SDeque
+    , asSDeque
+    , BDeque
+    , asBDeque
+    , module Data.Mutable.Class
+    ) where
+
+import           Control.Exception            (assert)
+import           Control.Monad                (liftM)
+import           Data.Mutable.Class
+import qualified Data.Vector.Generic.Mutable  as V
+import qualified Data.Vector.Mutable          as B
+import qualified Data.Vector.Storable.Mutable as S
+import qualified Data.Vector.Unboxed.Mutable  as U
+
+data DequeState v s a = DequeState
+    (v s a)
+    {-# UNPACK #-} !Int -- start
+    {-# UNPACK #-} !Int -- size
+
+-- | A double-ended queue supporting any underlying vector type and any monad.
+--
+-- This implements a circular double-ended queue with exponential growth.
+--
+-- Since 0.2.0
+newtype Deque v s a = Deque (MutVar s (DequeState v s a))
+
+-- | A 'Deque' specialized to unboxed vectors.
+--
+-- Since 0.2.0
+type UDeque = Deque U.MVector
+
+-- | A 'Deque' specialized to storable vectors.
+--
+-- Since 0.2.0
+type SDeque = Deque S.MVector
+
+-- | A 'Deque' specialized to boxed vectors.
+--
+-- Since 0.2.0
+type BDeque = Deque B.MVector
+
+-- |
+-- Since 0.2.0
+asUDeque :: UDeque s a -> UDeque s a
+asUDeque = id
+
+-- |
+-- Since 0.2.0
+asSDeque :: SDeque s a -> SDeque s a
+asSDeque = id
+
+-- |
+-- Since 0.2.0
+asBDeque :: BDeque s a -> BDeque s a
+asBDeque = id
+
+instance MutableContainer (Deque v s a) where
+    type MCState (Deque v s a) = s
+instance V.MVector v a => MutableCollection (Deque v s a) where
+    type CollElement (Deque v s a) = a
+    newColl = do
+        v <- V.new baseSize
+        liftM Deque $ newRef (DequeState v 0 0)
+      where
+        baseSize = 32
+    {-# INLINE newColl #-}
+instance V.MVector v a => MutablePopFront (Deque v s a) where
+    popFront (Deque var) = do
+        DequeState v start size <- readRef var
+        if size == 0
+            then return Nothing
+            else do
+                x <- V.unsafeRead v start
+                let start' = start + 1
+                    start''
+                        | start' >= V.length v = 0
+                        | otherwise = start'
+                writeRef var $! DequeState v start'' (size - 1)
+                return $! Just x
+    {-# INLINE popFront #-}
+instance V.MVector v a => MutablePopBack (Deque v s a) where
+    popBack (Deque var) = do
+        DequeState v start size <- readRef var
+        if size == 0
+            then return Nothing
+            else do
+                let size' = size - 1
+                    end = start + size'
+                    end'
+                        | end >= V.length v = end - V.length v
+                        | otherwise = end
+                x <- V.unsafeRead v end'
+                writeRef var $! DequeState v start size'
+                return $! Just x
+    {-# INLINE popBack #-}
+instance V.MVector v a => MutablePushFront (Deque v s a) where
+    pushFront (Deque var) x = do
+        DequeState v start size <- readRef var
+        inner v start size
+      where
+        inner v start size = do
+            if size >= V.length v
+                then newVector v start size inner
+                else do
+                    let size' = size + 1
+                        start' = (start - 1) `rem` V.length v
+                        start''
+                            | start' < 0 = V.length v + start'
+                            | otherwise = start'
+                    V.unsafeWrite v start'' x
+                    writeRef var $! DequeState v start'' size'
+    {-# INLINE pushFront #-}
+instance V.MVector v a => MutablePushBack (Deque v s a) where
+    pushBack (Deque var) x = do
+        DequeState v start size <- readRef var
+        inner v start size
+      where
+        inner v start size = do
+            if size >= V.length v
+                then newVector v start size inner
+                else do
+                    let end = start + size
+                        end'
+                            | end >= V.length v = end - V.length v
+                            | otherwise = end
+                    V.unsafeWrite v end' x
+                    writeRef var $! DequeState v start (size + 1)
+    {-# INLINE pushBack #-}
+
+newVector :: (PrimMonad m, V.MVector v a)
+          => v (PrimState m) a
+          -> Int
+          -> Int
+          -> (v (PrimState m) a -> Int -> Int -> m b)
+          -> m b
+newVector v size2 sizeOrig f = assert (sizeOrig == V.length v) $ do
+    v' <- V.unsafeNew (V.length v * 2)
+    let size1 = V.length v - size2
+    V.unsafeCopy
+        (V.unsafeTake size1 v')
+        (V.unsafeSlice size2 size1 v)
+    V.unsafeCopy
+        (V.unsafeSlice size1 size2 v')
+        (V.unsafeTake size2 v)
+    f v' 0 sizeOrig
+{-# INLINE newVector #-}
diff --git a/src/Data/Mutable/PRef.hs b/src/Data/Mutable/PRef.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Mutable/PRef.hs
@@ -0,0 +1,62 @@
+{-# LANGUAGE MagicHash    #-}
+{-# LANGUAGE TypeFamilies #-}
+-- | Use @ByteArray@s containing one element for mutable references.
+--
+-- This is similar to @URef@s, but avoids the overhead of storing the length of
+-- the @Vector@, which we statically know will always be 1. This allows it to
+-- be a bit faster.
+--
+-- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.
+module Data.Mutable.PRef
+    ( -- * Types
+      PRef
+    , IOPRef
+      -- * Functions
+    , asPRef
+    , MutableRef (..)
+    ) where
+
+import Data.Mutable.Class
+import Data.Primitive           (sizeOf)
+import Data.Primitive.ByteArray (MutableByteArray, newByteArray, readByteArray,
+                                 writeByteArray)
+import Data.Primitive.Types     (Prim)
+
+-- | A primitive ByteArray reference, supporting any monad.
+--
+-- Since 0.2.0
+newtype PRef s a = PRef (MutableByteArray s)
+
+-- |
+-- Since 0.2.0
+asPRef :: PRef s a -> PRef s a
+asPRef x = x
+{-# INLINE asPRef #-}
+
+-- | A primitive ByteArray IO reference.
+type IOPRef = PRef (PrimState IO)
+
+instance MutableContainer (PRef s a) where
+    type MCState (PRef s a) = s
+instance Prim a => MutableRef (PRef s a) where
+    type RefElement (PRef s a) = a
+
+    newRef x = do
+        ba <- newByteArray (sizeOf $! x)
+        writeByteArray ba 0 x
+        return $! PRef ba
+    {-# INLINE newRef #-}
+
+    readRef (PRef ba) = readByteArray ba 0
+    {-# INLINE readRef #-}
+
+    writeRef (PRef ba) = writeByteArray ba 0
+    {-# INLINE writeRef #-}
+
+    modifyRef (PRef ba) f = do
+        x <- readByteArray ba 0
+        writeByteArray ba 0 $! f x
+    {-# INLINE modifyRef #-}
+
+    modifyRef' = modifyRef
+    {-# INLINE modifyRef' #-}
diff --git a/src/Data/Mutable/SRef.hs b/src/Data/Mutable/SRef.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Mutable/SRef.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE TypeFamilies #-}
+-- | Use 1-length mutable storable vectors for mutable references.
+--
+-- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.
+module Data.Mutable.SRef
+    ( -- * Types
+      SRef
+    , IOSRef
+      -- * Functions
+    , asSRef
+    , MutableRef (..)
+    ) where
+
+import           Data.Mutable.Class
+import Foreign.ForeignPtr
+import Foreign.Storable
+import Control.Monad.Primitive
+
+-- | A storable vector reference, supporting any monad.
+--
+-- Since 0.2.0
+newtype SRef s a = SRef (ForeignPtr a)
+
+-- |
+-- Since 0.2.0
+asSRef :: SRef s a -> SRef s a
+asSRef x = x
+{-# INLINE asSRef #-}
+
+-- | A storable IO vector reference.
+type IOSRef = SRef (PrimState IO)
+
+instance MutableContainer (SRef s a) where
+    type MCState (SRef s a) = s
+instance Storable a => MutableRef (SRef s a) where
+    type RefElement (SRef s a) = a
+
+    newRef x = unsafePrimToPrim $ do
+        fptr <- mallocForeignPtr
+        withForeignPtr fptr $ flip poke x
+        return $! SRef fptr
+    {-# INLINE newRef#-}
+
+    readRef (SRef fptr) = unsafePrimToPrim $ withForeignPtr fptr peek
+    {-# INLINE readRef #-}
+
+    writeRef (SRef fptr) x = unsafePrimToPrim $ withForeignPtr fptr $ flip poke x
+    {-# INLINE writeRef #-}
+
+    modifyRef (SRef fptr) f = unsafePrimToPrim $ withForeignPtr fptr $ \ptr ->
+        peek ptr >>= poke ptr . f
+    {-# INLINE modifyRef #-}
+
+    modifyRef' = modifyRef
+    {-# INLINE modifyRef' #-}
diff --git a/src/Data/Mutable/URef.hs b/src/Data/Mutable/URef.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Mutable/URef.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE TypeFamilies #-}
+-- | Use 1-length mutable unboxed vectors for mutable references.
+--
+-- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.
+module Data.Mutable.URef
+    ( -- * Types
+      URef
+    , IOURef
+      -- * Functions
+    , asURef
+    , MutableRef (..)
+    ) where
+
+import           Control.Monad               (liftM)
+import           Data.Mutable.Class
+import qualified Data.Vector.Generic.Mutable as V
+import qualified Data.Vector.Unboxed.Mutable as VU
+
+-- | An unboxed vector reference, supporting any monad.
+--
+-- Since 0.2.0
+newtype URef s a = URef (VU.MVector s a)
+
+-- |
+-- Since 0.2.0
+asURef :: URef s a -> URef s a
+asURef x = x
+{-# INLINE asURef #-}
+
+-- | An unboxed IO vector reference.
+type IOURef = URef (PrimState IO)
+
+instance MutableContainer (URef s a) where
+    type MCState (URef s a) = s
+instance VU.Unbox a => MutableRef (URef s a) where
+    type RefElement (URef s a) = a
+
+    newRef = liftM URef . V.replicate 1
+    {-# INLINE newRef#-}
+
+    readRef (URef v) = V.unsafeRead v 0
+    {-# INLINE readRef #-}
+
+    writeRef (URef v) = V.unsafeWrite v 0
+    {-# INLINE writeRef #-}
+
+    modifyRef (URef v) f = V.unsafeRead v 0 >>= V.unsafeWrite v 0 . f
+    {-# INLINE modifyRef #-}
+
+    modifyRef' = modifyRef
+    {-# INLINE modifyRef' #-}
