diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for effect-stack
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/Control/Monad/Stack/Accum.hs b/Control/Monad/Stack/Accum.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Stack/Accum.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE KindSignatures #-}
+
+module Control.Monad.Stack.Accum where
+
+import Control.Monad.Trans.Accum
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Cont
+import Control.Monad.Trans.Except
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.RWS.CPS as RC
+import Control.Monad.Trans.RWS.Lazy as RL
+import Control.Monad.Trans.RWS.Strict as RS
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Select
+import Control.Monad.Trans.State.Lazy as SL
+import Control.Monad.Trans.State.Strict as SS
+import Control.Monad.Trans.Writer.CPS as WC
+import Control.Monad.Trans.Writer.Lazy as WL
+import Control.Monad.Trans.Writer.Strict as WS
+
+class Monad m => AccumStack m where
+	type PopAccum m :: * -> *
+	liftAccum :: PopAccum m a -> m a
+
+instance (Monad m, Monoid w) => AccumStack (AccumT w m) where
+	type PopAccum (AccumT w m) = m
+	liftAccum = lift
+
+instance AccumStack m => AccumStack (ContT r m) where
+	type PopAccum (ContT r m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance AccumStack m => AccumStack (ExceptT e m) where
+	type PopAccum (ExceptT e m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance AccumStack m => AccumStack (IdentityT m) where
+	type PopAccum (IdentityT m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance AccumStack m => AccumStack (MaybeT m) where
+	type PopAccum (MaybeT m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance (AccumStack m, Monoid w) => AccumStack (RC.RWST r w s m) where
+	type PopAccum (RC.RWST r w s m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance (AccumStack m, Monoid w) => AccumStack (RL.RWST r w s m) where
+	type PopAccum (RL.RWST r w s m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance (AccumStack m, Monoid w) => AccumStack (RS.RWST r w s m) where
+	type PopAccum (RS.RWST r w s m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance AccumStack m => AccumStack (ReaderT r m) where
+	type PopAccum (ReaderT r m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance AccumStack m => AccumStack (SelectT r m) where
+	type PopAccum (SelectT r m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance AccumStack m => AccumStack (SL.StateT s m) where
+	type PopAccum (SL.StateT s m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance AccumStack m => AccumStack (SS.StateT s m) where
+	type PopAccum (SS.StateT s m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance (AccumStack m, Monoid w) => AccumStack (WC.WriterT w m) where
+	type PopAccum (WC.WriterT w m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance (AccumStack m, Monoid w) => AccumStack (WL.WriterT w m) where
+	type PopAccum (WL.WriterT w m) = PopAccum m
+	liftAccum = lift . liftAccum
+
+instance (AccumStack m, Monoid w) => AccumStack (WS.WriterT w m) where
+	type PopAccum (WS.WriterT w m) = PopAccum m
+	liftAccum = lift . liftAccum
diff --git a/Control/Monad/Stack/Cont.hs b/Control/Monad/Stack/Cont.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Stack/Cont.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE KindSignatures #-}
+
+module Control.Monad.Stack.Cont where
+
+import Control.Monad.Trans.Accum
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Cont
+import Control.Monad.Trans.Except
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.RWS.CPS as RC
+import Control.Monad.Trans.RWS.Lazy as RL
+import Control.Monad.Trans.RWS.Strict as RS
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Select
+import Control.Monad.Trans.State.Lazy as SL
+import Control.Monad.Trans.State.Strict as SS
+import Control.Monad.Trans.Writer.CPS as WC
+import Control.Monad.Trans.Writer.Lazy as WL
+import Control.Monad.Trans.Writer.Strict as WS
+
+class Monad m => ContStack m where
+	type PopCont m :: * -> *
+	liftCont :: PopCont m a -> m a
+
+instance (ContStack m, Monoid w) => ContStack (AccumT w m) where
+	type PopCont (AccumT w m) = PopCont m
+	liftCont = lift . liftCont
+
+instance Monad m => ContStack (ContT r m) where
+	type PopCont (ContT r m) = m
+	liftCont = lift
+
+instance ContStack m => ContStack (ExceptT e m) where
+	type PopCont (ExceptT e m) = PopCont m
+	liftCont = lift . liftCont
+
+instance ContStack m => ContStack (IdentityT m) where
+	type PopCont (IdentityT m) = PopCont m
+	liftCont = lift . liftCont
+
+instance ContStack m => ContStack (MaybeT m) where
+	type PopCont (MaybeT m) = PopCont m
+	liftCont = lift . liftCont
+
+instance (ContStack m, Monoid w) => ContStack (RC.RWST r w s m) where
+	type PopCont (RC.RWST r w s m) = PopCont m
+	liftCont = lift . liftCont
+
+instance (ContStack m, Monoid w) => ContStack (RL.RWST r w s m) where
+	type PopCont (RL.RWST r w s m) = PopCont m
+	liftCont = lift . liftCont
+
+instance (ContStack m, Monoid w) => ContStack (RS.RWST r w s m) where
+	type PopCont (RS.RWST r w s m) = PopCont m
+	liftCont = lift . liftCont
+
+instance ContStack m => ContStack (ReaderT r m) where
+	type PopCont (ReaderT r m) = PopCont m
+	liftCont = lift . liftCont
+
+instance ContStack m => ContStack (SelectT r m) where
+	type PopCont (SelectT r m) = PopCont m
+	liftCont = lift . liftCont
+
+instance ContStack m => ContStack (SL.StateT s m) where
+	type PopCont (SL.StateT s m) = PopCont m
+	liftCont = lift . liftCont
+
+instance ContStack m => ContStack (SS.StateT s m) where
+	type PopCont (SS.StateT s m) = PopCont m
+	liftCont = lift . liftCont
+
+instance (ContStack m, Monoid w) => ContStack (WC.WriterT w m) where
+	type PopCont (WC.WriterT w m) = PopCont m
+	liftCont = lift . liftCont
+
+instance (ContStack m, Monoid w) => ContStack (WL.WriterT w m) where
+	type PopCont (WL.WriterT w m) = PopCont m
+	liftCont = lift . liftCont
+
+instance (ContStack m, Monoid w) => ContStack (WS.WriterT w m) where
+	type PopCont (WS.WriterT w m) = PopCont m
+	liftCont = lift . liftCont
diff --git a/Control/Monad/Stack/Except.hs b/Control/Monad/Stack/Except.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Stack/Except.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE KindSignatures #-}
+
+module Control.Monad.Stack.Except where
+
+import Control.Monad.Trans.Accum
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Cont
+import Control.Monad.Trans.Except
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.RWS.CPS as RC
+import Control.Monad.Trans.RWS.Lazy as RL
+import Control.Monad.Trans.RWS.Strict as RS
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Select
+import Control.Monad.Trans.State.Lazy as SL
+import Control.Monad.Trans.State.Strict as SS
+import Control.Monad.Trans.Writer.CPS as WC
+import Control.Monad.Trans.Writer.Lazy as WL
+import Control.Monad.Trans.Writer.Strict as WS
+
+class Monad m => ErrorStack m where
+	type PopError m :: * -> *
+	liftError :: PopError m a -> m a
+
+instance (ErrorStack m, Monoid w) => ErrorStack (AccumT w m) where
+	type PopError (AccumT w m) = PopError m
+	liftError = lift . liftError
+
+instance ErrorStack m => ErrorStack (ContT r m) where
+	type PopError (ContT r m) = PopError m
+	liftError = lift . liftError
+
+instance Monad m => ErrorStack (ExceptT e m) where
+	type PopError (ExceptT e m) = m
+	liftError = lift
+
+instance ErrorStack m => ErrorStack (IdentityT m) where
+	type PopError (IdentityT m) = PopError m
+	liftError = lift . liftError
+
+instance ErrorStack m => ErrorStack (MaybeT m) where
+	type PopError (MaybeT m) = PopError m
+	liftError = lift . liftError
+
+instance (ErrorStack m, Monoid w) => ErrorStack (RC.RWST r w s m) where
+	type PopError (RC.RWST r w s m) = PopError m
+	liftError = lift . liftError
+
+instance (ErrorStack m, Monoid w) => ErrorStack (RL.RWST r w s m) where
+	type PopError (RL.RWST r w s m) = PopError m
+	liftError = lift . liftError
+
+instance (ErrorStack m, Monoid w) => ErrorStack (RS.RWST r w s m) where
+	type PopError (RS.RWST r w s m) = PopError m
+	liftError = lift . liftError
+
+instance ErrorStack m => ErrorStack (ReaderT r m) where
+	type PopError (ReaderT r m) = PopError m
+	liftError = lift . liftError
+
+instance ErrorStack m => ErrorStack (SelectT r m) where
+	type PopError (SelectT r m) = PopError m
+	liftError = lift . liftError
+
+instance ErrorStack m => ErrorStack (SL.StateT s m) where
+	type PopError (SL.StateT s m) = PopError m
+	liftError = lift . liftError
+
+instance ErrorStack m => ErrorStack (SS.StateT s m) where
+	type PopError (SS.StateT s m) = PopError m
+	liftError = lift . liftError
+
+instance (ErrorStack m, Monoid w) => ErrorStack (WC.WriterT w m) where
+	type PopError (WC.WriterT w m) = PopError m
+	liftError = lift . liftError
+
+instance (ErrorStack m, Monoid w) => ErrorStack (WL.WriterT w m) where
+	type PopError (WL.WriterT w m) = PopError m
+	liftError = lift . liftError
+
+instance (ErrorStack m, Monoid w) => ErrorStack (WS.WriterT w m) where
+	type PopError (WS.WriterT w m) = PopError m
+	liftError = lift . liftError
diff --git a/Control/Monad/Stack/Fail.hs b/Control/Monad/Stack/Fail.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Stack/Fail.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE KindSignatures #-}
+
+module Control.Monad.Stack.Fail where
+
+import Control.Monad.Trans.Accum
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Cont
+import Control.Monad.Trans.Except
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.RWS.CPS as RC
+import Control.Monad.Trans.RWS.Lazy as RL
+import Control.Monad.Trans.RWS.Strict as RS
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Select
+import Control.Monad.Trans.State.Lazy as SL
+import Control.Monad.Trans.State.Strict as SS
+import Control.Monad.Trans.Writer.CPS as WC
+import Control.Monad.Trans.Writer.Lazy as WL
+import Control.Monad.Trans.Writer.Strict as WS
+
+class Monad m => FailStack m where
+	type PopFail m :: * -> *
+	liftFail :: PopFail m a -> m a
+
+instance (FailStack m, Monoid w) => FailStack (AccumT w m) where
+	type PopFail (AccumT w m) = PopFail m
+	liftFail = lift . liftFail
+
+instance FailStack m => FailStack (ContT r m) where
+	type PopFail (ContT r m) = PopFail m
+	liftFail = lift . liftFail
+
+instance FailStack m => FailStack (ExceptT e m) where
+	type PopFail (ExceptT e m) = PopFail m
+	liftFail = lift . liftFail
+
+instance FailStack m => FailStack (IdentityT m) where
+	type PopFail (IdentityT m) = PopFail m
+	liftFail = lift . liftFail
+
+instance Monad m => FailStack (MaybeT m) where
+	type PopFail (MaybeT m) = m
+	liftFail = lift
+
+instance (FailStack m, Monoid w) => FailStack (RC.RWST r w s m) where
+	type PopFail (RC.RWST r w s m) = PopFail m
+	liftFail = lift . liftFail
+
+instance (FailStack m, Monoid w) => FailStack (RL.RWST r w s m) where
+	type PopFail (RL.RWST r w s m) = PopFail m
+	liftFail = lift . liftFail
+
+instance (FailStack m, Monoid w) => FailStack (RS.RWST r w s m) where
+	type PopFail (RS.RWST r w s m) = PopFail m
+	liftFail = lift . liftFail
+
+instance FailStack m => FailStack (ReaderT r m) where
+	type PopFail (ReaderT r m) = PopFail m
+	liftFail = lift . liftFail
+
+instance FailStack m => FailStack (SelectT r m) where
+	type PopFail (SelectT r m) = PopFail m
+	liftFail = lift . liftFail
+
+instance FailStack m => FailStack (SL.StateT s m) where
+	type PopFail (SL.StateT s m) = PopFail m
+	liftFail = lift . liftFail
+
+instance FailStack m => FailStack (SS.StateT s m) where
+	type PopFail (SS.StateT s m) = PopFail m
+	liftFail = lift . liftFail
+
+instance (FailStack m, Monoid w) => FailStack (WC.WriterT w m) where
+	type PopFail (WC.WriterT w m) = PopFail m
+	liftFail = lift . liftFail
+
+instance (FailStack m, Monoid w) => FailStack (WL.WriterT w m) where
+	type PopFail (WL.WriterT w m) = PopFail m
+	liftFail = lift . liftFail
+
+instance (FailStack m, Monoid w) => FailStack (WS.WriterT w m) where
+	type PopFail (WS.WriterT w m) = PopFail m
+	liftFail = lift . liftFail
diff --git a/Control/Monad/Stack/Reader.hs b/Control/Monad/Stack/Reader.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Stack/Reader.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE KindSignatures #-}
+
+module Control.Monad.Stack.Reader where
+
+import Control.Monad.Trans.Accum
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Cont
+import Control.Monad.Trans.Except
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.RWS.CPS as RC
+import Control.Monad.Trans.RWS.Lazy as RL
+import Control.Monad.Trans.RWS.Strict as RS
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Select
+import Control.Monad.Trans.State.Lazy as SL
+import Control.Monad.Trans.State.Strict as SS
+import Control.Monad.Trans.Writer.CPS as WC
+import Control.Monad.Trans.Writer.Lazy as WL
+import Control.Monad.Trans.Writer.Strict as WS
+
+class Monad m => ReaderStack m where
+	type PopReader m :: * -> *
+	liftReader :: PopReader m a -> m a
+
+instance (ReaderStack m, Monoid w) => ReaderStack (AccumT w m) where
+	type PopReader (AccumT w m) = PopReader m
+	liftReader = lift . liftReader
+
+instance ReaderStack m => ReaderStack (ContT r m) where
+	type PopReader (ContT r m) = PopReader m
+	liftReader = lift . liftReader
+
+instance Monad m => ReaderStack (ExceptT e m) where
+	type PopReader (ExceptT e m) = m
+	liftReader = lift
+
+instance ReaderStack m => ReaderStack (IdentityT m) where
+	type PopReader (IdentityT m) = PopReader m
+	liftReader = lift . liftReader
+
+instance ReaderStack m => ReaderStack (MaybeT m) where
+	type PopReader (MaybeT m) = PopReader m
+	liftReader = lift . liftReader
+
+instance (Monad m, Monoid w) => ReaderStack (RC.RWST r w s m) where
+	type PopReader (RC.RWST r w s m) = m
+	liftReader = lift
+
+instance (Monad m, Monoid w) => ReaderStack (RL.RWST r w s m) where
+	type PopReader (RL.RWST r w s m) = m
+	liftReader = lift
+
+instance (Monad m, Monoid w) => ReaderStack (RS.RWST r w s m) where
+	type PopReader (RS.RWST r w s m) = m
+	liftReader = lift
+
+instance Monad m => ReaderStack (ReaderT r m) where
+	type PopReader (ReaderT r m) = m
+	liftReader = lift
+
+instance ReaderStack m => ReaderStack (SelectT r m) where
+	type PopReader (SelectT r m) = PopReader m
+	liftReader = lift . liftReader
+
+instance ReaderStack m => ReaderStack (SL.StateT s m) where
+	type PopReader (SL.StateT s m) = PopReader m
+	liftReader = lift . liftReader
+
+instance ReaderStack m => ReaderStack (SS.StateT s m) where
+	type PopReader (SS.StateT s m) = PopReader m
+	liftReader = lift . liftReader
+
+instance (ReaderStack m, Monoid w) => ReaderStack (WC.WriterT w m) where
+	type PopReader (WC.WriterT w m) = PopReader m
+	liftReader = lift . liftReader
+
+instance (ReaderStack m, Monoid w) => ReaderStack (WL.WriterT w m) where
+	type PopReader (WL.WriterT w m) = PopReader m
+	liftReader = lift . liftReader
+
+instance (ReaderStack m, Monoid w) => ReaderStack (WS.WriterT w m) where
+	type PopReader (WS.WriterT w m) = PopReader m
+	liftReader = lift . liftReader
diff --git a/Control/Monad/Stack/Select.hs b/Control/Monad/Stack/Select.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Stack/Select.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE KindSignatures #-}
+
+module Control.Monad.Stack.Select where
+
+import Control.Monad.Trans.Accum
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Cont
+import Control.Monad.Trans.Except
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.RWS.CPS as RC
+import Control.Monad.Trans.RWS.Lazy as RL
+import Control.Monad.Trans.RWS.Strict as RS
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Select
+import Control.Monad.Trans.State.Lazy as SL
+import Control.Monad.Trans.State.Strict as SS
+import Control.Monad.Trans.Writer.CPS as WC
+import Control.Monad.Trans.Writer.Lazy as WL
+import Control.Monad.Trans.Writer.Strict as WS
+
+class Monad m => SelectStack m where
+	type PopSelect m :: * -> *
+	liftSelect :: PopSelect m a -> m a
+
+instance (SelectStack m, Monoid w) => SelectStack (AccumT w m) where
+	type PopSelect (AccumT w m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance SelectStack m => SelectStack (ContT r m) where
+	type PopSelect (ContT r m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance SelectStack m => SelectStack (ExceptT e m) where
+	type PopSelect (ExceptT e m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance SelectStack m => SelectStack (IdentityT m) where
+	type PopSelect (IdentityT m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance SelectStack m => SelectStack (MaybeT m) where
+	type PopSelect (MaybeT m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance (SelectStack m, Monoid w) => SelectStack (RC.RWST r w s m) where
+	type PopSelect (RC.RWST r w s m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance (SelectStack m, Monoid w) => SelectStack (RL.RWST r w s m) where
+	type PopSelect (RL.RWST r w s m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance (SelectStack m, Monoid w) => SelectStack (RS.RWST r w s m) where
+	type PopSelect (RS.RWST r w s m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance SelectStack m => SelectStack (ReaderT r m) where
+	type PopSelect (ReaderT r m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance Monad m => SelectStack (SelectT r m) where
+	type PopSelect (SelectT r m) = m
+	liftSelect = lift
+
+instance SelectStack m => SelectStack (SL.StateT s m) where
+	type PopSelect (SL.StateT s m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance SelectStack m => SelectStack (SS.StateT s m) where
+	type PopSelect (SS.StateT s m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance (SelectStack m, Monoid w) => SelectStack (WC.WriterT w m) where
+	type PopSelect (WC.WriterT w m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance (SelectStack m, Monoid w) => SelectStack (WL.WriterT w m) where
+	type PopSelect (WL.WriterT w m) = PopSelect m
+	liftSelect = lift . liftSelect
+
+instance (SelectStack m, Monoid w) => SelectStack (WS.WriterT w m) where
+	type PopSelect (WS.WriterT w m) = PopSelect m
+	liftSelect = lift . liftSelect
diff --git a/Control/Monad/Stack/State.hs b/Control/Monad/Stack/State.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Stack/State.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE KindSignatures #-}
+
+module Control.Monad.Stack.State where
+
+import Control.Monad.Trans.Accum
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Cont
+import Control.Monad.Trans.Except
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.RWS.CPS as RC
+import Control.Monad.Trans.RWS.Lazy as RL
+import Control.Monad.Trans.RWS.Strict as RS
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Select
+import Control.Monad.Trans.State.Lazy as SL
+import Control.Monad.Trans.State.Strict as SS
+import Control.Monad.Trans.Writer.CPS as WC
+import Control.Monad.Trans.Writer.Lazy as WL
+import Control.Monad.Trans.Writer.Strict as WS
+
+class Monad m => StateStack m where
+	type PopState m :: * -> *
+	liftState :: PopState m a -> m a
+
+instance (StateStack m, Monoid w) => StateStack (AccumT w m) where
+	type PopState (AccumT w m) = PopState m
+	liftState = lift . liftState
+
+instance StateStack m => StateStack (ContT r m) where
+	type PopState (ContT r m) = PopState m
+	liftState = lift . liftState
+
+instance StateStack m => StateStack (ExceptT e m) where
+	type PopState (ExceptT e m) = PopState m
+	liftState = lift . liftState
+
+instance StateStack m => StateStack (IdentityT m) where
+	type PopState (IdentityT m) = PopState m
+	liftState = lift . liftState
+
+instance StateStack m => StateStack (MaybeT m) where
+	type PopState (MaybeT m) = PopState m
+	liftState = lift . liftState
+
+instance (Monad m, Monoid w) => StateStack (RC.RWST r w s m) where
+	type PopState (RC.RWST r w s m) = m
+	liftState = lift
+
+instance (Monad m, Monoid w) => StateStack (RL.RWST r w s m) where
+	type PopState (RL.RWST r w s m) = m
+	liftState = lift
+
+instance (Monad m, Monoid w) => StateStack (RS.RWST r w s m) where
+	type PopState (RS.RWST r w s m) = m
+	liftState = lift
+
+instance StateStack m => StateStack (ReaderT r m) where
+	type PopState (ReaderT r m) = PopState m
+	liftState = lift . liftState
+
+instance StateStack m => StateStack (SelectT r m) where
+	type PopState (SelectT r m) = PopState m
+	liftState = lift . liftState
+
+instance Monad m => StateStack (SL.StateT s m) where
+	type PopState (SL.StateT s m) = m
+	liftState = lift
+
+instance Monad m => StateStack (SS.StateT s m) where
+	type PopState (SS.StateT s m) = m
+	liftState = lift
+
+instance (StateStack m, Monoid w) => StateStack (WC.WriterT w m) where
+	type PopState (WC.WriterT w m) = PopState m
+	liftState = lift . liftState
+
+instance (StateStack m, Monoid w) => StateStack (WL.WriterT w m) where
+	type PopState (WL.WriterT w m) = PopState m
+	liftState = lift . liftState
+
+instance (StateStack m, Monoid w) => StateStack (WS.WriterT w m) where
+	type PopState (WS.WriterT w m) = PopState m
+	liftState = lift . liftState
diff --git a/Control/Monad/Stack/Writer.hs b/Control/Monad/Stack/Writer.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Stack/Writer.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE KindSignatures #-}
+
+module Control.Monad.Stack.Writer where
+
+import Control.Monad.Trans.Accum
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Cont
+import Control.Monad.Trans.Except
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.RWS.CPS as RC
+import Control.Monad.Trans.RWS.Lazy as RL
+import Control.Monad.Trans.RWS.Strict as RS
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Select
+import Control.Monad.Trans.State.Lazy as SL
+import Control.Monad.Trans.State.Strict as SS
+import Control.Monad.Trans.Writer.CPS as WC
+import Control.Monad.Trans.Writer.Lazy as WL
+import Control.Monad.Trans.Writer.Strict as WS
+
+class Monad m => WriterStack m where
+	type PopWriter m :: * -> *
+	liftWriter :: PopWriter m a -> m a
+
+instance (WriterStack m, Monoid w) => WriterStack (AccumT w m) where
+	type PopWriter (AccumT w m) = PopWriter m
+	liftWriter = lift . liftWriter
+
+instance WriterStack m => WriterStack (ContT r m) where
+	type PopWriter (ContT r m) = PopWriter m
+	liftWriter = lift . liftWriter
+
+instance WriterStack m => WriterStack (ExceptT e m) where
+	type PopWriter (ExceptT e m) = PopWriter m
+	liftWriter = lift . liftWriter
+
+instance WriterStack m => WriterStack (IdentityT m) where
+	type PopWriter (IdentityT m) = PopWriter m
+	liftWriter = lift . liftWriter
+
+instance WriterStack m => WriterStack (MaybeT m) where
+	type PopWriter (MaybeT m) = PopWriter m
+	liftWriter = lift . liftWriter
+
+instance (Monad m, Monoid w) => WriterStack (RC.RWST r w s m) where
+	type PopWriter (RC.RWST r w s m) = m
+	liftWriter = lift
+
+instance (Monad m, Monoid w) => WriterStack (RL.RWST r w s m) where
+	type PopWriter (RL.RWST r w s m) = m
+	liftWriter = lift
+
+instance (Monad m, Monoid w) => WriterStack (RS.RWST r w s m) where
+	type PopWriter (RS.RWST r w s m) = m
+	liftWriter = lift
+
+instance WriterStack m => WriterStack (ReaderT r m) where
+	type PopWriter (ReaderT r m) = PopWriter m
+	liftWriter = lift . liftWriter
+
+instance WriterStack m => WriterStack (SelectT r m) where
+	type PopWriter (SelectT r m) = PopWriter m
+	liftWriter = lift . liftWriter
+
+instance WriterStack m => WriterStack (SL.StateT s m) where
+	type PopWriter (SL.StateT s m) = PopWriter m
+	liftWriter = lift . liftWriter
+
+instance WriterStack m => WriterStack (SS.StateT s m) where
+	type PopWriter (SS.StateT s m) = PopWriter m
+	liftWriter = lift . liftWriter
+
+instance (Monad m, Monoid w) => WriterStack (WC.WriterT w m) where
+	type PopWriter (WC.WriterT w m) = m
+	liftWriter = lift
+
+instance (Monad m, Monoid w) => WriterStack (WL.WriterT w m) where
+	type PopWriter (WL.WriterT w m) = m
+	liftWriter = lift
+
+instance (WriterStack m, Monoid w) => WriterStack (WS.WriterT w m) where
+	type PopWriter (WS.WriterT w m) = PopWriter m
+	liftWriter = lift . liftWriter
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2019, Daniel Wagner
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Daniel Wagner nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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/effect-stack.cabal b/effect-stack.cabal
new file mode 100644
--- /dev/null
+++ b/effect-stack.cabal
@@ -0,0 +1,80 @@
+name:                effect-stack
+version:             0.1.0.0
+synopsis:            Reducing the pain of transformer stacks with duplicated effects
+description:         When using monad transformer stacks, it is common to want
+                     to mix effects from various layers of the stack within a
+                     single block of code. The @lift@ operation can be used to
+                     convert an action that uses effects at some deep layer of
+                     the stack into one that works in the full stack. It
+                     quickly becomes tedious to include exactly the right
+                     number of calls to @lift@ each time they are needed; and
+                     makes the code more fragile when the transformer stack is
+                     changed (e.g. to include a new effect).
+                     .
+                     The @mtl@ package provides a convenient way to point to a
+                     particular layer of the stack, under the assumption that
+                     there is exactly one "kind" of each interesting effect.
+                     (For example, one can only have one type of state, one
+                     type of environment to read from, and so forth.) However,
+                     if one wishes to have to copies of a single kind of
+                     effect, there is no convenient, generic way to choose
+                     anything other than the one that appears topmost in the
+                     stack. For example, for a stack that contains two
+                     @StateT@s in it, one can write code that accesses the
+                     outermost state using a type like
+                     .
+                     @MonadState outer m => m ()@
+                     .
+                     but there is no polymorphic way to reach the inner
+                     @StateT@'s state. One is back to writing fragile code that
+                     depends on exactly which transformer stack was chosen.
+                     .
+                     This package provides a way to make such choices
+                     generically: it introduces a separate stack for each kind
+                     of effect, and provides an operation for popping one layer
+                     of a given effect's stack. Continuing the @StateT@
+                     example, one could write
+                     .
+                     @MonadState outer m => m ()@
+                     .
+                     as before for the outermost state, or
+                     .
+                     @(StateStack m, MonadState inner (PopState m)) => m ()@
+                     .
+                     to access the state from underneath the outermost
+                     @StateT@, no matter how deep it is.
+license:             BSD3
+license-file:        LICENSE
+author:              Daniel Wagner
+maintainer:          me@dmwit.com
+-- copyright:
+category:            Control
+build-type:          Simple
+extra-source-files:  ChangeLog.md
+cabal-version:       >=1.10
+
+source-repository head
+  type:     git
+  location: https://github.com/dmwit/effect-stack
+
+library
+  exposed-modules:
+                       Control.Monad.Stack.Accum,
+                       Control.Monad.Stack.Cont,
+                       Control.Monad.Stack.Except,
+                       Control.Monad.Stack.Fail,
+                       Control.Monad.Stack.Reader,
+                       Control.Monad.Stack.Select,
+                       Control.Monad.Stack.State,
+                       Control.Monad.Stack.Writer
+  -- other-modules:
+  other-extensions:
+                       KindSignatures,
+                       TypeFamilies
+  build-depends:
+                       base >=4.12 && <4.13,
+                       transformers >=0.5 && <0.6,
+                       mtl
+  -- hs-source-dirs:
+  default-language:    Haskell2010
+  ghc-options:         -fno-warn-tabs
