diff --git a/Control/Comonad/Cofree.hs b/Control/Comonad/Cofree.hs
--- a/Control/Comonad/Cofree.hs
+++ b/Control/Comonad/Cofree.hs
@@ -1,4 +1,8 @@
-{-# LANGUAGE CPP, FlexibleContexts, FlexibleInstances, UndecidableInstances #-}
+{-# LANGUAGE CPP
+           , FlexibleContexts
+           , FlexibleInstances
+           , UndecidableInstances
+           , MultiParamTypeClasses #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.Comonad.Cofree
@@ -7,15 +11,15 @@
 --
 -- Maintainer  :  Edward Kmett <ekmett@gmail.com>
 -- Stability   :  provisional
--- Portability :  portable
+-- Portability :  MPTCs, fundeps
 --
--- Haskell 98 cofree comonads
+-- Cofree comonads
 --
 ----------------------------------------------------------------------------
 module Control.Comonad.Cofree
   ( Cofree(..)
   , section
-  , outCofree
+  , unwrap
   , coiter
   , unfold
   ) where
@@ -23,6 +27,10 @@
 import Control.Applicative
 import Control.Comonad
 import Control.Comonad.Trans.Class
+import Control.Comonad.Cofree.Class
+import Control.Comonad.Env.Class
+import Control.Comonad.Store.Class
+import Control.Comonad.Traced.Class
 import Data.Functor.Bind
 import Data.Distributive
 import Data.Foldable
@@ -40,9 +48,6 @@
 
 data Cofree f a = a :< f (Cofree f a)
 
-outCofree :: Cofree f a -> f (Cofree f a)
-outCofree (_ :< as) = as
-
 coiter :: Functor f => (a -> f a) -> a -> Cofree f a
 coiter psi a = a :< (coiter psi <$> psi a)
 
@@ -50,16 +55,19 @@
 unfold f c = case f c of 
   (x, d) -> x :< fmap (unfold f) d
 
+instance Functor f => ComonadCofree f (Cofree f) where
+  unwrap (_ :< as) = as
+
 instance Distributive f => Distributive (Cofree f) where
-  distribute w = fmap extract w :< fmap distribute (distribute (fmap outCofree w))
+  distribute w = fmap extract w :< fmap distribute (collect unwrap w)
 
 instance Functor f => Functor (Cofree f) where
   fmap f (a :< as) = f a :< fmap (fmap f) as
   b <$ (_ :< as) = b :< fmap (b <$) as
 
 instance Functor f => Extend (Cofree f) where
-  extend f w = f w :< fmap (extend f) (outCofree w)
-  duplicate w = w :< fmap duplicate (outCofree w)
+  extend f w = f w :< fmap (extend f) (unwrap w)
+  duplicate w = w :< fmap duplicate (unwrap w)
 
 instance Functor f => Comonad (Cofree f) where
   extract (a :< _) = a
@@ -114,9 +122,7 @@
 instance Traversable1 f => Traversable1 (Cofree f) where
   traverse1 f (a :< as) = (:<) <$> f a <.> traverse1 (traverse1 f) as
 
-
 #ifdef GHC_TYPEABLE
-
 instance (Typeable1 f) => Typeable1 (Cofree f) where
   typeOf1 dfa = mkTyConApp cofreeTyCon [typeOf1 (f dfa)]
     where
@@ -150,5 +156,15 @@
 cofreeDataType :: DataType
 cofreeDataType = mkDataType "Control.Comonad.Cofree.Cofree" [cofreeConstr]
 {-# NOINLINE cofreeDataType #-}
-
 #endif
+
+instance ComonadEnv e w => ComonadEnv e (Cofree w) where
+  ask = ask . lower
+
+instance ComonadStore s w => ComonadStore s (Cofree w) where
+  pos (_ :< as) = pos as
+  peek s (_ :< as) = extract (peek s as)
+
+
+instance ComonadTraced m w => ComonadTraced m (Cofree w) where
+  trace m = trace m . lower
diff --git a/Control/Comonad/Cofree/Class.hs b/Control/Comonad/Cofree/Class.hs
new file mode 100644
--- /dev/null
+++ b/Control/Comonad/Cofree/Class.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE MultiParamTypeClasses
+           , FunctionalDependencies
+           , FlexibleInstances
+           , UndecidableInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Cofree.Class
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  fundeps, MPTCs
+----------------------------------------------------------------------------
+module Control.Comonad.Cofree.Class 
+  ( ComonadCofree(..)
+  ) where
+
+import Control.Applicative
+import Control.Comonad
+import qualified Control.Comonad.Trans.Env.Strict as Strict
+import qualified Control.Comonad.Trans.Store.Strict as Strict
+import qualified Control.Comonad.Trans.Discont.Strict as Strict
+import qualified Control.Comonad.Trans.Env.Lazy as Lazy
+import qualified Control.Comonad.Trans.Store.Lazy as Lazy
+import qualified Control.Comonad.Trans.Discont.Lazy as Lazy
+import qualified Control.Comonad.Trans.Traced as Simple
+import qualified Control.Comonad.Trans.Traced.Memo as Memo
+import qualified Control.Comonad.Trans.Store.Memo as Memo
+import qualified Control.Comonad.Trans.Discont.Memo as Memo
+import Control.Comonad.Trans.Identity 
+import Data.Monoid
+import Data.Semigroup
+
+class (Functor f, Comonad w) => ComonadCofree f w | w -> f where
+  unwrap :: w a -> f (w a)
+
+instance ComonadCofree f w => ComonadCofree f (IdentityT w) where
+  unwrap = fmap IdentityT . unwrap . runIdentityT
+  
+instance ComonadCofree f w => ComonadCofree f (Strict.EnvT e w) where
+  unwrap (Strict.EnvT e wa) = Strict.EnvT e <$> unwrap wa
+
+instance ComonadCofree f w => ComonadCofree f (Lazy.EnvT e w) where
+  unwrap (Lazy.EnvT e wa) = Lazy.EnvT e <$> unwrap wa
+
+instance ComonadCofree f w => ComonadCofree f (Strict.StoreT s w) where
+  unwrap (Strict.StoreT wsa s) = flip Strict.StoreT s <$> unwrap wsa
+
+instance ComonadCofree f w => ComonadCofree f (Lazy.StoreT s w) where
+  unwrap (Lazy.StoreT wsa s) = flip Lazy.StoreT s <$> unwrap wsa
+
+instance ComonadCofree f w => ComonadCofree f (Memo.StoreT s w) where
+  unwrap w = flip Memo.storeT s <$> unwrap wsa
+    where (wsa, s) = Memo.runStoreT w
+
+instance (ComonadCofree f w, Semigroup m, Monoid m) => ComonadCofree f (Simple.TracedT m w) where
+  unwrap (Simple.TracedT wma) = Simple.TracedT <$> unwrap wma
+
+instance (ComonadCofree f w, Semigroup m, Monoid m) => ComonadCofree f (Memo.TracedT m w) where
+  unwrap = fmap Memo.tracedT . unwrap . Memo.runTracedT
+
+instance ComonadCofree f w => ComonadCofree f (Strict.DiscontT k w) where
+  unwrap (Strict.DiscontT f ws) = Strict.DiscontT f <$> unwrap ws
+
+instance ComonadCofree f w => ComonadCofree f (Lazy.DiscontT k w) where
+  unwrap (Lazy.DiscontT f ws) = Lazy.DiscontT f <$> unwrap ws
+
+instance ComonadCofree f w => ComonadCofree f (Memo.DiscontT k w) where
+  unwrap w = Memo.discontT f <$> unwrap wa
+    where (f, wa) = Memo.runDiscontT w
diff --git a/Control/Monad/Free.hs b/Control/Monad/Free.hs
--- a/Control/Monad/Free.hs
+++ b/Control/Monad/Free.hs
@@ -1,26 +1,37 @@
-{-# LANGUAGE FlexibleContexts, FlexibleInstances, UndecidableInstances #-}
+{-# LANGUAGE FlexibleContexts
+           , FlexibleInstances
+           , UndecidableInstances
+	   , MultiParamTypeClasses #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.Monad.Free
--- Copyright   :  (C) 2008-2011 Edward Kmett,
+-- Copyright   :  (C) 2008-2011 Edward Kmett
 -- License     :  BSD-style (see the file LICENSE)
 --
 -- Maintainer  :  Edward Kmett <ekmett@gmail.com>
 -- Stability   :  provisional
--- Portability :  portable
+-- Portability :  MPTCs, fundeps
 --
--- Haskell 98 free monads
+-- Free monads
 --
 ----------------------------------------------------------------------------
 module Control.Monad.Free
-  ( Free(..)
+  ( MonadFree(..)
+  , Free(..)
   , retract
+  , liftF
   , iter
   ) where
 
 import Control.Applicative
 import Control.Monad (liftM, MonadPlus(..))
 import Control.Monad.Trans.Class
+import Control.Monad.Free.Class
+import Control.Monad.Reader.Class
+import Control.Monad.Writer.Class
+import Control.Monad.State.Class
+import Control.Monad.Error.Class
+import Control.Monad.Cont.Class
 import Data.Functor.Bind
 import Data.Foldable
 import Data.Traversable
@@ -29,10 +40,6 @@
 
 data Free f a = Pure a | Free (f (Free f a))
 
-iter :: Functor f => (f a -> a) -> Free f a -> a
-iter _ (Pure a) = a
-iter phi (Free m) = phi (iter phi <$> m)
-
 instance (Eq (f (Free f a)), Eq a) => Eq (Free f a) where
   Pure a == Pure b = a == b
   Free fa == Free fb = fa == fb
@@ -95,11 +102,6 @@
 instance MonadTrans Free where
   lift = Free . liftM Pure
 
--- | retract . lift = id
-retract :: Monad f => Free f a -> f a
-retract (Pure a) = return a
-retract (Free as) = as >>= retract
-
 instance Foldable f => Foldable (Free f) where
   foldMap f (Pure a) = f a
   foldMap f (Free fa) = foldMap (foldMap f) fa
@@ -115,3 +117,41 @@
 instance Traversable1 f => Traversable1 (Free f) where
   traverse1 f (Pure a) = Pure <$> f a
   traverse1 f (Free fa) = Free <$> traverse1 (traverse1 f) fa
+
+instance (Functor m, MonadWriter e m) => MonadWriter e (Free m) where
+  tell = lift . tell
+  listen = lift . listen . retract
+  pass = lift . pass . retract
+  
+instance (Functor m, MonadReader e m) => MonadReader e (Free m) where
+  ask = lift ask
+  local f = lift . local f . retract
+  
+instance (Functor m, MonadState s m) => MonadState s (Free m) where
+  get = lift get
+  put s = lift (put s)
+
+instance (Functor m, MonadError e m) => MonadError e (Free m) where
+  throwError = lift . throwError
+  catchError as f = lift (catchError (retract as) (retract . f))
+
+instance (Functor m, MonadCont m) => MonadCont (Free m) where
+  callCC f = lift (callCC (retract . f . liftM lift))
+
+liftF :: Functor f => f a -> Free f a
+liftF = Free . fmap Pure
+
+instance Functor f => MonadFree f (Free f) where
+  wrap = Free
+
+-- | 
+--
+-- > retract . lift = id
+-- > retract . liftF = id
+retract :: Monad f => Free f a -> f a
+retract (Pure a) = return a
+retract (Free as) = as >>= retract
+
+iter :: Functor f => (f a -> a) -> Free f a -> a
+iter _ (Pure a) = a
+iter phi (Free m) = phi (iter phi <$> m)
diff --git a/Control/Monad/Free/Class.hs b/Control/Monad/Free/Class.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Free/Class.hs
@@ -0,0 +1,64 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Monad.Free.Class
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable (fundeps, MPTCs)
+----------------------------------------------------------------------------
+module Control.Monad.Free.Class 
+  ( MonadFree(..)
+  ) where
+
+import Control.Applicative
+import Control.Monad.Trans.Reader
+import qualified Control.Monad.Trans.State.Strict as Strict
+import qualified Control.Monad.Trans.State.Lazy as Lazy
+import qualified Control.Monad.Trans.Writer.Strict as Strict
+import qualified Control.Monad.Trans.Writer.Lazy as Lazy
+import qualified Control.Monad.Trans.RWS.Strict as Strict
+import qualified Control.Monad.Trans.RWS.Lazy as Lazy
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.List
+import Control.Monad.Trans.Error
+import Control.Monad.Trans.Identity 
+import Data.Monoid
+
+class Monad m => MonadFree f m | m -> f where
+  wrap :: f (m a) -> m a
+
+instance (Functor f, MonadFree f m) => MonadFree f (ReaderT e m) where
+  wrap fm = ReaderT $ \e -> wrap $ flip runReaderT e <$> fm
+
+instance (Functor f, MonadFree f m) => MonadFree f (Lazy.StateT s m) where
+  wrap fm = Lazy.StateT $ \s -> wrap $ flip Lazy.runStateT s <$> fm
+
+instance (Functor f, MonadFree f m) => MonadFree f (Strict.StateT s m) where
+  wrap fm = Strict.StateT $ \s -> wrap $ flip Strict.runStateT s <$> fm
+
+instance (Functor f, MonadFree f m, Monoid w) => MonadFree f (Lazy.WriterT w m) where
+  wrap = Lazy.WriterT . wrap . fmap Lazy.runWriterT
+
+instance (Functor f, MonadFree f m, Monoid w) => MonadFree f (Strict.WriterT w m) where
+  wrap = Strict.WriterT . wrap . fmap Strict.runWriterT
+
+instance (Functor f, MonadFree f m, Monoid w) => MonadFree f (Strict.RWST r w s m) where
+  wrap fm = Strict.RWST $ \r s -> wrap $ fmap (\m -> Strict.runRWST m r s) fm
+
+instance (Functor f, MonadFree f m, Monoid w) => MonadFree f (Lazy.RWST r w s m) where
+  wrap fm = Lazy.RWST $ \r s -> wrap $ fmap (\m -> Lazy.runRWST m r s) fm
+
+instance (Functor f, MonadFree f m) => MonadFree f (MaybeT m) where
+  wrap = MaybeT . wrap . fmap runMaybeT
+
+instance (Functor f, MonadFree f m) => MonadFree f (IdentityT m) where
+  wrap = IdentityT . wrap . fmap runIdentityT 
+
+instance (Functor f, MonadFree f m) => MonadFree f (ListT m) where
+  wrap = ListT . wrap . fmap runListT
+
+instance (Functor f, MonadFree f m, Error e) => MonadFree f (ErrorT e m) where
+  wrap = ErrorT . wrap . fmap runErrorT
diff --git a/free.cabal b/free.cabal
--- a/free.cabal
+++ b/free.cabal
@@ -1,6 +1,6 @@
 name:          free
 category:      Control, Monads
-version:       0.2.3
+version:       1.8.0
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -9,8 +9,8 @@
 stability:     provisional
 homepage:      git://github.com/ekmett/free/
 copyright:     Copyright (C) 2008-2011 Edward A. Kmett
-synopsis:      Haskell 98 monads for free
-description:   Haskell 98 monads for free
+synopsis:      Monads for free
+description:   Monads for free
 build-type:    Simple
 
 source-repository head
@@ -22,9 +22,11 @@
     base >= 4 && < 4.4,
     distributive >= 0.2 && < 0.3,
     transformers >= 0.2.0 && <= 0.3,
+    mtl >= 2.0.1.0 && < 2.1,
     semigroupoids >= 1.2.2 && <= 1.3,
     comonad >= 1.1 && < 1.2,
-    comonad-transformers >= 1.6.3 && < 1.7,
+    comonad-transformers >= 1.8 && < 1.9,
+    comonads-fd >= 1.8 && < 1.9,
     semigroups >= 0.5 && < 0.6
 
   if impl(ghc)
@@ -34,6 +36,8 @@
 
   exposed-modules:
     Control.Monad.Free
+    Control.Monad.Free.Class
     Control.Comonad.Cofree
+    Control.Comonad.Cofree.Class
 
   ghc-options:      -Wall 
