diff --git a/Control/Monad/CatchIO.hs b/Control/Monad/CatchIO.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/CatchIO.hs
@@ -0,0 +1,51 @@
+module Control.Monad.CatchIO ( MonadCatchIO(..),
+                               E.Exception(..),
+                               throw,
+                               try, tryJust,
+                               Handler(..), catches )
+
+where
+
+import Prelude hiding ( catch )
+
+import qualified Control.Exception as E
+
+import Control.Monad.Reader
+import Control.Monad.State
+import Control.Monad.Error
+import Control.Monad.Writer
+import Control.Monad.RWS
+
+class MonadIO m => MonadCatchIO m where
+    -- | Generalized version of 'E.catch'
+    catch   :: E.Exception e => m a -> (e -> m a) -> m a
+ 
+    -- | Generalized version of 'E.block'
+    block   :: m a -> m a
+
+    -- | Generalized version of 'E.unblock'
+    unblock :: m a -> m a
+
+-- | Generalized version of 'E.throwIO'
+throw :: (MonadCatchIO m, E.Exception e) => e -> m a
+
+-- | Generalized version of 'E.try'
+try :: (MonadCatchIO m, E.Exception e) => m a -> m (Either e a)
+
+-- | Generalized version of 'E.tryJust'
+tryJust :: (MonadCatchIO m, E.Exception e)
+        => (e -> Maybe b) -> m a -> m (Either b a)
+
+-- | Generalized version of 'E.Handler'
+data Handler m a = forall e . E.Exception e => Handler (e -> m a)
+
+-- | Generalized version of 'E.catches'
+catches :: MonadCatchIO m => m a -> [Handler m a] -> m a
+catches a handlers = a `catch` handler
+    where handler e = foldr tryH (throw e) handlers
+            where tryH (Handler h) res = case E.fromException e of
+                                             Just e' -> h e'
+                                             Nothing -> res
+
+
+#include "generic-code.inc"
diff --git a/Control/Monad/CatchIO/Old.hs b/Control/Monad/CatchIO/Old.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/CatchIO/Old.hs
@@ -0,0 +1,57 @@
+module Control.Monad.CatchIO.Old ( MonadCatchIO(..),
+                                   E.Exception(..),
+                                   throw,
+                                   throwDyn, catchDyn,
+                                   try, tryJust )
+
+where
+
+#if __BASE_VERSION__ == 3
+import qualified Control.Exception as E
+#else
+import qualified Control.OldException as E
+#endif
+
+import Prelude hiding ( catch )
+
+import Data.Dynamic
+
+import Control.Monad.Reader
+import Control.Monad.State
+import Control.Monad.Error
+import Control.Monad.Writer
+import Control.Monad.RWS
+
+class MonadIO m => MonadCatchIO m where
+    -- | Generalized version of 'E.catch'
+    catch :: m a -> (E.Exception -> m a) -> m a
+
+    -- | Generalized version of 'E.block'
+    block   :: m a -> m a
+
+    -- | Generalized version of 'E.unblock'
+    unblock :: m a -> m a
+
+-- | Generalized version of 'E.throwIO'
+throw :: MonadCatchIO m => E.Exception -> m a
+
+-- | Generalized version of 'E.try'
+try :: MonadCatchIO m => m a -> m (Either E.Exception a)
+
+-- | Generalized version of 'E.tryJust'
+tryJust :: MonadCatchIO m => (E.Exception -> Maybe b) -> m a -> m (Either b a)
+
+
+
+#include "../generic-code.inc"
+
+throwDyn :: Typeable e => e -> b
+throwDyn = E.throw . E.DynException . toDyn
+
+catchDyn :: (Typeable e, MonadCatchIO m) => m a -> (e -> m a) -> m a
+catchDyn a f = a `catch` handler
+    where handler e = case e of
+                        E.DynException dyn -> case fromDynamic dyn of
+                                                Just exception  -> f exception
+                                                Nothing         -> E.throw e
+                        _                  -> E.throw e
diff --git a/MonadCatchIO-mtl.cabal b/MonadCatchIO-mtl.cabal
new file mode 100644
--- /dev/null
+++ b/MonadCatchIO-mtl.cabal
@@ -0,0 +1,42 @@
+name:                MonadCatchIO-mtl
+version:             0.1.0.0
+description:
+        Provides a monad-transformer version of the @Control.Exception.catch@
+        function. For this, it defines the @MonadCatchIO@ class, a subset of
+        @MonadIO@. It defines proper instances for most monad transformers in
+        the 'mtl' library.
+
+synopsis:           Monad-transformer version of the Control.Exception module
+category:           Control
+license:            PublicDomain
+maintainer:         jcpetruzza@gmail.com
+homepage:           http://code.haskell.org/~jcpetruzza/MonadCatchIO-mtl
+
+cabal-version:      >= 1.2
+build-type:         Simple
+tested-with:        GHC==6.10
+
+Flag base3
+  description: Don't expect the new Control.Exception module (prior to base-4)
+  default: False
+
+Library
+  build-depends:    mtl
+  ghc-options:      -Wall
+  extensions:       CPP
+                    ExistentialQuantification
+
+  if flag(base3) {
+    build-depends: base < 4
+  } else {
+    build-depends: base >= 4
+  }
+
+  exposed-modules: Control.Monad.CatchIO.Old
+
+  if flag(base3) {
+    cpp-options: -D__BASE_VERSION__=3
+  } else {
+    cpp-options: -D__BASE_VERSION__=4
+    exposed-modules:  Control.Monad.CatchIO
+  }
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,5 @@
+#!/usr/bin/env runhaskell
+> module Main where
+> import Distribution.Simple
+> main :: IO ()
+> main = defaultMainWithHooks defaultUserHooks
