diff --git a/Control/Monad/Failure.hs b/Control/Monad/Failure.hs
--- a/Control/Monad/Failure.hs
+++ b/Control/Monad/Failure.hs
@@ -1,62 +1,3 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE OverlappingInstances #-}
-
-{-| Defines the class @MonadFailure@ for monads which can fail.
--}
-module Control.Monad.Failure where
-
-import Control.Exception (throw, Exception)
-import Control.Monad
-#if TRANSFORMERS
-import Control.Monad.Trans
-import Control.Monad.Trans.Error
-import Control.Monad.Trans.List
-import Control.Monad.Trans.Reader
-import Control.Monad.Trans.State
-import Control.Monad.Trans.Writer
-import Control.Monad.Trans.RWS
-#else
-import Control.Monad.Error
-import Control.Monad.List
-import Control.Monad.Reader
-import Control.Monad.State
-import Control.Monad.Writer
-import Control.Monad.RWS
-#endif
-
-import Data.Monoid
-
-class Monad m => MonadFailure e m where
-    failure :: e -> m a
-
--- ----------
--- Instances
--- ----------
-instance MonadFailure e Maybe where failure _ = Nothing
-instance MonadFailure e []    where failure _ = []
-
-instance Exception e => MonadFailure e IO where
-  failure = Control.Exception.throw
-
-instance (Error e) => MonadFailure e (Either e) where
-  failure = Left
-
-instance (Error e, Monad m) => MonadFailure e (ErrorT e m) where
-  failure = throwError
-
-instance MonadFailure e m => MonadFailure e (ListT m) where
-  failure = lift . failure
-
-instance MonadFailure e m => MonadFailure e (ReaderT r m) where
-  failure = lift . failure
-
-instance (Monoid w, MonadFailure e m) => MonadFailure e (WriterT w  m) where
-  failure = lift . failure
-
-instance MonadFailure e m => MonadFailure e (StateT s m) where
-  failure = lift . failure
+module Control.Monad.Failure (module Control.Monad.Failure.Class) where
 
