diff --git a/Control/Error.hs b/Control/Error.hs
new file mode 100644
--- /dev/null
+++ b/Control/Error.hs
@@ -0,0 +1,31 @@
+{-|
+    Import this module in your code to access the entire library's
+    functionality:
+
+> import Control.Error
+
+    This module exports the entire library as well as useful exports from other
+    standard error-handling libraries.
+-}
+
+module Control.Error (
+    module Control.Error.Script,
+    module Control.Error.Safe,
+    module Control.Error.Util,
+    module Control.Monad.Trans.Either,
+    module Control.Monad.Trans.Maybe,
+    module Data.Either,
+    module Data.EitherR,
+    module Data.Maybe,
+    module Safe
+    ) where
+
+import Control.Error.Script
+import Control.Error.Safe
+import Control.Error.Util
+import Control.Monad.Trans.Either
+import Control.Monad.Trans.Maybe
+import Data.Either
+import Data.EitherR
+import Data.Maybe
+import Safe
diff --git a/Control/Error/Safe.hs b/Control/Error/Safe.hs
new file mode 100644
--- /dev/null
+++ b/Control/Error/Safe.hs
@@ -0,0 +1,141 @@
+{-|
+    This module extends the @safe@ library's functions with corresponding
+    versions compatible with 'Either' and 'EitherT'.
+
+    All functions take an exceptional value to return should they fail.
+
+    I suffix the 'Either'-compatible functions with @Err@ and prefix the
+    'EitherT'-compatible functions with @try@.
+
+    Note that this library re-exports the 'Maybe' compatible functions from
+    @safe@ in the "Control.Error" module, so they are not provided here.
+-}
+
+module Control.Error.Safe (
+    -- * Either-compatible functions
+    tailErr,
+    initErr,
+    headErr,
+    lastErr,
+    minimumErr,
+    maximumErr,
+    foldr1Err,
+    foldl1Err,
+    foldl1Err',
+    atErr,
+    readErr,
+    assertErr,
+    -- * EitherT-compatible functions
+    tryTail,
+    tryInit,
+    tryHead,
+    tryLast,
+    tryMinimum,
+    tryMaximum,
+    tryFoldr1,
+    tryFoldl1,
+    tryFoldl1',
+    tryAt,
+    tryRead,
+    tryAssert,
+    ) where
+
+import Control.Error.Util
+import Control.Monad.Trans.Either
+import Safe
+
+-- | A 'tail' that fails in the 'Either' monad
+tailErr :: e -> [a] -> Either e [a]
+tailErr e = note e . tailMay
+
+-- | An 'init' that fails in the 'Either' monad
+initErr :: e -> [a] -> Either e [a]
+initErr e = note e . initMay
+
+-- | A 'head' that fails in the 'Either' monad
+headErr :: e -> [a] -> Either e a
+headErr e = note e . headMay
+
+-- | A 'last' that fails in the 'Either' monad
+lastErr :: e -> [a] -> Either e a
+lastErr e = note e . lastMay
+
+-- | A 'minimum' that fails in the 'Either' monad
+minimumErr :: (Ord a) => e -> [a] -> Either e a
+minimumErr e = note e . minimumMay
+
+-- | A 'maximum' that fails in the 'Either' monad
+maximumErr :: (Ord a) => e -> [a] -> Either e a
+maximumErr e = note e . maximumMay
+
+-- | A 'foldr1' that fails in the 'Either' monad
+foldr1Err :: e -> (a -> a -> a) -> [a] -> Either e a
+foldr1Err e step xs = note e $ foldr1May step xs
+
+-- | A 'foldl1' that fails in the 'Either' monad
+foldl1Err :: e -> (a -> a -> a) -> [a] -> Either e a
+foldl1Err e step xs = note e $ foldl1May step xs
+
+-- | A 'foldl1'' that fails in the 'Either' monad
+foldl1Err' :: e -> (a -> a -> a) -> [a] -> Either e a
+foldl1Err' e step xs = note e $ foldl1May' step xs
+
+-- | A ('!!') that fails in the 'Either' monad
+atErr :: e -> [a] -> Int -> Either e a
+atErr e xs n = note e $ atMay xs n
+
+-- | A 'read' that fails in the 'Either' monad
+readErr :: (Read a) => e -> String -> Either e a
+readErr e = note e . readMay
+
+-- | An assertion that fails in the 'Either' monad
+assertErr :: e -> Bool -> a -> Either e a
+assertErr e p a = if p then Right a else Left e
+
+-- | A 'tail' that fails in the 'EitherT' monad
+tryTail :: (Monad m) => e -> [a] -> EitherT e m [a]
+tryTail e xs = liftEither $ tailErr e xs
+
+-- | An 'init' that fails in the 'EitherT' monad
+tryInit :: (Monad m) => e -> [a] -> EitherT e m [a]
+tryInit e xs = liftEither $ initErr e xs
+
+-- | A 'head' that fails in the 'EitherT' monad
+tryHead :: (Monad m) => e -> [a] -> EitherT e m a
+tryHead e xs = liftEither $ headErr e xs
+
+-- | A 'last' that fails in the 'EitherT' monad
+tryLast :: (Monad m) => e -> [a] -> EitherT e m a
+tryLast e xs = liftEither $ lastErr e xs
+
+-- | A 'minimum' that fails in the 'EitherT' monad
+tryMinimum :: (Monad m, Ord a) => e -> [a] -> EitherT e m a
+tryMinimum e xs = liftEither $ maximumErr e xs
+
+-- | A 'maximum' that fails in the 'EitherT' monad
+tryMaximum :: (Monad m, Ord a) => e -> [a] -> EitherT e m a
+tryMaximum e xs = liftEither $ maximumErr e xs
+
+-- | A 'foldr1' that fails in the 'EitherT' monad
+tryFoldr1 :: (Monad m) => e -> (a -> a -> a) -> [a] -> EitherT e m a
+tryFoldr1 e step xs = liftEither $ foldr1Err e step xs
+
+-- | A 'foldl1' that fails in the 'EitherT' monad
+tryFoldl1 :: (Monad m) => e -> (a -> a -> a) -> [a] -> EitherT e m a
+tryFoldl1 e step xs = liftEither $ foldl1Err e step xs
+
+-- | A 'foldl1'' that fails in the 'EitherT' monad
+tryFoldl1' :: (Monad m) => e -> (a -> a -> a) -> [a] -> EitherT e m a
+tryFoldl1' e step xs = liftEither $ foldl1Err' e step xs
+
+-- | A ('!!') that fails in the 'EitherT' monad
+tryAt :: (Monad m) => e -> [a] -> Int -> EitherT e m a
+tryAt e xs n = liftEither $ atErr e xs n
+
+-- | A 'read' that fails in the 'EitherT' monad
+tryRead :: (Monad m, Read a) => e -> String -> EitherT e m a
+tryRead e str = liftEither $ readErr e str
+
+-- | An assertion that fails in the 'EitherT' monad
+tryAssert :: (Monad m) => e -> Bool -> a -> EitherT e m a
+tryAssert e p a = liftEither $ assertErr e p a
diff --git a/Control/Error/Script.hs b/Control/Error/Script.hs
new file mode 100644
--- /dev/null
+++ b/Control/Error/Script.hs
@@ -0,0 +1,57 @@
+{-|
+    Use this module if you like to write simple scripts, but you prefer to use
+    'EitherT' to handle errors rather than @Control.Exception@.
+
+> import Control.Error
+>
+> main = runScript $ do
+>     str <- tryIO getLine
+>     n   <- tryRead "Read failed" str
+>     tryIO $ print (n + 1)
+-}
+
+module Control.Error.Script (
+    -- * The Script Monad
+    Script,
+    runScript,
+    tryMaybe,
+    tryEither,
+    tryIO
+    ) where
+
+import Control.Exception
+import Control.Monad.Trans.Either
+import Control.Error.Util
+import Data.EitherR
+import System.IO
+import System.Exit
+
+-- | An 'IO' action that can fail with a 'String' error message
+type Script = EitherT String IO
+
+{-|
+    Runs the 'Script' monad
+
+    Prints the first error to 'stderr' and exits with 'exitFailure'
+-}
+runScript :: Script a -> IO a
+runScript s = do
+    e <- runEitherT s
+    case e of
+        Left  e -> do
+            hPutStrLn stderr e
+            exitFailure
+        Right a -> return a
+
+-- | A 'Maybe' that fails in the 'Script' monad
+tryMaybe :: String -> Maybe a -> Script a
+tryMaybe str = tryEither . note str
+
+-- | An 'Either' that fails in the 'Script' monad
+tryEither :: Either String r -> Script r
+tryEither = liftEither
+
+-- | 'tryIO' is like 'lift', except it converts exceptions to the 'Script' monad
+tryIO :: IO a -> Script a
+tryIO io = EitherT . fmap (fmapL show)
+                   $ (try :: IO a -> IO (Either SomeException a)) io
diff --git a/Control/Error/Util.hs b/Control/Error/Util.hs
new file mode 100644
--- /dev/null
+++ b/Control/Error/Util.hs
@@ -0,0 +1,38 @@
+{-|
+    Use this module to convert between 'Maybe', 'Either', 'MaybeT', and
+    'EitherT'.
+-}
+
+module Control.Error.Util where
+
+import Control.Monad
+import Control.Monad.Trans.Either
+import Control.Monad.Trans.Maybe
+
+-- | Suppress the 'Left' value of an 'Either'
+hush :: Either a b -> Maybe b
+hush e = case e of
+    Left  _ -> Nothing
+    Right b -> Just b
+
+-- | Suppress the 'Left' value of an 'EitherT'
+hushT :: (Monad m) => EitherT a m b -> MaybeT m b
+hushT = MaybeT . liftM hush . runEitherT
+
+-- | Tag the 'Nothing' value of a 'Maybe'
+note :: a -> Maybe b -> Either a b
+note a m = case m of
+    Nothing -> Left  a
+    Just b  -> Right b
+
+-- | Tag the 'Nothing' value of a 'MaybeT'
+noteT :: (Monad m) => a -> MaybeT m b -> EitherT a m b
+noteT a = EitherT . liftM (note a) . runMaybeT
+
+-- | Lift a 'Maybe' to the 'MaybeT' monad
+liftMaybe :: (Monad m) => Maybe b -> MaybeT m b
+liftMaybe = MaybeT . return
+
+-- | Lift an 'Either' to the 'EitherT' monad
+liftEither :: (Monad m) => Either a b -> EitherT a m b
+liftEither = EitherT . return
diff --git a/Data/EitherR.hs b/Data/EitherR.hs
new file mode 100644
--- /dev/null
+++ b/Data/EitherR.hs
@@ -0,0 +1,142 @@
+{-|
+    This modules provides newtypes which flip the type variables of 'Either'
+    and 'EitherT' to access the symmetric monad over the opposite type variable.
+
+    This module provides the following simple benefits to the casual user:
+
+    * A type-class free alternative to @MonadError@
+
+    * No @UndecidableInstances@ or any other extensions, for that matter
+
+    * A more powerful 'catchE' statement that allows you to change the type of
+      error value returned
+
+    More advanced users can take advantage of the fact that 'EitherR' and
+    'EitherRT' define an entirely symmetric \"success monad\" where
+    error-handling computations are the default and successful results terminate
+    the monad.  This allows you to chain error-handlers and pass around values
+    other than exceptions until you can finally recover from the error:
+
+> runEitherRT $ do
+>     e2 <- ioExceptionHandler e1
+>     bool <- arithmeticExceptionhandler e2
+>     when bool $ lift $ putStrLn "DEBUG: Arithmetic handler did something"
+
+    If any of the above error handlers 'succeed', no other handlers are tried.
+-}
+
+module Data.EitherR (
+    EitherR(..),
+    -- ** Operations in the EitherR monad
+    succeed,
+    -- ** Conversions to the Either monad
+    throwE,
+    catchE,
+    handleE,
+    fmapL,
+    -- * EitherRT
+    EitherRT(..),
+    -- ** Operations in the EitherRT monad
+    right,
+    succeedT,
+    -- ** Conversions to the EitherT monad
+    throwT,
+    catchT,
+    handleT,
+    fmapLT
+    ) where
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Either
+
+{-|
+    If \"@Either e r@\" is the error monad, then \"@EitherR r e@\" is the
+    corresponding success monad, where:
+
+    * 'return' is 'throwE'.
+
+    * ('>>=') is 'catchE'.
+
+    * Successful results abort the computation
+-}
+newtype EitherR r e = EitherR { runEitherR :: Either e r }
+
+instance Functor (EitherR r) where
+    fmap = liftM
+
+instance Applicative (EitherR r) where
+    pure  = return
+    (<*>) = ap
+
+instance Monad (EitherR r) where
+    return = EitherR . Left
+    (EitherR m) >>= f = EitherR $ case m of
+        Left  e -> runEitherR (f e)
+        Right r -> Right r
+
+-- | Complete error handling, returning a result
+succeed :: r -> EitherR r e
+succeed = EitherR . return
+
+-- | 'throwE' in the error monad corresponds to 'return' in the success monad
+throwE :: e -> Either e r
+throwE = runEitherR . return
+
+-- | 'catchE' in the error monad corresponds to ('>>=') in the success monad
+catchE :: Either a r -> (a -> Either b r) -> Either b r
+e `catchE` f = runEitherR $ (EitherR e) >>= (EitherR . f)
+
+-- | 'catchE' with the arguments flipped
+handleE :: (a -> Either b r) -> Either a r -> Either b r
+handleE = flip catchE
+
+-- | Map a function over the 'Left' value of an 'Either'
+fmapL :: (a -> b) -> Either a r -> Either b r
+fmapL f = runEitherR . fmap f . EitherR
+
+-- | 'EitherR' converted into a monad transformer
+newtype EitherRT r m e = EitherRT { runEitherRT :: EitherT e m r }
+
+instance (Monad m) => Functor (EitherRT r m) where
+    fmap = liftM
+
+instance (Monad m) => Applicative (EitherRT r m) where
+    pure  = return
+    (<*>) = ap
+
+instance (Monad m) => Monad (EitherRT r m) where
+    return = EitherRT . left
+    m >>= f = EitherRT $ EitherT $ do
+        x <- runEitherT $ runEitherRT m
+        runEitherT $ runEitherRT $ case x of
+            Left  e -> f e
+            Right r -> right r
+
+instance MonadTrans (EitherRT r) where
+    lift = EitherRT . EitherT . liftM Left
+
+-- | The dual to 'left' and synonymous with 'succeedT'
+right :: (Monad m) => r -> EitherRT r m e
+right = EitherRT . return
+
+-- | Complete error handling, returning a result
+succeedT :: (Monad m) => r -> EitherRT r m e
+succeedT = right
+
+-- | 'throwT' in the error monad corresponds to 'return' in the success monad
+throwT :: (Monad m) => e -> EitherT e m r
+throwT = runEitherRT . return
+
+-- | 'catchT' in the error monad corresponds to ('>>=') in the success monad
+catchT :: (Monad m) => EitherT a m r -> (a -> EitherT b m r) -> EitherT b m r
+e `catchT` f = runEitherRT $ (EitherRT e) >>= (EitherRT . f)
+
+-- | 'catchT' with the arguments flipped
+handleT :: (Monad m) => (a -> EitherT b m r) -> EitherT a m r -> EitherT b m r
+handleT = flip catchT
+
+-- | Map a function over the 'Left' value of an 'EitherT'
+fmapLT :: (Monad m) => (a -> b) -> EitherT a m r -> EitherT b m r
+fmapLT f = runEitherRT . fmap f . EitherRT
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2012, Gabriel Gonzalez
+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 name of Gabriel Gonzalez nor the names of other 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/errors.cabal b/errors.cabal
new file mode 100644
--- /dev/null
+++ b/errors.cabal
@@ -0,0 +1,34 @@
+Name: errors
+Version: 1.0.0
+Cabal-Version: >=1.14.0
+Build-Type: Simple
+License: BSD3
+License-File: LICENSE
+Copyright: 2012 Gabriel Gonzalez
+Author: Gabriel Gonzalez
+Maintainer: Gabriel439@gmail.com
+Stability: Experimental
+Bug-Reports: https://github.com/Gabriel439/Haskell-Errors-Library/issues
+Synopsis: Simplified error-handling
+Description:
+    The one-stop shop for all your error-handling needs!  Just import
+    "Control.Error".
+    .
+    This library encourages an error-handling style that directly uses the type
+    system, rather than out-of-band exceptions.
+Category: Control, Error Handling
+Tested-With: GHC ==7.4.1
+Source-Repository head
+    Type: git
+    Location: https://github.com/Gabriel439/Haskell-Errors-Library
+
+Library
+    Build-Depends: base >= 4 && < 5, EitherT, safe, transformers
+    Exposed-Modules:
+        Control.Error,
+        Control.Error.Script,
+        Control.Error.Util,
+        Control.Error.Safe,
+        Data.EitherR
+    GHC-Options: -O2
+    Default-Language: Haskell2010
