diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+## 0.1.0.0
+
+* Initial release
diff --git a/Control/Monad/Trans/RWS/Ref.hs b/Control/Monad/Trans/RWS/Ref.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Trans/RWS/Ref.hs
@@ -0,0 +1,212 @@
+{-# LANGUAGE DeriveFunctor         #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE UndecidableInstances  #-}
+-- | An implementation of @RWST@ built on top of mutable references,
+-- providing a proper monad morphism.
+--
+-- An additional advantage of this transformer over the standard @RWST@
+-- transformers in the transformers package is that it does not have space
+-- leaks in the writer component. For more information, see
+-- <https://mail.haskell.org/pipermail/libraries/2012-October/018599.html>.
+module Control.Monad.Trans.RWS.Ref
+    ( RWSRefT
+    , runRWSRefT
+    , runRWSIORefT
+    , runRWSSTRefT
+    , module Control.Monad.RWS.Class
+    ) where
+
+import           Control.Applicative         (Applicative (..))
+import           Control.Monad               (ap, liftM)
+import           Control.Monad.Catch         (MonadCatch (..), MonadMask (..),
+                                              MonadThrow (..))
+import           Control.Monad.IO.Class      (MonadIO (..))
+import           Control.Monad.RWS.Class
+import           Control.Monad.Trans.Control (defaultLiftBaseWith,
+                                              defaultRestoreM)
+import           Control.Monad.Trans.Unlift
+import           Data.Monoid                 (Monoid, mappend, mempty)
+import           Data.Mutable                (IORef, MCState, MutableRef,
+                                              PrimMonad, PrimState, RealWorld,
+                                              RefElement, STRef, modifyRef',
+                                              newRef, readRef, writeRef)
+
+-- |
+--
+-- Since 0.1.0
+newtype RWSRefT refw refs r w s m a = RWSRefT
+    { unRWSRefT :: r -> refw w -> refs s -> m a
+    }
+    deriving Functor
+
+-- |
+--
+-- Since 0.1.0
+runRWSRefT
+    :: ( Monad m
+       , w ~ RefElement (refw w)
+       , s ~ RefElement (refs s)
+       , MCState (refw w) ~ PrimState b
+       , MCState (refs s) ~ PrimState b
+       , MonadBase b m
+       , MutableRef (refw w)
+       , MutableRef (refs s)
+       , PrimMonad b
+       , Monoid w
+       )
+    => RWSRefT refw refs r w s m a
+    -> r
+    -> s
+    -> m (a, s, w)
+runRWSRefT (RWSRefT f) r s0 = do
+    (refw, refs) <- liftBase $ (,) `liftM` newRef mempty `ap` newRef s0
+    a <- f r refw refs
+    (w, s) <- liftBase $ (,) `liftM` readRef refw `ap` readRef refs
+    return (a, s, w)
+{-# INLINEABLE runRWSRefT #-}
+
+-- |
+--
+-- Since 0.1.0
+runRWSIORefT
+    :: ( Monad m
+       , RealWorld ~ PrimState b
+       , MonadBase b m
+       , PrimMonad b
+       , Monoid w
+       )
+    => RWSRefT IORef IORef r w s m a
+    -> r
+    -> s
+    -> m (a, s, w)
+runRWSIORefT = runRWSRefT
+{-# INLINE runRWSIORefT #-}
+
+-- |
+--
+-- Since 0.1.0
+runRWSSTRefT
+    :: ( Monad m
+       , ps ~ PrimState b
+       , MonadBase b m
+       , PrimMonad b
+       , Monoid w
+       )
+    => RWSRefT (STRef ps) (STRef ps) r w s m a
+    -> r
+    -> s
+    -> m (a, s, w)
+runRWSSTRefT = runRWSRefT
+{-# INLINE runRWSSTRefT #-}
+
+instance Applicative m => Applicative (RWSRefT refw refs r w s m) where
+    pure m = RWSRefT $ \_ _ _ -> pure m
+    {-# INLINE pure #-}
+    RWSRefT f <*> RWSRefT g = RWSRefT $ \x y z -> f x y z <*> g x y z
+    {-# INLINE (<*>) #-}
+instance Monad m => Monad (RWSRefT refw refs r w s m) where
+    return m = RWSRefT $ \_ _ _ -> return m
+    {-# INLINE return #-}
+    RWSRefT f >>= g = RWSRefT $ \x y z -> do
+        a <- f x y z
+        unRWSRefT (g a) x y z
+    {-# INLINE (>>=) #-}
+
+instance Monad m => MonadReader r (RWSRefT refw refs r w s m) where
+    ask = RWSRefT $ \r _ _ -> return r
+    {-# INLINE ask #-}
+    local f (RWSRefT g) = RWSRefT $ \r w s -> g (f r) w s
+instance ( MCState (refw w) ~ PrimState b
+         , Monad m
+         , w ~ RefElement (refw w)
+         , MutableRef (refw w)
+         , PrimMonad b
+         , MonadBase b m
+         , Monoid w
+         )
+  => MonadWriter w (RWSRefT refw refs r w s m) where
+    writer (a, w) = RWSRefT $ \_ ref _ ->
+        liftBase $ modifyRef' ref (`mappend` w) >> return a
+    {-# INLINE writer #-}
+    tell w = RWSRefT $ \_ ref _ -> liftBase $ modifyRef' ref (`mappend` w)
+    {-# INLINE tell #-}
+    listen (RWSRefT f) = RWSRefT $ \r _ s -> do
+        ref <- liftBase (newRef mempty)
+        a <- f r ref s
+        w <- liftBase (readRef ref)
+        return (a, w)
+    {-# INLINEABLE listen #-}
+    pass (RWSRefT f) = RWSRefT $ \r ref s -> do
+        (a, g) <- f r ref s
+        liftBase $ modifyRef' ref g
+        return a
+    {-# INLINEABLE pass #-}
+instance ( MCState (refs s) ~ PrimState b
+         , Monad m
+         , s ~ RefElement (refs s)
+         , MutableRef (refs s)
+         , PrimMonad b
+         , MonadBase b m
+         )
+  => MonadState s (RWSRefT refw refs r w s m) where
+    get = RWSRefT $ \_ _ -> liftBase . readRef
+    {-# INLINE get #-}
+    put x = seq x $ RWSRefT $ \_ _ -> liftBase . (`writeRef` x)
+    {-# INLINE put #-}
+instance ( MCState (refw w) ~ PrimState b
+         , MCState (refs s) ~ PrimState b
+         , Monad m
+         , w ~ RefElement (refw w)
+         , s ~ RefElement (refs s)
+         , MutableRef (refw w)
+         , MutableRef (refs s)
+         , PrimMonad b
+         , MonadBase b m
+         , Monoid w
+         )
+  => MonadRWS r w s (RWSRefT refw refs r w s m)
+
+instance MonadTrans (RWSRefT refw refs r w s) where
+    lift f = RWSRefT $ \_ _ _ -> f
+    {-# INLINE lift #-}
+instance MonadIO m => MonadIO (RWSRefT refw refs r w s m) where
+    liftIO = lift . liftIO
+    {-# INLINE liftIO #-}
+instance MonadBase b m => MonadBase b (RWSRefT refw refs r w s m) where
+    liftBase = lift . liftBase
+    {-# INLINE liftBase #-}
+
+instance MonadTransControl (RWSRefT refw refs r w s) where
+    type StT (RWSRefT refw refs r w s) a = a
+    liftWith f = RWSRefT $ \r w s -> f $ \t -> unRWSRefT t r w s
+    restoreT f = RWSRefT $ \_ _ _ -> f
+    {-# INLINABLE liftWith #-}
+    {-# INLINABLE restoreT #-}
+
+instance MonadBaseControl b m => MonadBaseControl b (RWSRefT refw refs r w s m) where
+    type StM (RWSRefT refw refs r w s m) a = StM m a
+    liftBaseWith = defaultLiftBaseWith
+    restoreM = defaultRestoreM
+    {-# INLINE liftBaseWith #-}
+    {-# INLINE restoreM #-}
+
+instance MonadThrow m => MonadThrow (RWSRefT refw refs r w s m) where
+    throwM = lift . throwM
+    {-# INLINE throwM #-}
+instance MonadCatch m => MonadCatch (RWSRefT refw refs r w s m) where
+    catch (RWSRefT f) g = RWSRefT $ \e w s -> catch (f e w s)
+        ((\m -> unRWSRefT m e w s) . g)
+
+instance MonadMask m => MonadMask (RWSRefT refw refs r w s m) where
+  mask a = RWSRefT $ \e w s -> mask $ \u -> unRWSRefT (a $ q u) e w s
+    where q :: (m a -> m a) -> RWSRefT refw refs r w s m a -> RWSRefT refw refs r w s m a
+          q u (RWSRefT b) = RWSRefT (\r w s -> u (b r w s))
+  {-# INLINE mask #-}
+  uninterruptibleMask a =
+    RWSRefT $ \e w s -> uninterruptibleMask $ \u -> unRWSRefT (a $ q u) e w s
+      where q :: (m a -> m a) -> RWSRefT refw refs r w s m a -> RWSRefT refw refs r w s m a
+            q u (RWSRefT b) = RWSRefT (\r w s -> u (b r w s))
+  {-# INLINE uninterruptibleMask #-}
diff --git a/Control/Monad/Trans/State/Ref.hs b/Control/Monad/Trans/State/Ref.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Trans/State/Ref.hs
@@ -0,0 +1,153 @@
+{-# LANGUAGE DeriveFunctor         #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE UndecidableInstances  #-}
+-- | An implementation of @StateT@ built on top of mutable references,
+-- providing a proper monad morphism.
+module Control.Monad.Trans.State.Ref
+    ( StateRefT
+    , runStateRefT
+    , runStateIORefT
+    , runStateSTRefT
+    , module Control.Monad.State.Class
+    ) where
+
+import           Control.Applicative         (Applicative (..))
+import           Control.Monad.Catch         (MonadCatch (..), MonadMask (..),
+                                              MonadThrow (..))
+import           Control.Monad.IO.Class      (MonadIO (..))
+import           Control.Monad.State.Class
+import           Control.Monad.Trans.Control (defaultLiftBaseWith,
+                                              defaultRestoreM)
+import           Control.Monad.Trans.Unlift
+import           Data.Mutable                (IORef, MCState, MutableRef,
+                                              PrimMonad, PrimState, RealWorld,
+                                              RefElement, STRef, newRef,
+                                              readRef, writeRef)
+
+-- |
+--
+-- Since 0.1.0
+newtype StateRefT ref s m a = StateRefT
+    { unStateRefT :: ref s -> m a
+    }
+    deriving Functor
+
+-- |
+--
+-- Since 0.1.0
+runStateRefT
+    :: ( Monad m
+       , s ~ RefElement (ref s)
+       , MCState (ref s) ~ PrimState b
+       , MonadBase b m
+       , MutableRef (ref s)
+       , PrimMonad b
+       )
+    => StateRefT ref s m a
+    -> s
+    -> m (a, s)
+runStateRefT (StateRefT f) v0 = do
+    ref <- liftBase $ newRef v0
+    a <- f ref
+    v <- liftBase $ readRef ref
+    return (a, v)
+{-# INLINEABLE runStateRefT #-}
+
+-- |
+--
+-- Since 0.1.0
+runStateIORefT
+    :: ( Monad m
+       , RealWorld ~ PrimState b
+       , MonadBase b m
+       , PrimMonad b
+       )
+    => StateRefT IORef s m a
+    -> s
+    -> m (a, s)
+runStateIORefT = runStateRefT
+{-# INLINE runStateIORefT #-}
+
+-- |
+--
+-- Since 0.1.0
+runStateSTRefT
+    :: ( Monad m
+       , ps ~ PrimState b
+       , MonadBase b m
+       , PrimMonad b
+       )
+    => StateRefT (STRef ps) s m a
+    -> s
+    -> m (a, s)
+runStateSTRefT = runStateRefT
+{-# INLINE runStateSTRefT #-}
+
+instance Applicative m => Applicative (StateRefT ref s m) where
+    pure = StateRefT . const . pure
+    {-# INLINE pure #-}
+    StateRefT f <*> StateRefT g = StateRefT $ \x -> f x <*> g x
+    {-# INLINE (<*>) #-}
+instance Monad m => Monad (StateRefT ref s m) where
+    return = StateRefT . const . return
+    {-# INLINE return #-}
+    StateRefT f >>= g = StateRefT $ \x -> do
+        a <- f x
+        unStateRefT (g a) x
+    {-# INLINE (>>=) #-}
+instance ( MCState (ref s) ~ PrimState b
+         , Monad m
+         , s ~ RefElement (ref s)
+         , MutableRef (ref s)
+         , PrimMonad b
+         , MonadBase b m
+         )
+  => MonadState s (StateRefT ref s m) where
+    get = StateRefT $ liftBase . readRef
+    {-# INLINE get #-}
+    put x = seq x $ StateRefT $ liftBase . (`writeRef` x)
+    {-# INLINE put #-}
+
+instance MonadTrans (StateRefT ref s) where
+    lift = StateRefT . const
+    {-# INLINE lift #-}
+instance MonadIO m => MonadIO (StateRefT ref s m) where
+    liftIO = lift . liftIO
+    {-# INLINE liftIO #-}
+instance MonadBase b m => MonadBase b (StateRefT ref s m) where
+    liftBase = lift . liftBase
+    {-# INLINE liftBase #-}
+
+instance MonadTransControl (StateRefT ref s) where
+    type StT (StateRefT ref s) a = a
+    liftWith f = StateRefT $ \r -> f $ \t -> unStateRefT t r
+    restoreT = StateRefT . const
+    {-# INLINABLE liftWith #-}
+    {-# INLINABLE restoreT #-}
+
+instance MonadBaseControl b m => MonadBaseControl b (StateRefT ref s m) where
+    type StM (StateRefT ref s m) a = StM m a
+    liftBaseWith = defaultLiftBaseWith
+    restoreM = defaultRestoreM
+    {-# INLINE liftBaseWith #-}
+    {-# INLINE restoreM #-}
+
+instance MonadThrow m => MonadThrow (StateRefT ref s m) where
+    throwM = lift . throwM
+    {-# INLINE throwM #-}
+instance MonadCatch m => MonadCatch (StateRefT ref s m) where
+    catch (StateRefT f) g = StateRefT $ \e -> catch (f e) ((`unStateRefT` e) . g)
+
+instance MonadMask m => MonadMask (StateRefT ref s m) where
+  mask a = StateRefT $ \e -> mask $ \u -> unStateRefT (a $ q u) e
+    where q :: (m a -> m a) -> StateRefT ref s m a -> StateRefT ref s m a
+          q u (StateRefT b) = StateRefT (u . b)
+  {-# INLINE mask #-}
+  uninterruptibleMask a =
+    StateRefT $ \e -> uninterruptibleMask $ \u -> unStateRefT (a $ q u) e
+      where q :: (m a -> m a) -> StateRefT ref s m a -> StateRefT ref s m a
+            q u (StateRefT b) = StateRefT (u . b)
+  {-# INLINE uninterruptibleMask #-}
diff --git a/Control/Monad/Trans/Unlift.hs b/Control/Monad/Trans/Unlift.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Trans/Unlift.hs
@@ -0,0 +1,116 @@
+{-# LANGUAGE ConstraintKinds        #-}
+{-# LANGUAGE FlexibleContexts       #-}
+{-# LANGUAGE FlexibleInstances      #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE MultiParamTypeClasses  #-}
+{-# LANGUAGE RankNTypes             #-}
+{-# LANGUAGE ScopedTypeVariables    #-}
+{-# LANGUAGE TypeFamilies           #-}
+{-# LANGUAGE TypeOperators          #-}
+{-# LANGUAGE UndecidableInstances   #-}
+-- | See overview in the README.md
+module Control.Monad.Trans.Unlift
+    ( -- * Trans
+      MonadTransUnlift
+    , Unlift (..)
+    , askUnlift
+    , askRun
+      -- * Base
+    , MonadBaseUnlift
+    , UnliftBase (..)
+    , askUnliftBase
+    , askRunBase
+      -- * Reexports
+    , MonadTrans (..)
+    , MonadBase (..)
+    , MonadTransControl (..)
+    , MonadBaseControl (..)
+    ) where
+
+import           Control.Monad               (ap, liftM)
+import           Control.Monad.Base          (MonadBase (..))
+import           Control.Monad.ST            (ST)
+import           Control.Monad.STM           (STM)
+import           Control.Monad.Trans.Class   (MonadTrans (..))
+import           Control.Monad.Trans.Control (MonadBaseControl (..),
+                                              MonadTransControl (..))
+import           Control.Monad.Trans.Reader  (ReaderT)
+import           Data.Constraint             ((:-), (\\))
+import           Data.Constraint.Forall      (Forall, inst)
+import           Data.Functor.Identity       (Identity)
+
+-- | A function which can move an action down the monad transformer stack, by
+-- providing any necessary environment to the action.
+--
+-- Note that, if ImpredicativeTypes worked reliably, this type wouldn't be
+-- necessary, and 'askUnlift' would simply include a more generalized type.
+--
+-- Since 0.1.0
+newtype Unlift t = Unlift { unlift :: forall a n. Monad n => t n a -> n a }
+
+class    (StT t a ~ a) => Identical t a
+instance (StT t a ~ a) => Identical t a
+
+-- | A monad transformer which can be unlifted, obeying the monad morphism laws.
+--
+-- Since 0.1.0
+class    (MonadTransControl t, Forall (Identical t)) => MonadTransUnlift t
+instance (MonadTransControl t, Forall (Identical t)) => MonadTransUnlift t
+
+mkUnlift :: forall t m a . (Forall (Identical t), Monad m)
+         => (forall n b. Monad n => t n b -> n (StT t b)) -> t m a -> m a
+mkUnlift r act = r act \\ (inst :: Forall (Identical t) :- Identical t a)
+
+-- | Get the 'Unlift' action for the current transformer layer.
+--
+-- Since 0.1.0
+askUnlift :: forall t m. (MonadTransUnlift t, Monad m) => t m (Unlift t)
+askUnlift = liftWith unlifter
+  where
+    unlifter :: (forall n b. Monad n => t n b -> n (StT t b)) -> m (Unlift t)
+    unlifter r = return $ Unlift (mkUnlift r)
+
+-- | A simplified version of 'askUnlift' which addresses the common case where
+-- polymorphism isn't necessary.
+--
+-- Since 0.1.0
+askRun :: (MonadTransUnlift t, Monad (t m), Monad m) => t m (t m a -> m a)
+askRun = liftM unlift askUnlift
+{-# INLINE askRun #-}
+
+-- | Similar to 'Unlift', but instead of moving one layer down the stack, moves
+-- the action to the base monad.
+--
+-- Since 0.1.0
+newtype UnliftBase b m = UnliftBase { unliftBase :: forall a. m a -> b a }
+
+class    (StM m a ~ a) => IdenticalBase m a
+instance (StM m a ~ a) => IdenticalBase m a
+
+-- | A monad transformer stack which can be unlifted, obeying the monad morphism laws.
+--
+-- Since 0.1.0
+class (MonadBaseControl b m, Forall (IdenticalBase m)) => MonadBaseUnlift b m | m -> b
+instance (MonadBaseControl b m, Forall (IdenticalBase m)) => MonadBaseUnlift b m
+
+mkUnliftBase :: forall m a b. (Forall (IdenticalBase m), Monad b)
+             => (forall c. m c -> b (StM m c)) -> m a -> b a
+mkUnliftBase r act = r act \\ (inst :: Forall (IdenticalBase m) :- IdenticalBase m a)
+
+-- | Get the 'UnliftBase' action for the current transformer stack.
+--
+-- Since 0.1.0
+askUnliftBase :: forall b m. (MonadBaseUnlift b m) => m (UnliftBase b m)
+askUnliftBase = liftBaseWith unlifter
+  where
+    unlifter :: (forall c. m c -> b (StM m c)) -> b (UnliftBase b m)
+    unlifter r = return $ UnliftBase (mkUnliftBase r)
+
+-- | A simplified version of 'askUnliftBase' which addresses the common case
+-- where polymorphism isn't necessary.
+--
+-- Since 0.1.0
+askRunBase :: (MonadBaseUnlift b m)
+           => m (m a -> b a)
+askRunBase = liftM unliftBase askUnliftBase
+{-# INLINE askRunBase #-}
diff --git a/Control/Monad/Trans/Writer/Ref.hs b/Control/Monad/Trans/Writer/Ref.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Trans/Writer/Ref.hs
@@ -0,0 +1,172 @@
+{-# LANGUAGE DeriveFunctor         #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE UndecidableInstances  #-}
+-- | An implementation of @WriterT@ built on top of mutable references,
+-- providing a proper monad morphism.
+--
+-- An additional advantage of this transformer over the standard @WriterT@
+-- transformers in the transformers package is that it does not have space
+-- leaks. For more information, see
+-- <https://mail.haskell.org/pipermail/libraries/2012-October/018599.html>.
+module Control.Monad.Trans.Writer.Ref
+    ( WriterRefT
+    , runWriterRefT
+    , runWriterIORefT
+    , runWriterSTRefT
+    , module Control.Monad.Writer.Class
+    ) where
+
+import           Control.Applicative         (Applicative (..))
+import           Control.Monad.Catch         (MonadCatch (..), MonadMask (..),
+                                              MonadThrow (..))
+import           Control.Monad.IO.Class      (MonadIO (..))
+import           Control.Monad.Trans.Control (defaultLiftBaseWith,
+                                              defaultRestoreM)
+import           Control.Monad.Trans.Unlift
+import           Control.Monad.Writer.Class
+import           Data.Monoid                 (Monoid, mappend, mempty)
+import           Data.Mutable                (IORef, MCState, MutableRef,
+                                              PrimMonad, PrimState, RealWorld,
+                                              RefElement, STRef, modifyRef',
+                                              newRef, readRef, writeRef)
+
+-- |
+--
+-- Since 0.1.0
+newtype WriterRefT ref w m a = WriterRefT
+    { unWriterRefT :: ref w -> m a
+    }
+    deriving Functor
+
+-- |
+--
+-- Since 0.1.0
+runWriterRefT
+    :: ( Monad m
+       , w ~ RefElement (ref w)
+       , MCState (ref w) ~ PrimState b
+       , MonadBase b m
+       , MutableRef (ref w)
+       , PrimMonad b
+       , Monoid w
+       )
+    => WriterRefT ref w m a
+    -> m (a, w)
+runWriterRefT (WriterRefT f) = do
+    ref <- liftBase $ newRef mempty
+    a <- f ref
+    v <- liftBase $ readRef ref
+    return (a, v)
+{-# INLINEABLE runWriterRefT #-}
+
+-- |
+--
+-- Since 0.1.0
+runWriterIORefT
+    :: ( Monad m
+       , RealWorld ~ PrimState b
+       , MonadBase b m
+       , PrimMonad b
+       , Monoid w
+       )
+    => WriterRefT IORef w m a
+    -> m (a, w)
+runWriterIORefT = runWriterRefT
+{-# INLINE runWriterIORefT #-}
+
+-- |
+--
+-- Since 0.1.0
+runWriterSTRefT
+    :: ( Monad m
+       , ps ~ PrimState b
+       , MonadBase b m
+       , PrimMonad b
+       , Monoid w
+       )
+    => WriterRefT (STRef ps) w m a
+    -> m (a, w)
+runWriterSTRefT = runWriterRefT
+{-# INLINE runWriterSTRefT #-}
+
+instance Applicative m => Applicative (WriterRefT ref w m) where
+    pure = WriterRefT . const . pure
+    {-# INLINE pure #-}
+    WriterRefT f <*> WriterRefT g = WriterRefT $ \x -> f x <*> g x
+    {-# INLINE (<*>) #-}
+instance Monad m => Monad (WriterRefT ref w m) where
+    return = WriterRefT . const . return
+    {-# INLINE return #-}
+    WriterRefT f >>= g = WriterRefT $ \x -> do
+        a <- f x
+        unWriterRefT (g a) x
+    {-# INLINE (>>=) #-}
+instance ( MCState (ref w) ~ PrimState b
+         , Monad m
+         , w ~ RefElement (ref w)
+         , MutableRef (ref w)
+         , PrimMonad b
+         , MonadBase b m
+         , Monoid w
+         )
+  => MonadWriter w (WriterRefT ref w m) where
+    writer (a, w) = WriterRefT $ \ref ->
+        liftBase $ modifyRef' ref (`mappend` w) >> return a
+    {-# INLINE writer #-}
+    tell w = WriterRefT $ \ref -> liftBase $ modifyRef' ref (`mappend` w)
+    {-# INLINE tell #-}
+    listen (WriterRefT f) = lift $ do
+        ref <- liftBase (newRef mempty)
+        a <- f ref
+        w <- liftBase (readRef ref)
+        return (a, w)
+    {-# INLINEABLE listen #-}
+    pass (WriterRefT f) = WriterRefT $ \ref -> do
+        (a, g) <- f ref
+        liftBase $ modifyRef' ref g
+        return a
+    {-# INLINEABLE pass #-}
+
+instance MonadTrans (WriterRefT ref w) where
+    lift = WriterRefT . const
+    {-# INLINE lift #-}
+instance MonadIO m => MonadIO (WriterRefT ref w m) where
+    liftIO = lift . liftIO
+    {-# INLINE liftIO #-}
+instance MonadBase b m => MonadBase b (WriterRefT ref w m) where
+    liftBase = lift . liftBase
+    {-# INLINE liftBase #-}
+
+instance MonadTransControl (WriterRefT ref w) where
+    type StT (WriterRefT ref w) a = a
+    liftWith f = WriterRefT $ \r -> f $ \t -> unWriterRefT t r
+    restoreT = WriterRefT . const
+    {-# INLINABLE liftWith #-}
+    {-# INLINABLE restoreT #-}
+
+instance MonadBaseControl b m => MonadBaseControl b (WriterRefT ref w m) where
+    type StM (WriterRefT ref w m) a = StM m a
+    liftBaseWith = defaultLiftBaseWith
+    restoreM = defaultRestoreM
+    {-# INLINE liftBaseWith #-}
+    {-# INLINE restoreM #-}
+
+instance MonadThrow m => MonadThrow (WriterRefT ref w m) where
+    throwM = lift . throwM
+    {-# INLINE throwM #-}
+instance MonadCatch m => MonadCatch (WriterRefT ref w m) where
+    catch (WriterRefT f) g = WriterRefT $ \e -> catch (f e) ((`unWriterRefT` e) . g)
+
+instance MonadMask m => MonadMask (WriterRefT ref w m) where
+  mask a = WriterRefT $ \e -> mask $ \u -> unWriterRefT (a $ q u) e
+    where q :: (m a -> m a) -> WriterRefT ref w m a -> WriterRefT ref w m a
+          q u (WriterRefT b) = WriterRefT (u . b)
+  {-# INLINE mask #-}
+  uninterruptibleMask a =
+    WriterRefT $ \e -> uninterruptibleMask $ \u -> unWriterRefT (a $ q u) e
+      where q :: (m a -> m a) -> WriterRefT ref w m a -> WriterRefT ref w m a
+            q u (WriterRefT b) = WriterRefT (u . b)
+  {-# INLINE uninterruptibleMask #-}
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2015 Michael Snoyman
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,152 @@
+## monad-unlift
+
+A common pattern is to have some kind of a monad transformer, and want to pass
+an action into a function that requires actions in a base monad. That sounds a
+bit abstract, so let's give a concrete example:
+
+```haskell
+-- From async
+concurrently :: IO a -> IO b -> IO (a, b)
+
+func1 :: ReaderT Foo IO String
+func2 :: ReaderT Foo IO Double
+
+doBoth :: ReaderT Foo IO (String, Double)
+doBoth = _
+```
+
+Doing this manually is possible, but a bit tedious:
+
+```haskell
+doBoth :: ReaderT Foo IO (String, Double)
+doBoth = ReaderT $ \foo -> concurrently
+    (runReaderT func1 foo)
+    (runReaderT func2 foo)
+```
+
+This also doesn't generalize at all; you'll be stuck writing `concurrently`
+variants for every monad transformer stack. Fortunately, the `monad-control`
+package generalizes this to a large number of transformer stacks. Let's
+implement our generalized `concurrently`:
+
+```haskell
+concurrentlyG :: MonadBaseControl IO m
+              => m a -> m b -> m (StM m a, StM m b)
+concurrentlyG f g = liftBaseWith $ \run ->
+    concurrently (run f) (run g)
+```
+
+Notice how, in the signature for `concurrentlyG`, we no longer return `(a, b)`,
+but `(StM m a, StM m b)`. This is because there may be additional monadic
+context for each thread of execution, and we have no way of merging these
+together in general. Some examples of context are:
+
+* With `WriterT`, it's the values that you called `tell` on
+* With `EitherT`, the returned value may not exist at all
+
+In addition to this difficulty, many people find the types in `monad-control`
+difficult to navigate, due to their extreme generality (which is in fact the
+power of that package!).
+
+There is a subset of these transformer stacks that are in fact [monad
+morphisms](http://www.stackage.org/package/mmorph). Simply stated, these are
+transformer stacks that are isomorphic to `ReaderT`. For these monads, there is
+not context in the returned value. Therefore, there's no need to combine
+returned states or deal with possibly missing values.
+
+This concept is represented by the monad-unlift package, which provides a pair of typeclasses for these kinds of transformer stacks. Before we dive in, let's see how we solve our `concurrentlyG` problem with it:
+
+```haskell
+concurrentlyG :: MonadBaseUnlift IO m
+              => m a -> m b -> m (a, b)
+concurrentlyG f g = do
+    UnliftBase run <- askUnliftBase
+    liftBase $ concurrently (run f) (run g)
+```
+
+Notice how we get `(a, b)` in the return type as desired. There's no need to
+unwrap values are deal with context.
+
+### MonadTransUnlift
+
+`MonadTransUnlift` is a class for any monad transformer which is isomorphic
+to `ReaderT`, in the sense that the environment can be captured and applied
+later. Some interesting cases in this space are:
+
+* `IdentityT` and things isomorphic to it; in this case, you can think of the environment as being `()`
+* Transformers which contain a mutable reference in their environment. This allows them to behave like stateful transformers (e.g., `StateT` or `WriterT`), but still behave the monad morphism laws. (See below for more details.)
+
+Due to weaknesses in GHC's ImpredicativeTypes, we have a helper datatype to
+allow for getting polymorphic unlift functions, appropriately named `Unlift`.
+For many common cases, you can get away with using `askRun` instead, e.g.:
+
+```haskell
+bar :: ReaderT Foo IO ()
+
+baz :: ReaderT Foo IO ()
+baz = do
+    run <- askRun
+    liftIO $ void $ forkIO $ run bar
+```
+
+Using `Unlift`, this would instead be:
+
+```haskell
+    Unlift run <- askUnlift
+    liftIO $ void $ forkIO $ run bar
+```
+
+or equivalently:
+
+```haskell
+    u <- askUnlift
+    liftIO $ void $ forkIO $ unlift u bar
+```
+
+### MonadBaseUnlift
+
+`MonadBaseUnlift` extends this concept to entire transformer stacks. This is
+typically the typeclass that people end up using. You can think of these two
+typeclasses in exactly the same way as `MonadTrans` and `MonadIO`, or more
+precisely `MonadTrans` and `MonadBase`.
+
+For the same ImpredicativeTypes reason, there's a helper type `UnliftBase`.
+Everything we just discussed should transfer directly to `MonadBaseUnlift`,
+so learning something new isn't necessary. For example, you can rewrite the
+last snippet as:
+
+```haskell
+    u <- askUnliftBase
+    liftIO $ void $ forkIO $ unliftBase u bar
+```
+
+### Reference transformers
+
+When playing transformer stack games with a transformer like `StateT`, it's
+common to accidentally discard state modifications. Additionally, in the case
+of runtime exceptions, it's usually impossible to retain the state. (Similar
+statements apply to `WriterT` and `RWST`, both in strict and lazy variants.)
+
+Another approach is to use a `ReaderT` and hold onto a mutable reference. This
+is problematic since there's no built in support for operations like `get`,
+`put`, or `tell`. What we want is to have a `MonadState` and/or `MonadWriter`
+instance.
+
+To address this case, this package includes variants of those transformers that
+use mutable references. These reference are generic using the
+[mutable-containers](http://www.stackage.org/package/mutable-containers)
+package, which allows you to have highly efficient references like `PRef`
+instead of always using boxed references like `IORef`.
+
+### conduit
+
+The `transPipe` function in conduit has caused confusion in the past due to its
+requirement of provided functions to obey monad morphism laws. This package
+makes a good companion to conduit to simplify that function's usage.
+
+### Other notable instances
+
+Both the `HandlerT` transformer from yesod-core and `LoggingT`/`NoLoggingT` are
+valid monad morphisms. `HandlerT` is in fact my first example of using the
+"enviornment holding a mutable reference" technique to overcome exceptions
+destroying state.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/monad-unlift.cabal b/monad-unlift.cabal
new file mode 100644
--- /dev/null
+++ b/monad-unlift.cabal
@@ -0,0 +1,30 @@
+name:                monad-unlift
+version:             0.1.0.0
+synopsis:            Typeclasses for representing monad transformer unlifting
+description:         See README.md
+homepage:            https://github.com/fpco/monad-unlift
+license:             MIT
+license-file:        LICENSE
+author:              Michael Snoyman
+maintainer:          michael@fpcomplete.com
+copyright:           FP Complete
+category:            Control
+build-type:          Simple
+extra-source-files:  README.md ChangeLog.md
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Control.Monad.Trans.Unlift
+                       Control.Monad.Trans.State.Ref
+                       Control.Monad.Trans.Writer.Ref
+                       Control.Monad.Trans.RWS.Ref
+  build-depends:       base >= 4.6 && < 5
+                     , monad-control >= 1.0 && < 1.1
+                     , transformers
+                     , mtl
+                     , transformers-base
+                     , mutable-containers >= 0.3 && < 0.4
+                     , exceptions >= 0.6
+                     , stm
+                     , constraints
+  default-language:    Haskell2010
