diff --git a/Control/Monad/Readers.hs b/Control/Monad/Readers.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Readers.hs
@@ -0,0 +1,54 @@
+-- | MonadState without the function dependency @m -> s@.
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+module Control.Monad.Readers
+    ( module Control.Monad.Reader
+    , MonadReaders(ask, local)
+    , asks
+    ) where
+
+import Control.Monad.Reader hiding (MonadReader(ask, local, reader), asks)
+import qualified Control.Monad.Reader as MTL (ask, local)
+import Control.Monad.State (StateT, get, evalStateT)
+import Control.Monad.Writer (runWriterT, WriterT)
+
+-- | Version of MonadReader modified to remove the functional dependency.
+class Monad m => MonadReaders r m where
+    ask :: m r
+    ask = reader id
+
+    local :: (r -> r) -> m a -> m a
+
+    reader :: (r -> a) -> m a
+    reader f = do
+      r <- ask
+      return (f r)
+
+instance Monad m => MonadReaders r (ReaderT r m) where
+    ask = MTL.ask
+    local = MTL.local
+
+instance (Monad m, MonadReaders r m) => MonadReaders r (StateT s m) where
+    ask = lift ask
+    local f action = get >>= lift . local f . evalStateT action
+
+instance (Monad m, Monoid w, MonadReaders r m) => MonadReaders r (WriterT w m) where
+    ask = lift ask
+    local f action = lift (local f (runWriterT action >>= return . fst))
+
+{-
+-- Here is how you create a MonadReaders instance for a type that is
+-- nested inside another MonadReaders instances.   You need to declare
+-- this with the exact parent type (here Bar) or you will get
+-- overlapping instances.
+
+instance (Monad m, MonadReaders Foo m) => MonadReaders Foo (ReaderT Bar m) where
+    ask = lift ask
+    local f action = MTL.ask >>= runReaderT (local f (lift action))
+-}
+
+-- | Retrieves a function of the current environment.
+asks :: MonadReaders r m
+    => (r -> a) -- ^ The selector function to apply to the environment.
+    -> m a
+asks = reader
diff --git a/Control/Monad/States.hs b/Control/Monad/States.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/States.hs
@@ -0,0 +1,54 @@
+-- | MonadState without the function dependency @m -> s@.
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+module Control.Monad.States
+    ( module Control.Monad.State
+    , MonadStates(get, put)
+    , modify
+    , modify'
+    , gets
+    ) where
+
+import Control.Monad.Reader
+import Control.Monad.State hiding (MonadState(get, put, state), modify, modify', gets)
+import qualified Control.Monad.State as MTL (get, put)
+import Control.Monad.Writer (WriterT)
+
+-- | Copy of 'Control.Monad.State.MonadState' with functional dependency m -> s removed.
+class Monad m => MonadStates s m where
+    get :: m s
+    get = state (\s -> (s, s))
+    put :: s -> m ()
+    put s = state (\_ -> ((), s))
+    state :: (s -> (a, s)) -> m a
+    state f = do
+      s <- get
+      let ~(a, s') = f s
+      put s'
+      return a
+
+-- | Copy of 'Control.Monad.State.mondify'
+modify :: MonadStates s m => (s -> s) -> m ()
+modify f = state (\s -> ((), f s))
+
+-- | Copy of 'Control.Monad.State.modify''
+modify' :: MonadStates s m => (s -> s) -> m ()
+modify' f = state (\s -> let s' = f s in s' `seq` ((), s'))
+
+-- | Copy of 'Control.Monad.State.gets'
+gets :: MonadStates s m => (s -> a) -> m a
+gets f = do
+    s <- get
+    return (f s)
+
+instance Monad m => MonadStates s (StateT s m) where
+    get = MTL.get
+    put = MTL.put
+
+instance (Monad m, MonadStates s m) => MonadStates s (ReaderT r m) where
+    get = lift get
+    put s = lift $ put s
+
+instance (Monad m, Monoid w, MonadStates s m) => MonadStates s (WriterT w m) where
+    get = lift get
+    put = lift . put
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+import Distribution.Simple
+main :: IO ()
+main = defaultMain
diff --git a/mtl-unleashed.cabal b/mtl-unleashed.cabal
new file mode 100644
--- /dev/null
+++ b/mtl-unleashed.cabal
@@ -0,0 +1,31 @@
+name:               mtl-unleashed
+version:            0.2
+cabal-version:      >= 1.10
+build-type:         Simple
+license:            BSD3
+category:           Control
+author:             David Fox
+copyright:          (c) 2015 David Fox
+maintainer:         David Fox <dsf@seereason.com>
+homepage:           https://github.com/seereason/mtl-unleashed
+bug-reports:        https://github.com/seereason/mtl-unleashed/issues
+stability:          experimental
+synopsis:           MTL classes without the functional dependency
+description:
+  Classes MonadState and MonadReader without the functional
+  dependency from the monad to the contained type.  This allows
+  more flexibility to extract bits and pieces of state based on
+  type, but increases ambiguities that need to be resolved with
+  extra type signatures.
+
+library
+  build-depends: base < 5, mtl
+  ghc-options: -Wall -O2
+  exposed-modules:
+    Control.Monad.Readers
+    Control.Monad.States
+  default-language: Haskell2010
+
+source-repository head
+  type:     git
+  location: git://github.com/seereason/mtl-unleashed.git