-instance (Monoid w, MonadFailure e m) => MonadFailure e (RWST r w s m) where
-  failure = lift . failure
+import Control.Monad.Failure.Class
diff --git a/Control/Monad/Failure/Class.hs b/Control/Monad/Failure/Class.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Failure/Class.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE Rank2Types #-}
+{-| Defines the class @MonadFailure@ for monads which can fail.
+-}
+module Control.Monad.Failure.Class where
+
+import Control.Exception (throw, Exception)
+
+class Monad m => MonadFailure e m where
+    failure :: e -> m a
+
+class MonadFailure e m => WrapFailure e m where
+    -- | Wrap the failure value, if any, with the given function. This is
+    -- useful in particular when you want all the exceptions returned from a
+    -- certain library to be of a certain type, even if they were generated by
+    -- a different library.
+    wrapFailure :: (forall eIn. Exception eIn => eIn -> e) -> m a -> m a
+
+-- --------------
+-- base instances
+-- --------------
+
+instance MonadFailure e Maybe where failure _ = Nothing
+instance MonadFailure e []    where failure _ = []
+
+instance Exception e => MonadFailure e IO where
+  failure = Control.Exception.throw
diff --git a/Control/Monad/Failure/Mtl.hs b/Control/Monad/Failure/Mtl.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Failure/Mtl.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+module Control.Monad.Failure.Mtl (module Control.Monad.Failure.Class) where
+
+import Control.Monad.Failure.Class
+
+import Control.Monad.Error
+import Control.Monad.List
+import Control.Monad.Reader
+import Control.Monad.State.Lazy     as Lazy
+import Control.Monad.State.Strict   as Strict
+import Control.Monad.Writer.Lazy    as Lazy
+import Control.Monad.Writer.Strict  as Strict
+import Control.Monad.RWS.Lazy       as Lazy
+import Control.Monad.RWS.Strict     as Strict
+import Data.Monoid
+
+-- -----------------------
+-- MonadFailure Instances
+-- -----------------------
+
+instance (Error e, Monad m) => MonadFailure e (ErrorT e m) where
+  failure = throwError
+
+instance MonadFailure e m => MonadFailure e (ListT m) where
+  failure = lift . failure
+
+instance MonadFailure e m => MonadFailure e (ReaderT r m) where
+  failure = lift . failure
+
+instance (Monoid w, MonadFailure e m) => MonadFailure e (Lazy.WriterT w  m) where
+  failure = lift . failure
+
+instance MonadFailure e m => MonadFailure e (Lazy.StateT s m) where
+  failure = lift . failure
+
+instance (Monoid w, MonadFailure e m) => MonadFailure e (Lazy.RWST r w s m) where
+  failure = lift . failure
+
+instance (Monoid w, MonadFailure e m) => MonadFailure e (Strict.WriterT w  m) where
+  failure = lift . failure
+
+instance MonadFailure e m => MonadFailure e (Strict.StateT s m) where
+  failure = lift . failure
+
+instance (Monoid w, MonadFailure e m) => MonadFailure e (Strict.RWST r w s m) where
+  failure = lift . failure
+
+-- ---------------------
+-- WrapFailure instances
+-- ---------------------
+
+instance WrapFailure e m => WrapFailure e (ListT m) where
+  wrapFailure f = ListT . wrapFailure f . runListT
+
+instance WrapFailure e m => WrapFailure e (ReaderT r m) where
+  wrapFailure f m = ReaderT $ \r -> wrapFailure f (runReaderT m r)
+
+instance (WrapFailure e m, Monoid w) => WrapFailure e (Lazy.WriterT w m) where
+  wrapFailure f = Lazy.WriterT . wrapFailure f . Lazy.runWriterT
+
+
+-- all the following instances require undecidable instances
+instance WrapFailure e m => WrapFailure e (Lazy.StateT s m) where
+  wrapFailure f m = Lazy.StateT $ \s -> wrapFailure f (Lazy.runStateT m s)
+
+instance (WrapFailure e m, Monoid w) => WrapFailure e (Lazy.RWST r w s m) where
+  wrapFailure f m = Lazy.RWST $ \r s -> wrapFailure f (Lazy.runRWST m r s)
+
+instance WrapFailure e m => WrapFailure e (Strict.StateT s m) where
+  wrapFailure f m = Strict.StateT $ \s -> wrapFailure f (Strict.runStateT m s)
+
+instance (WrapFailure e m, Monoid w) => WrapFailure e (Strict.RWST r w s m) where
+  wrapFailure f m = Strict.RWST $ \r s -> wrapFailure f (Strict.runRWST m r s)
diff --git a/Control/Monad/Failure/Transformers.hs b/Control/Monad/Failure/Transformers.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Failure/Transformers.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE PackageImports #-}
+
+module Control.Monad.Failure.Transformers (module Control.Monad.Failure.Class) where
+
+import Control.Monad.Failure.Class
+
+import Control.Exception (throw, catch, Exception, SomeException(..))
+import "transformers" Control.Monad.Trans
+import Control.Monad.Trans.Error
+import Control.Monad.Trans.List
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.State.Lazy     as Lazy
+import Control.Monad.Trans.State.Strict   as Strict
+import Control.Monad.Trans.Writer.Lazy    as Lazy
+import Control.Monad.Trans.Writer.Strict  as Strict
+import Control.Monad.Trans.RWS.Lazy       as Lazy
+import Control.Monad.Trans.RWS.Strict     as Strict
+import Data.Monoid
+
+-- -----------------------
+-- MonadFailure Instances
+-- -----------------------
+
+instance (Error e) => MonadFailure e (Either e) where
+  failure = Left
+
+instance (Error e, Monad m) => MonadFailure e (ErrorT e m) where
+  failure = throwError
+
+instance MonadFailure e m => MonadFailure e (ListT m) where
+  failure = lift . failure
+
+instance MonadFailure e m => MonadFailure e (ReaderT r m) where
+  failure = lift . failure
+
+instance (Monoid w, MonadFailure e m) => MonadFailure e (Lazy.WriterT w  m) where
+  failure = lift . failure
+
+instance MonadFailure e m => MonadFailure e (Lazy.StateT s m) where
+  failure = lift . failure
+
+instance (Monoid w, MonadFailure e m) => MonadFailure e (Lazy.RWST r w s m) where
+  failure = lift . failure
+
+instance (Monoid w, MonadFailure e m) => MonadFailure e (Strict.WriterT w  m) where
+  failure = lift . failure
+
+instance MonadFailure e m => MonadFailure e (Strict.StateT s m) where
+  failure = lift . failure
+
+instance (Monoid w, MonadFailure e m) => MonadFailure e (Strict.RWST r w s m) where
+  failure = lift . failure
+
+-- ---------------------
+-- WrapFailure instances
+-- ---------------------
+
+instance Exception e => WrapFailure e IO where
+  wrapFailure f m = m `Control.Exception.catch` \e@SomeException{} -> Control.Exception.throw (f e)
+
+instance WrapFailure e m => WrapFailure e (ListT m) where
+  wrapFailure f = ListT . wrapFailure f . runListT
+
+instance WrapFailure e m => WrapFailure e (ReaderT r m) where
+  wrapFailure f m = ReaderT $ \r -> wrapFailure f (runReaderT m r)
+
+instance (WrapFailure e m, Monoid w) => WrapFailure e (Lazy.WriterT w m) where
+  wrapFailure f = Lazy.WriterT . wrapFailure f . Lazy.runWriterT
+
+
+-- all the following instances require undecidable instances
+instance WrapFailure e m => WrapFailure e (Lazy.StateT s m) where
+  wrapFailure f m = Lazy.StateT $ \s -> wrapFailure f (Lazy.runStateT m s)
+
+instance (WrapFailure e m, Monoid w) => WrapFailure e (Lazy.RWST r w s m) where
+  wrapFailure f m = Lazy.RWST $ \r s -> wrapFailure f (Lazy.runRWST m r s)
+
+instance WrapFailure e m => WrapFailure e (Strict.StateT s m) where
+  wrapFailure f m = Strict.StateT $ \s -> wrapFailure f (Strict.runStateT m s)
+
+instance (WrapFailure e m, Monoid w) => WrapFailure e (Strict.RWST r w s m) where
+  wrapFailure f m = Strict.RWST $ \r s -> wrapFailure f (Strict.runRWST m r s)
diff --git a/control-monad-failure.cabal b/control-monad-failure.cabal
--- a/control-monad-failure.cabal
+++ b/control-monad-failure.cabal
@@ -1,5 +1,5 @@
 name: control-monad-failure
-version: 0.1
+version: 0.2
 Cabal-Version:  >= 1.2.3
 build-type: Simple
 license: PublicDomain
@@ -11,25 +11,19 @@
 category: Control, Monads
 stability: experimental
 
-Flag transformers
-   default: False
-
-Flag extensibleExceptionsInBase
+Flag mtl
+  default: True
 
 Library
   buildable: True
-  build-depends: pretty, template-haskell
-
-  if flag(transformers)
-     build-depends: transformers
-     cpp-options: -DTRANSFORMERS
-  else
-     build-depends: mtl
-  if flag(extensibleExceptionsInBase)
-     build-depends: base >= 4 && < 5
-  else
-     build-depends: base >= 3 && < 4, extensible-exceptions
+  build-depends: base >= 4 && < 5, transformers
 
   extensions:  MultiParamTypeClasses, FlexibleInstances
   exposed-modules:
      Control.Monad.Failure
+     Control.Monad.Failure.Class
+     Control.Monad.Failure.Transformers
+  if flag(mtl)
+    cpp-options: -DMTL
+    build-depends: mtl
+    exposed-modules: Control.Monad.Failure.Mtl
