diff --git a/Control/Monad/Exception.hs b/Control/Monad/Exception.hs
--- a/Control/Monad/Exception.hs
+++ b/Control/Monad/Exception.hs
@@ -1,67 +1,49 @@
-
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 module Control.Monad.Exception (
-    module Control.Monad.Exception,
+    EM,  evalEM,  runEM,
+    EMT(..), evalEMT, runEMT,
+    MonadZeroException(..),
     module Control.Monad.Exception.Class ) where
 
+import Control.Monad.Identity
 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 {unEM::Either SomeException a}
+type EM l = EMT l Identity
 
 -- | Run a computation which may fail
 evalEM :: EM (Caught SomeException l) a -> Either SomeException a
-evalEM (EM a) = a
+evalEM (EMT a) = mapLeft wrapException (runIdentity a)
 
+mapLeft :: (a -> b) -> Either a r -> Either b r
+mapLeft f (Left x)  = Left (f x)
+mapLeft _ (Right x) = Right x
+
 -- | Run a safe computation
 runEM :: EM l a -> a
-runEM (EM (Right a)) = a
-runEM _ = error "evalEM : The impossible happened"
-
-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
-
+runEM = runIdentity . runEMT
 
--- 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
+data MonadZeroException = MonadZeroException deriving (Show, Typeable)
+instance Exception MonadZeroException
 
-newtype EMT l m a = EMT {unEMT :: m (Either SomeException a)}
+newtype EMT l m a = EMT {unEMT :: m (Either (WrapException l) a)}
 
 evalEMT :: Monad m => EMT (Caught SomeException l) m a -> m (Either SomeException a)
-evalEMT (EMT m) = m
+evalEMT (EMT m) = mapLeft wrapException `liftM` m
 
 runEMT :: Monad m => EMT l m a -> m a
 runEMT (EMT m) = liftM f m where
   f (Right x) = x
-  f (Left  x) = error "evalEMT: The impossible happened"
+  f (Left  _) = error "evalEMT: The impossible happened"
 
 instance Monad m => Functor (EMT l m) where
   fmap f emt = EMT $ do
@@ -79,19 +61,19 @@
                   Right x -> unEMT (f x)
 
 instance (Exception e, Throws e l, Monad m) => MonadThrow e (EMT l m) where
-  throw = EMT . return . Left . toException
+  throw = EMT . return . Left . WrapException . toException
 instance (Exception e, Monad m) => MonadCatch e (EMT (Caught e l) m) (EMT l m) where
   catch emt h = EMT $ do
                 v <- unEMT emt
                 case v of
                   Right x -> return (Right x)
-                  Left  e -> case fromException e of
-                               Nothing -> return (Left e)
+                  Left (WrapException e) -> case fromException e of
+                               Nothing -> return (Left (WrapException e))
                                Just e' -> unEMT (h e')
 
 
-instance (Monad m, Throws MonadZero l) => MonadPlus (EMT l m) where
-  mzero = throw MonadZero
+instance (Monad m, Throws MonadZeroException l) => MonadPlus (EMT l m) where
+  mzero = throw MonadZeroException
   mplus emt1 emt2 = EMT$ do
                      v1 <- unEMT emt1
                      case v1 of
@@ -105,7 +87,7 @@
                                              Right r -> r
                                              _       -> error "empty fix argument"
 
-instance MonadIO m => MonadIO (EMT l m) where
+instance (Throws SomeException l, MonadIO m) => MonadIO (EMT l m) where
   liftIO = lift . liftIO
 
 instance MonadCont m => MonadCont (EMT l m) where
diff --git a/Control/Monad/Exception/Class.hs b/Control/Monad/Exception/Class.hs
--- a/Control/Monad/Exception/Class.hs
+++ b/Control/Monad/Exception/Class.hs
@@ -1,7 +1,14 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
 module Control.Monad.Exception.Class (
        module Control.Monad,
-       module Control.Monad.Exception.Class,
-       Exception(..), SomeException) where
+       MonadThrow(..), MonadCatch(..),
+       Throws, Caught,
+       WrapException(..), Exception(..), SomeException) where
 
 import Control.Monad
 import Control.Monad.Trans
@@ -11,11 +18,29 @@
 import Control.Monad.Trans.State
 import Control.Monad.Trans.Writer
 import Control.Monad.Trans.RWS
+#if __GLASGOW_HASKELL__ < 610
+import Control.Exception.Extensible (Exception(..), SomeException)
+import qualified Control.Exception.Extensible as Control.Exception
+#else
 import Control.Exception (Exception(..), SomeException)
 import qualified Control.Exception
+#endif
 import Data.Monoid
 import Prelude hiding (catch)
 
+{-| @Throws@ is the mechanism used to keep a type level
+    list of exceptions.
+    .
+    Usually there is no need for the user of this library
+    to add further instances to @Throws@ except in one
+    case: to encode subtyping. For instance if we have
+    an @IOException@ type and a @FIleNotFoundException@ subcase,
+    we need to add the instance:
+
+ > instance Throws FileNotFoundException (Caught IOException l)
+
+-}
+
 class Exception e => Throws e s
 
 class Monad m => MonadThrow e m where
@@ -25,27 +50,37 @@
    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
+   catch   :: m a -> (e -> m' a) -> m' a
 
 instance Exception e => MonadCatch e IO IO where
-   catch = Control.Exception.catch
+   catch   = Control.Exception.catch
 
+-- | A type level witness of a exception handler.
 data Caught e l
 
 instance Exception e => Throws e (Caught e l)
 instance Throws e l => Throws e (Caught e1 l)
+-- | @SomeException@ is at the top of the exception hierarchy
+--   .
+--   Capturing SomeException captures every possible exception
 instance Exception e => Throws e (Caught SomeException l)
 
--- Throw and Catch instances for the Either and ErrorT monads
+-- Labelled SomeException
+-- ------------------------
+newtype WrapException l = WrapException {wrapException::SomeException} deriving Show
 
+
+-- 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)
 
+-- 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))
 
diff --git a/control-monad-exception.cabal b/control-monad-exception.cabal
--- a/control-monad-exception.cabal
+++ b/control-monad-exception.cabal
@@ -1,5 +1,5 @@
 name: control-monad-exception
-version: 0.1.2
+version: 0.2
 Cabal-Version:  >= 1.2.3
 build-type: Simple
 license: PublicDomain
@@ -37,11 +37,27 @@
 synopsis: Explicitly typed exceptions
 category: Control, Monads
 stability: experimental
+tested-with: GHC ==6.8.2
+tested-with: GHC ==6.10.2
+tested-with: GHC ==6.10.3
 
+Flag extensibleExceptions
+  description: Use extensible-exception package
+  default: False
 
 Library
   buildable: True
-  build-depends: base >= 4.0, transformers, monads-fd
+  if flag(extensibleExceptions)
+    build-depends:
+      extensible-exceptions >= 0.1 && <0.2,
+      base >= 3.0 && <4
+  else
+    build-depends:
+      base >= 4.0
+
+  build-depends:
+    transformers >= 0.0.1 && <0.2,
+    monads-fd >= 0.0 && <0.1
   extensions:  MultiParamTypeClasses, 
                FunctionalDependencies,
                OverlappingInstances, 
@@ -52,3 +68,4 @@
   exposed-modules:
      Control.Monad.Exception.Class
      Control.Monad.Exception
+  ghc-options: -Wall -fno-warn-name-shadowing
