diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2011, Mikhail Vorozhtsov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, 
+  this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright 
+  notice, this list of conditions and the following disclaimer in the 
+  documentation and/or other materials provided with the distribution.
+- Neither the names of the copyright owners nor the names of the 
+  contributors may be used to endorse or promote products derived 
+  from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/monad-abort-fd.cabal b/monad-abort-fd.cabal
new file mode 100644
--- /dev/null
+++ b/monad-abort-fd.cabal
@@ -0,0 +1,36 @@
+Name: monad-abort-fd
+Version: 0.1
+Category: Control
+Stability: experimental
+Synopsis: A better error monad transformer
+Description:
+  This package provides automated lifting of operations via functional
+  dependencies for the @transformers-abort@ package.
+
+Homepage: https://github.com/mvv/monad-abort-fd
+Bug-Reports: https://github.com/mvv/monad-abort-fd/issues
+
+Author: Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>
+Maintainer: Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>
+Copyright: 2011 Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>
+License: BSD3
+License-File: LICENSE
+
+Cabal-Version: >= 1.6.0
+Build-Type: Simple
+
+Source-Repository head
+  Type: git
+  Location: https://github.com/mvv/monad-abort-fd.git
+
+Library
+  Build-Depends:
+    base               >= 4 && < 5,
+    transformers-abort >= 0.1,
+    mtl                >= 2.0
+  Hs-Source-Dirs: src
+  GHC-Options: -Wall
+  Exposed-Modules:
+    Control.Monad.Abort.Class
+    Control.Monad.Abort
+
diff --git a/src/Control/Monad/Abort.hs b/src/Control/Monad/Abort.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/Abort.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE UnicodeSyntax #-}
+
+module Control.Monad.Abort (
+    MonadAbort(..),
+    MonadRecover(..),
+
+    Abort,
+    runAbort,
+    runAbort',
+
+    AbortT(..),
+    runAbortT',
+
+    module Control.Monad,
+    module Control.Monad.Fix,
+    module Control.Monad.Trans
+  ) where
+
+import Control.Monad
+import Control.Monad.Fix
+import Control.Monad.Instances ()
+import Control.Monad.Trans
+import Control.Monad.Trans.Abort hiding (abort, recover)
+import Control.Monad.Abort.Class
+
diff --git a/src/Control/Monad/Abort/Class.hs b/src/Control/Monad/Abort/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/Abort/Class.hs
@@ -0,0 +1,123 @@
+{-# LANGUAGE UnicodeSyntax #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+module Control.Monad.Abort.Class (
+    MonadAbort(..),
+    MonadRecover(..)
+  ) where
+
+import Data.Monoid
+import Control.Monad.Cont
+import Control.Monad.Error
+import Control.Monad.List
+import Control.Monad.Reader
+import Control.Monad.State (MonadState(..))
+import qualified Control.Monad.State.Lazy as L
+import qualified Control.Monad.State.Strict as S
+import Control.Monad.Writer (MonadWriter(..))
+import qualified Control.Monad.Writer.Lazy as L
+import qualified Control.Monad.Writer.Strict as S
+import Control.Monad.RWS (MonadRWS)
+import qualified Control.Monad.RWS.Lazy as L
+import qualified Control.Monad.RWS.Strict as S
+import Control.Monad.Trans.Abort (AbortT(..))
+import qualified Control.Monad.Trans.Abort as A
+
+class Monad μ ⇒ MonadAbort e μ | μ → e where
+  abort ∷ e → μ α
+
+class MonadAbort e μ ⇒ MonadRecover e μ | μ → e where
+  recover ∷ μ α → (e → μ α) → μ α
+
+instance Monad μ ⇒ MonadAbort e (AbortT e μ) where
+  abort = A.abort
+
+instance Monad μ ⇒ MonadRecover e (AbortT e μ) where
+  recover = A.recover
+
+instance Monad μ ⇒ MonadError e (AbortT e μ) where
+  throwError = A.abort
+  catchError = A.recover
+
+instance MonadCont μ ⇒ MonadCont (AbortT e μ) where
+  callCC k = AbortT $ callCC $ \f → runAbortT $ k (lift . f . Right) 
+
+instance MonadReader r μ ⇒ MonadReader r (AbortT e μ) where
+  ask = lift ask
+  local f = AbortT . local f . runAbortT
+
+instance MonadState s μ ⇒ MonadState s (AbortT e μ) where
+  get = lift get
+  put = lift . put
+
+instance MonadWriter w μ ⇒ MonadWriter w (AbortT e μ) where
+  tell = lift . tell
+  listen m = AbortT $ do
+    (lr, w) ← listen $ runAbortT m
+    return $! fmap (, w) lr
+  pass m = AbortT $ pass $ do
+    lr ← runAbortT m
+    return $! either ((, id) . Left) (\(r, f) → (Right r, f)) lr
+
+instance MonadRWS r w s μ ⇒ MonadRWS r w s (AbortT e μ)
+
+instance MonadAbort e μ ⇒ MonadAbort e (ContT r μ) where
+  abort = lift . abort
+
+instance MonadAbort e μ ⇒ MonadAbort e (ListT μ) where
+  abort = lift . abort
+
+instance MonadRecover e μ ⇒ MonadRecover e (ListT μ) where
+  recover m h = ListT $ runListT m `recover` (runListT . h)
+
+instance MonadAbort e μ ⇒ MonadAbort e (ReaderT r μ) where
+  abort = lift . abort
+
+instance MonadRecover e μ ⇒ MonadRecover e (ReaderT r μ) where
+  recover m h = ReaderT $ \r → runReaderT m r `recover` ((`runReaderT` r) . h)
+
+instance MonadAbort e μ ⇒ MonadAbort e (L.StateT s μ) where
+  abort = lift . abort
+
+instance MonadRecover e μ ⇒ MonadRecover e (L.StateT s μ) where
+  recover m h = L.StateT $ \s →
+    L.runStateT m s `recover` ((`L.runStateT` s) . h)
+
+instance MonadAbort e μ ⇒ MonadAbort e (S.StateT s μ) where
+  abort = lift . abort
+
+instance MonadRecover e μ ⇒ MonadRecover e (S.StateT s μ) where
+  recover m h = S.StateT $ \s →
+    S.runStateT m s `recover` ((`S.runStateT` s) . h)
+
+instance (MonadAbort e μ, Monoid w) ⇒ MonadAbort e (L.WriterT w μ) where
+  abort = lift . abort
+
+instance (MonadRecover e μ, Monoid w) ⇒ MonadRecover e (L.WriterT w μ) where
+  recover m h = L.WriterT $ L.runWriterT m `recover` (L.runWriterT . h)
+
+instance (MonadAbort e μ, Monoid w) ⇒ MonadAbort e (S.WriterT w μ) where
+  abort = lift . abort
+
+instance (MonadRecover e μ, Monoid w) ⇒ MonadRecover e (S.WriterT w μ) where
+  recover m h = S.WriterT $ S.runWriterT m `recover` (S.runWriterT . h)
+
+instance (MonadAbort e μ, Monoid w) ⇒ MonadAbort e (L.RWST r w s μ) where
+  abort = lift . abort
+
+instance (MonadRecover e μ, Monoid w) ⇒ MonadRecover e (L.RWST r w s μ) where
+  recover m h = L.RWST $ \r s →
+    L.runRWST m r s `recover` (\e → L.runRWST (h e) r s)
+
+instance (MonadAbort e μ, Monoid w) ⇒ MonadAbort e (S.RWST r w s μ) where
+  abort = lift . abort
+
+instance (MonadRecover e μ, Monoid w) ⇒ MonadRecover e (S.RWST r w s μ) where
+  recover m h = S.RWST $ \r s →
+    S.runRWST m r s `recover` (\e → S.runRWST (h e) r s)
+
