diff --git a/Control/Monad/Exception.hs b/Control/Monad/Exception.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Exception.hs
@@ -0,0 +1,116 @@
+{-# LANGUAGE UndecidableInstances #-}
+module Control.Monad.Exception (
+    module Control.Monad.Exception,
+    module Control.Monad.Exception.Class ) where
+
+import Control.Monad.Exception.Class
+import Control.Monad.Fix
+import Control.Monad.Trans
+import Control.Monad.Cont.Class
+import Control.Monad.Reader.Class
+import Control.Monad.State.Class
+import Control.Monad.Writer.Class
+import Control.Monad.RWS.Class
+import Data.Monoid
+import Data.Typeable
+import Prelude hiding (catch)
+
+newtype EM l a = EM {runEM::Either SomeException a}
+
+instance Functor (EM l) where
+    fmap f (EM (Left e))  = EM (Left e)
+    fmap f (EM (Right x)) = EM (Right (f x))
+
+instance Monad (EM l) where
+  return = EM . Right
+  EM (Right x) >>= f = f x
+  EM (Left e) >>= _ = EM (Left e)
+
+instance (Exception e, Throws e l) => MonadThrow e (EM l) where
+  throw = EM . Left . toException
+instance Exception e => MonadCatch e (EM (Caught e l)) (EM l) where
+  catch (EM(Right x)) h = EM (Right x)
+  catch (EM(Left  e)) h = case fromException e of
+                            Nothing -> EM (Left e)
+                            Just e' -> h e'
+
+data MonadZero = MonadZero deriving (Show, Typeable)
+instance Exception MonadZero
+
+
+-- Requires undecidable instances
+instance Throws MonadZero l => MonadPlus (EM l) where
+  mzero                    = throw MonadZero
+  mplus (EM (Left _))   p2 = p2
+  mplus p1@(EM Right{}) p2 = p1
+
+newtype EMT l m a = EMT {runEMT :: m (Either SomeException a)}
+
+instance Monad m => Functor (EMT l m) where
+  fmap f emt = EMT $ do
+                 v <- runEMT emt
+                 case v of
+                   Left  e -> return (Left e)
+                   Right x -> return (Right (f x))
+
+instance Monad m => Monad (EMT l m) where
+  return = EMT . return . Right
+  emt >>= f = EMT $ do
+                v <- runEMT emt
+                case v of
+                  Left e  -> return (Left e)
+                  Right x -> runEMT (f x)
+
+instance (Exception e, Throws e l, Monad m) => MonadThrow e (EMT l m) where
+  throw = EMT . return . Left . toException
+instance (Exception e, Monad m) => MonadCatch e (EMT (Caught e l) m) (EMT l m) where
+  catch emt h = EMT $ do
+                v <- runEMT emt
+                case v of
+                  Right x -> return (Right x)
+                  Left  e -> case fromException e of
+                               Nothing -> return (Left e)
+                               Just e' -> runEMT (h e')
+
+
+instance (Monad m, Throws MonadZero l) => MonadPlus (EMT l m) where
+  mzero = throw MonadZero
+  mplus emt1 emt2 = EMT$ do
+                     v1 <- runEMT emt1
+                     case v1 of
+                       Left _  -> runEMT emt2
+                       Right _ -> return v1
+
+instance MonadTrans (EMT l) where lift = EMT . liftM Right
+
+instance MonadFix m => MonadFix (EMT l m) where
+  mfix f = EMT $ mfix $ \a -> runEMT $ f $ case a of
+                                             Right r -> r
+                                             _       -> error "empty fix argument"
+
+instance MonadIO m => MonadIO (EMT l m) where
+  liftIO = lift . liftIO
+
+instance MonadCont m => MonadCont (EMT l m) where
+  callCC f = EMT $ callCC $ \c -> runEMT (f (\a -> EMT $ c (Right a)))
+
+instance MonadReader r m => MonadReader r (EMT l m) where
+  ask = lift ask
+  local f m = EMT (local f (runEMT m))
+
+instance MonadState s m => MonadState s (EMT l m) where
+  get = lift get
+  put = lift . put
+
+instance (Monoid w, MonadWriter w m) => MonadWriter w (EMT l m) where
+  tell   = lift . tell
+  listen m = EMT $ do
+               (res, w) <- listen (runEMT m)
+               return (fmap (\x -> (x,w)) res)
+  pass m   = EMT $ pass $ do
+               a <- runEMT m
+               case a of
+                 Left  l     -> return (Left l, id)
+                 Right (r,f) -> return (Right r, f)
+
+instance (Monoid w, MonadRWS r w s m) => MonadRWS r w s (EMT l m)
diff --git a/Control/Monad/Exception/Class.hs b/Control/Monad/Exception/Class.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Exception/Class.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE UndecidableInstances #-}
+module Control.Monad.Exception.Class (
+       module Control.Monad,
+       module Control.Monad.Exception.Class,
+       Exception(..), SomeException) where
+
+import Control.Monad
+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
+import Control.Exception (Exception(..), SomeException)
+import qualified Control.Exception
+import Data.Monoid
+import Prelude hiding (catch)
+
+class Exception e => Throws e s
+
+class Monad m => MonadThrow e m where
+    throw :: e -> m a
+
+instance Exception e => MonadThrow e IO where
+   throw = Control.Exception.throw
+
+class (Monad m, Monad m') => MonadCatch e m m' | e m -> m', e m' -> m where
+   catch :: m a -> (e -> m' a) -> m' a
+
+instance Exception e => MonadCatch e IO IO where
+   catch = Control.Exception.catch
+
+data Caught e l
+
+instance Exception e => Throws e (Caught e l)
+instance Throws e l => Throws e (Caught e1 l)
+instance Exception e => Throws e (Caught SomeException l)
+
+-- Throw and Catch instances for the Either and ErrorT monads
+
+instance (Error e) => MonadThrow e (Either e) where throw = Left
+instance (Error e) => MonadCatch e (Either e) (Either e) where catch m h = either h Right m
+
+instance (Error e, Monad m) => MonadThrow e (ErrorT e m) where throw = throwError
+instance (Error e, Monad m) => MonadCatch e (ErrorT e m) (ErrorT e m) where catch = catchError
+
+-- Instances for transformers (requires undecidable instances in some cases)
+
+instance MonadThrow e m    => MonadThrow e (ListT m)            where throw = lift . throw
+instance MonadCatch e m m' => MonadCatch e (ListT m) (ListT m') where catch (ListT m) h = ListT (catch m (runListT . h))
+
+instance MonadThrow e m    => MonadThrow e (ReaderT r m)                where throw = lift . throw
+instance MonadCatch e m m' => MonadCatch e (ReaderT r m) (ReaderT r m') where catch (ReaderT m) h = ReaderT (\s -> catch (m s) ((`runReaderT` s) . h))
+
+instance (Monoid w, MonadThrow e m)    => MonadThrow e (WriterT w  m)               where throw = lift . throw
+instance (Monoid w, MonadCatch e m m') => MonadCatch e (WriterT w m) (WriterT w m') where catch (WriterT m) h = WriterT (catch m (runWriterT . h))
+
+instance MonadThrow e m    => MonadThrow e (StateT s m)               where throw = lift . throw
+instance MonadCatch e m m' => MonadCatch e (StateT s m) (StateT s m') where catch (StateT m) h = StateT (\s -> catch (m s) ((`runStateT` s) . h))
+
+instance (Monoid w, MonadThrow e m)    => MonadThrow e (RWST r w s m)                 where throw = lift . throw
+instance (Monoid w, MonadCatch e m m') => MonadCatch e (RWST r w s m) (RWST r w s m') where catch (RWST m) h = RWST (\r s -> catch (m r s) ((\m -> runRWST m r s) . h))
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/control-monad-exception.cabal b/control-monad-exception.cabal
new file mode 100644
--- /dev/null
+++ b/control-monad-exception.cabal
@@ -0,0 +1,53 @@
+name: control-monad-exception
+version: 0.1
+Cabal-Version:  >= 1.2.3
+build-type: Simple
+license: PublicDomain
+author: Pepe Iborra
+maintainer: pepeiborra@gmail.com
+homepage: http://github.com/pepeiborra/control-monad-exception
+description: 
+  This package provides explicitly typed exceptions as a library.
+  .
+  /Example/
+  .
+  > data Expr = Add Expr Expr | Div Expr Expr | Val Double
+  > eval (Val x)     = return x
+  > eval (Add a1 a2) = do
+  >    v1 <- eval a1
+  >    v2 <- eval a2
+  >    let sum = v1 + v2
+  >    if sum < v1 || sum < v2 then throw SumOverflow else return sum
+  > eval (Div a1 a2) = do
+  >    v1 <- eval a1
+  >    v2 <- eval a2
+  >    if v2 == 0 then throw DivideByZero else return (v1 / v2)
+  .
+  > data DivideByZero = DivideByZero deriving (Show, Typeable)
+  > data SumOverflow  = SumOverflow  deriving (Show, Typeable)
+  .
+  > instance Exception DivideByZero
+  > instance Exception SumOverflow
+  .
+  GHCi infers the following types
+  .
+  > eval :: (Throws DivideByZero l, Throws SumOverflow l) => Expr -> EM l Double
+  > eval `catch` \ (e::DivideByZero) -> return (-1)  :: Throws SumOverflow l => Expr -> EM l Double
+synopsis: Explicitly typed exceptions
+category: Control, Monads
+stability: experimental
+
+
+Library
+  buildable: True
+  build-depends: base >= 4.0, transformers, monads-fd
+  extensions:  MultiParamTypeClasses, 
+               FunctionalDependencies,
+               OverlappingInstances, 
+               FlexibleInstances,
+               EmptyDataDecls,
+               DeriveDataTypeable,
+               UndecidableInstances
+  exposed-modules:
+     Control.Monad.Exception.Class
+     Control.Monad.Exception
