diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,9 @@
+0.1.0.5
+
+* Large refactor, involving an associated value with an exit failure.
+* Delete nix
+* Delete Travis CI
+
 0.1.0.4
 
 * Fix `Semigroup` instance.
diff --git a/exitcode.cabal b/exitcode.cabal
--- a/exitcode.cabal
+++ b/exitcode.cabal
@@ -1,7 +1,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                exitcode
-version:             0.1.0.4
+version:             0.1.0.5
 synopsis:            Monad transformer for exit codes
 description:
   <<https://system-f.gitlab.io/logo/systemf-450x450.jpg>>
@@ -27,8 +27,8 @@
 library
   exposed-modules:     Control.Exitcode
   build-depends:       base >= 4.8 && < 6
+                     , bifunctors >= 5 && < 6
                      , lens >= 4.15 && < 6
-                     , mmorph >= 1.0 && < 1.2
                      , mtl >= 2.2 && < 2.3
                      , semigroupoids >= 5.1 && < 5.4
                      , semigroups >= 0.16 && < 0.19
@@ -40,6 +40,7 @@
 test-suite             tests
   build-depends:       QuickCheck >= 2.9.2 && < 2.13
                      , base >= 4.8 && < 6
+                     , bifunctors >= 5 && < 6
                      , checkers >= 0.4.6 && < 0.5
                      , exitcode
                      , hedgehog >= 0.5 && < 0.7
diff --git a/src/Control/Exitcode.hs b/src/Control/Exitcode.hs
--- a/src/Control/Exitcode.hs
+++ b/src/Control/Exitcode.hs
@@ -15,64 +15,81 @@
 -- * Construction
 , exitsuccess
 , exitsuccess0
+, exitfailure
 , exitfailure0
-, exitCodeValue
+, exitcodeValue
+, exitcodeValue0
 , fromExitCode
 , fromExitCode'
+, liftExitcode
+, liftExitcodeError
+, liftExitcodeError0
 -- * Extraction
+, runExitcodeT
+, runExitcodeT0
 , runExitcode
+, runExitcode0
 -- * Optics
 , exitCode
+, _ExitcodeInt
+, _ExitcodeInt'
 , _ExitFailure
+, _ExitFailureError
 , _ExitSuccess
 ) where
 
 import Control.Applicative
-    ( Applicative((<*>), liftA2, pure) )
+    ( Applicative((<*>), pure, liftA2) )
 import Control.Category ( Category((.)) )
 import Control.Lens
-    ( (^?),
+    ( Identity(runIdentity),
+      preview,
       view,
       iso,
       _Left,
       prism,
-      prism',
+      mapped,
       over,
+      Field1(_1),
+      Field2(_2),
       Iso,
       Prism,
-      Prism' )
-import Control.Monad ( join, Monad(return, (>>=)) )
+      Setter',
+      Traversal )
+import Control.Monad ( Monad(return, (>>=)) )
 import Control.Monad.Cont.Class ( MonadCont(..) )
 import Control.Monad.Error.Class ( MonadError(..) )
 import Control.Monad.IO.Class ( MonadIO(..) )
-import Control.Monad.Morph
-    ( MFunctor(..), MMonad(..) )
 import Control.Monad.Reader ( MonadReader(ask, local) )
-import Control.Monad.RWS.Class
-    ( MonadRWS )
-import Control.Monad.State.Lazy
-    ( MonadState(get, put) )
-import Control.Monad.Trans.Class ( MonadTrans(..) )
+import Control.Monad.RWS.Class ( MonadRWS )
+import Control.Monad.State.Lazy ( MonadState(get, put) )
 import Control.Monad.Trans.Maybe ( MaybeT(MaybeT) )
 import Control.Monad.Writer.Class ( MonadWriter(..) )
-import Data.Bool
+import Data.Bifoldable ( Bifoldable(bifoldMap) )
+import Data.Bifunctor ( Bifunctor(bimap) )
+import Data.Bitraversable ( Bitraversable(..) )
+import Data.Bool ( bool )
 import Data.Either ( Either(..), either )
 import Data.Eq ( Eq((==)) )
-import Data.Foldable ( Foldable(foldr) )
-import Data.Function ( ($), const, flip )
+import Data.Foldable ( Foldable(foldMap) )
+import Data.Function ( ($), const )
 import Data.Functor ( Functor(fmap), (<$>) )
 import Data.Functor.Alt ( Alt((<!>)) )
 import Data.Functor.Apply ( Apply((<.>)) )
 import Data.Functor.Bind ( Bind((>>-)) )
-import Data.Functor.Classes (Eq1, Ord1, Show1, compare1, eq1,
-                                             liftCompare, liftEq, liftShowList,
-                                             liftShowsPrec, showsPrec1,
-                                             showsUnaryWith)
+import Data.Functor.Classes
+    ( compare1,
+      eq1,
+      showsPrec1,
+      showsUnaryWith,
+      Eq1(..),
+      Ord1(..),
+      Show1(..) )
 import Data.Functor.Extend ( Extend(..) )
 import Data.Functor.Identity ( Identity(Identity) )
 import Data.Int ( Int )
 import Data.Maybe ( Maybe(Nothing, Just), fromMaybe )
-import Data.Monoid hiding (Alt)
+import Data.Monoid ( Monoid(mempty) )
 import Data.Ord ( Ord(compare) )
 import Data.Semigroup ( Semigroup((<>)) )
 import Data.Traversable ( Traversable(traverse) )
@@ -86,27 +103,27 @@
 
 -- | An exit code status where failing with a value `0` cannot be represented.
 --
--- Transformer for either a non-zero exit code (`Int`) or a value :: `a`.
-newtype ExitcodeT f a =
-  ExitcodeT (f (Either Int a))
+-- Transformer for either a (non-zero exit code value (`Int`) with error :: `e`) or a (value :: `a`).
+newtype ExitcodeT f e a =
+  ExitcodeT (f (Either (e, Int) a))
 
-type Exitcode a =
-  ExitcodeT Identity a
+type Exitcode e a =
+  ExitcodeT Identity e a
 
 type ExitcodeT0 f =
-  ExitcodeT f ()
+  ExitcodeT f () ()
 
 type Exitcode0 =
-  Exitcode ()
+  Exitcode () ()
 
 -- | Construct a succeeding exit code with the given value.
 --
--- >>> exitsuccess "abc" :: ExitcodeT Identity String
+-- >>> exitsuccess "abc" :: ExitcodeT Identity () String
 -- ExitcodeT (Identity (Right "abc"))
 exitsuccess ::
   Applicative f =>
   a
-  -> ExitcodeT f a
+  -> ExitcodeT f e a
 exitsuccess =
   ExitcodeT . pure . Right
 
@@ -116,7 +133,7 @@
 -- ExitcodeT (Identity (Right ()))
 exitsuccess0 ::
   Applicative f =>
-  ExitcodeT0 f
+  ExitcodeT f e ()
 exitsuccess0 =
   exitsuccess ()
 
@@ -124,41 +141,64 @@
 --
 -- If the given status is `0` then the exit code will succeed with unit.
 --
--- >>> exitfailure0 99 :: ExitcodeT0 Identity
--- ExitcodeT (Identity (Left 99))
--- >>> exitsuccess "abc" <> exitCodeValue 99 "def" :: ExitcodeT Identity String
--- ExitcodeT (Identity (Right "abc"))
--- >>> exitCodeValue 99 "abc" <> exitsuccess "def" :: ExitcodeT Identity String
--- ExitcodeT (Identity (Right "def"))
--- >>> exitCodeValue 99 "abc" <> exitCodeValue 88 "def" :: ExitcodeT Identity String
--- ExitcodeT (Identity (Left 88))
+-- >>> exitfailure 'x' 99 :: ExitcodeT Identity Char ()
+-- ExitcodeT (Identity (Left ('x',99)))
+exitfailure ::
+  Applicative f =>
+  e
+  -> Int
+  -> ExitcodeT f e ()
+exitfailure e n =
+  exitcodeValue e n ()
+
+-- | Construct a failing exit code with the given status.
+--
+-- If the given status is `0` then the exit code will succeed with unit.
 exitfailure0 ::
   Applicative f =>
   Int
   -> ExitcodeT0 f
-exitfailure0 n =
-  exitCodeValue n ()
+exitfailure0 =
+  exitfailure ()
 
--- |
+-- | Construct an exit code with the given status.
+-- Associate a value of type `e` with a failing exit code and a value of the type `a` with a success exit code.
 --
--- >>> exitCodeValue 99 "abc" :: ExitcodeT Identity String
--- ExitcodeT (Identity (Left 99))
--- >>> exitCodeValue 0 "abc" :: ExitcodeT Identity String
+-- If the given status is `0` then the exit code will succeed with unit.
+-- >>> exitcodeValue 'x' 99 "abc" :: ExitcodeT Identity Char String
+-- ExitcodeT (Identity (Left ('x',99)))
+-- >>> exitcodeValue 'x' 0 "abc" :: ExitcodeT Identity Char String
 -- ExitcodeT (Identity (Right "abc"))
-exitCodeValue ::
+exitcodeValue ::
   Applicative f =>
-  Int
+  e
+  -> Int
   -> a
-  -> ExitcodeT f a
-exitCodeValue n a =
-  ExitcodeT (pure (bool (Left n) (Right a) (n == 0)))
+  -> ExitcodeT f e a
+exitcodeValue e n =
+  liftExitcodeError (pure (e, n))
 
+-- | Construct an exit code with the given status.
+--
+-- If the given status is `0` then the exit code will succeed with unit.
+--
+-- >>> exitcodeValue0 99 :: ExitcodeT0 Identity
+-- ExitcodeT (Identity (Left ((),99)))
+-- >>> exitcodeValue0 0 :: ExitcodeT0 Identity
+-- ExitcodeT (Identity (Right ()))
+exitcodeValue0 ::
+  Applicative f =>
+  Int
+  -> ExitcodeT0 f
+exitcodeValue0 n =
+  exitcodeValue () n ()
+
 -- | From base exitcode.
 --
 -- >>> fromExitCode (Identity ExitSuccess)
 -- ExitcodeT (Identity (Right ()))
 -- >>> fromExitCode (Identity (ExitFailure 99))
--- ExitcodeT (Identity (Left 99))
+-- ExitcodeT (Identity (Left ((),99)))
 fromExitCode ::
   Functor f =>
   f ExitCode
@@ -172,7 +212,7 @@
 -- >>> fromExitCode' ExitSuccess
 -- ExitcodeT (Identity (Right ()))
 -- >>> fromExitCode' (ExitFailure 99)
--- ExitcodeT (Identity (Left 99))
+-- ExitcodeT (Identity (Left ((),99)))
 -- >>> fromExitCode' (ExitFailure 0)
 -- ExitcodeT (Identity (Right ()))
 fromExitCode' ::
@@ -184,12 +224,12 @@
 -- | Isomorphism from base exitcode to underlying `Maybe (Either Int ())` where `Int` is non-zero.
 --
 -- >>> view exitCode (Identity (ExitFailure 99))
--- ExitcodeT (MaybeT (Identity (Just (Left 99))))
+-- ExitcodeT (MaybeT (Identity (Just (Left ((),99)))))
 -- >>> view exitCode (Identity ExitSuccess)
 -- ExitcodeT (MaybeT (Identity (Just (Right ()))))
--- >>> review exitCode (exitfailure0 99) :: Identity ExitCode
+-- >>> Control.Lens.review exitCode (exitfailure () 99) :: Identity ExitCode
 -- Identity (ExitFailure 99)
--- >>> review exitCode exitsuccess0 :: Identity ExitCode
+-- >>> Control.Lens.review exitCode exitsuccess0 :: Identity ExitCode
 -- Identity ExitSuccess
 exitCode ::
   (Functor f, Functor g) =>
@@ -206,60 +246,166 @@
                                 ExitFailure 0 ->
                                   Nothing
                                 ExitFailure n ->
-                                  Just (Left n)) <$> x)))
+                                  Just (Left ((), n))) <$> x)))
     (\(ExitcodeT (MaybeT x)) -> (\case
                                   Just (Right ()) ->
                                     ExitSuccess
                                   Nothing ->
                                     ExitFailure 0
-                                  Just (Left n) ->
+                                  Just (Left ((), n)) ->
                                     ExitFailure n) <$> x)
 
 -- | Extract either the non-zero value or the success value.
 --
--- >>> runExitcode exitsuccess0 :: Identity (Either Int ())
+-- >>> runExitcodeT exitsuccess0 :: Identity (Either ((), Int) ())
 -- Identity (Right ())
--- >>> runExitcode (exitfailure0 99) :: Identity (Either Int ())
--- Identity (Left 99)
-runExitcode ::
-  ExitcodeT f a
-  -> f (Either Int a)
-runExitcode (ExitcodeT x) =
+-- >>> runExitcodeT (exitfailure () 99) :: Identity (Either ((), Int) ())
+-- Identity (Left ((),99))
+runExitcodeT ::
+  ExitcodeT f e a
+  -> f (Either (e, Int) a)
+runExitcodeT (ExitcodeT x) =
   x
 
--- | A prism to exit failure.
+-- | Extract either the non-zero value or `Nothing`.
 --
--- >>> preview _ExitFailure (exitfailure0 99)
+-- >>> runExitcodeT0 exitsuccess0 :: Identity (Maybe Int)
+-- Identity Nothing
+-- >>> runExitcodeT0 (exitfailure () 99) :: Identity (Maybe Int)
+-- Identity (Just 99)
+runExitcodeT0 ::
+  Functor f =>
+  ExitcodeT0 f
+  -> f (Maybe Int)
+runExitcodeT0 x =
+  preview (_Left . _2) <$> runExitcodeT x
+
+-- | Extract either the non-zero value or the success value.
+--
+-- >>> runExitcode exitsuccess0 :: Either ((), Int) ()
+-- Right ()
+-- >>> runExitcode (exitfailure () 99) :: Either ((), Int) ()
+-- Left ((),99)
+runExitcode ::
+  Exitcode e a
+  -> Either (e, Int) a
+runExitcode =
+  runIdentity . runExitcodeT
+
+-- | Extract either the non-zero value or `Nothing`.
+--
+-- >>> runExitcode0 exitsuccess0 :: Maybe Int
+-- Nothing
+-- >>> runExitcode0 (exitfailure () 99) :: Maybe Int
 -- Just 99
--- >>> preview _ExitFailure exitsuccess0
+runExitcode0 ::
+  Exitcode0
+  -> Maybe Int
+runExitcode0 =
+  runIdentity . runExitcodeT0
+
+-- | Isomorphism to integer.
+--
+-- >>> view _ExitcodeInt exitsuccess0 :: [Int]
+-- [0]
+-- >>> view _ExitcodeInt (exitfailure0 99) :: [Int]
+-- [99]
+-- >>> review _ExitcodeInt [0]
+-- ExitcodeT [Right ()]
+-- >>> review _ExitcodeInt [99]
+-- ExitcodeT [Left ((),99)]
+_ExitcodeInt ::
+  (Functor f, Functor f') =>
+  Iso
+    (ExitcodeT0 f)
+    (ExitcodeT0 f')
+    (f Int)
+    (f' Int)
+_ExitcodeInt =
+  iso
+    (\(ExitcodeT x) -> fmap (either (view _2) (\() -> 0)) x)
+    (\x -> liftExitcodeError (((),) <$> x) ())
+
+-- | Setter to integer.
+--
+-- >>> over _ExitcodeInt' (subtract 1) (exitsuccess0) :: ExitcodeT0 Identity
+-- ExitcodeT (Identity (Left ((),-1)))
+-- >>> over _ExitcodeInt' (subtract 1) (exitfailure0 99) :: ExitcodeT0 Identity
+-- ExitcodeT (Identity (Left ((),98)))
+-- >>> over _ExitcodeInt' (subtract 1) (exitfailure0 1) :: ExitcodeT0 Identity
+-- ExitcodeT (Identity (Right ()))
+_ExitcodeInt' ::
+  (Functor f) =>
+  Setter'
+    (ExitcodeT0 f)
+    Int
+_ExitcodeInt' =
+  _ExitcodeInt . mapped
+
+-- | A traversal to exit failure.
+--
+-- >>> preview _ExitFailure (exitfailure () 99 :: ExitcodeT0 Identity)
+-- Just ((),99)
+-- >>> preview _ExitFailure (exitsuccess0 :: ExitcodeT0 Identity)
 -- Nothing
--- >>> review _ExitFailure 99
--- ExitcodeT (Identity (Left 99))
--- >>> review _ExitFailure 0
+-- >>> over _ExitFailure (\(e, n) -> (e + 1, n + 1)) (exitsuccess0 :: ExitcodeT Identity Int ())
 -- ExitcodeT (Identity (Right ()))
+-- >>> over _ExitFailure (\(e, n) -> (reverse e, n + 1)) (exitfailure "abc" 1 :: ExitcodeT Identity String ())
+-- ExitcodeT (Identity (Left ("cba",2)))
+-- >>> over _ExitFailure (\(e, n) -> (reverse e, n - 1)) (exitfailure "abc" 1 :: ExitcodeT Identity String ())
+-- ExitcodeT (Identity (Right ()))
 _ExitFailure ::
-  Prism'
-    Exitcode0
-    Int
-_ExitFailure =
-  prism'
-    exitfailure0
-    (\(ExitcodeT (Identity x)) -> x ^? _Left)
+  Traversable f =>
+  Traversal
+    (ExitcodeT f e ())
+    (ExitcodeT f e' ())
+    (e, Int)
+    (e', Int)
+_ExitFailure f (ExitcodeT x) =
+  ExitcodeT <$> traverse (either (\z -> runExitcodeT (liftExitcodeError (f z) ())) (pure . pure)) x
 
+-- | A traversal over the associated failing value.
+--
+-- >>> over _ExitFailureError reverse exitsuccess0 :: ExitcodeT Identity [Int] ()
+-- ExitcodeT (Identity (Right ()))
+-- >>> over _ExitFailureError reverse (exitfailure "abc" 99) :: ExitcodeT Identity String ()
+-- ExitcodeT (Identity (Left ("cba",99)))
+-- >>> over _ExitFailureError reverse (exitfailure "abc" 0) :: ExitcodeT Identity String ()
+-- ExitcodeT (Identity (Right ()))
+-- >>> preview _ExitFailureError (exitfailure () 99 :: ExitcodeT0 Identity)
+-- Just ()
+-- >>> preview _ExitFailureError (exitsuccess0 :: ExitcodeT0 Identity)
+-- Nothing
+_ExitFailureError ::
+  Traversable f =>
+  Traversal
+    (ExitcodeT f e a)
+    (ExitcodeT f e' a)
+    e
+    e'
+_ExitFailureError f (ExitcodeT x) =
+  ExitcodeT <$> traverse (either (\(e, n) -> (\e' -> Left (e', n)) <$> f e) (pure . Right)) x
+
 -- | A prism to exit success.
 --
--- >>> preview _ExitSuccess (exitfailure0 99)
+-- >>> over _ExitSuccess (\x -> x) (exitfailure0 99)
+-- ExitcodeT (Identity (Left ((),99)))
+-- >>> over _ExitSuccess (\x -> x) (exitfailure0 0)
+-- ExitcodeT (Identity (Right ()))
+-- >>> over _ExitSuccess (\x -> x) (exitfailure0 0)
+-- ExitcodeT (Identity (Right ()))
+-- >>> preview _ExitSuccess (exitfailure () 99)
 -- Nothing
 -- >>> preview _ExitSuccess exitsuccess0
 -- Just ()
--- >>> review _ExitSuccess "abc"
+-- >>> Control.Lens.review _ExitSuccess "abc" :: ExitcodeT Identity () String
 -- ExitcodeT (Identity (Right "abc"))
 _ExitSuccess ::
   Prism
-    (Exitcode a)
-    (Exitcode b)
+    (Exitcode e a)
+    (Exitcode e a')
     a
-    b
+    a'
 _ExitSuccess =
   prism
     exitsuccess
@@ -267,15 +413,15 @@
       over _Left (ExitcodeT . Identity . Left) x
     )
 
-instance Functor f => Functor (ExitcodeT f) where
+instance Functor f => Functor (ExitcodeT f e) where
   fmap f (ExitcodeT x) =
     ExitcodeT (fmap (fmap f) x)
 
-instance Monad f => Apply (ExitcodeT f) where
+instance Monad f => Apply (ExitcodeT f e) where
   ExitcodeT f <.> ExitcodeT a =
     ExitcodeT (f >>= either (pure . Left) (\f' -> fmap (fmap f') a))
 
-instance Monad f => Applicative (ExitcodeT f) where
+instance Monad f => Applicative (ExitcodeT f e) where
   pure =
     ExitcodeT . pure . pure
   ExitcodeT f <*> ExitcodeT a =
@@ -283,42 +429,52 @@
 
 -- |
 --
--- >>> exitsuccess "abc" >>- \s -> exitsuccess (reverse s) :: ExitcodeT Identity String
+-- >>> exitsuccess "abc" >>- \s -> exitsuccess (reverse s) :: ExitcodeT Identity () String
 -- ExitcodeT (Identity (Right "cba"))
--- >>> exitsuccess "abc" >>- \_ -> exitfailure0 99 :: ExitcodeT Identity ()
--- ExitcodeT (Identity (Left 99))
--- >>> exitfailure0 99 >>- \_ -> exitsuccess "abc" :: ExitcodeT Identity String
--- ExitcodeT (Identity (Left 99))
--- >>> exitfailure0 99 >>- \_ -> exitfailure0 88 :: ExitcodeT Identity ()
--- ExitcodeT (Identity (Left 99))
--- >>> let loop = loop in exitfailure0 99 >>- loop :: ExitcodeT Identity ()
--- ExitcodeT (Identity (Left 99))
-instance Monad f => Bind (ExitcodeT f) where
+-- >>> exitsuccess "abc" >>- \_ -> exitfailure () 99 :: ExitcodeT Identity () ()
+-- ExitcodeT (Identity (Left ((),99)))
+-- >>> exitfailure 'x' 99 >>- \_ -> exitsuccess "abc" :: ExitcodeT Identity Char String
+-- ExitcodeT (Identity (Left ('x',99)))
+-- >>> exitfailure 'x' 99 >>- \_ -> exitfailure 'y' 88 :: ExitcodeT Identity Char ()
+-- ExitcodeT (Identity (Left ('x',99)))
+-- >>> let loop = loop in exitfailure () 99 >>- loop :: ExitcodeT Identity () ()
+-- ExitcodeT (Identity (Left ((),99)))
+instance Monad f => Bind (ExitcodeT f e) where
   (>>-) =
     (>>=)
 
-instance Monad f => Monad (ExitcodeT f) where
+instance Monad f => Monad (ExitcodeT f e) where
   return =
     ExitcodeT . return . return
   ExitcodeT x >>= f =
     ExitcodeT
-      (x >>= either (pure . Left) (runExitcode . f))
+      (x >>= either (pure . Left) (runExitcodeT . f))
 
-instance Monad f => Alt (ExitcodeT f) where
+-- |
+--
+-- >>> exitsuccess "abc" <!> exitsuccess "def" :: ExitcodeT Identity () String
+-- ExitcodeT (Identity (Right "abc"))
+-- >>> exitsuccess "abc" <!> exitcodeValue () 99 "def" :: ExitcodeT Identity () String
+-- ExitcodeT (Identity (Right "abc"))
+-- >>> exitcodeValue 'x' 99 "abc" <!> exitsuccess "def" :: ExitcodeT Identity Char String
+-- ExitcodeT (Identity (Right "def"))
+-- >>> exitcodeValue 'x' 99 "abc" <!> exitcodeValue 'y' 88 "def" :: ExitcodeT Identity Char String
+-- ExitcodeT (Identity (Left ('y',88)))
+instance Monad f => Alt (ExitcodeT f e) where
   ExitcodeT a <!> ExitcodeT b =
     ExitcodeT (a >>= either (const b) (pure a))
 
 -- |
 --
--- >>> exitsuccess "abc" <> exitsuccess "def" :: ExitcodeT Identity String
+-- >>> exitsuccess "abc" <> exitsuccess "def" :: ExitcodeT Identity () String
 -- ExitcodeT (Identity (Right "abcdef"))
--- >>> exitsuccess "abc" <> exitCodeValue 99 "def" :: ExitcodeT Identity String
+-- >>> exitsuccess "abc" <> exitcodeValue () 99 "def" :: ExitcodeT Identity () String
 -- ExitcodeT (Identity (Right "abc"))
--- >>> exitCodeValue 99 "abc" <> exitsuccess "def" :: ExitcodeT Identity String
+-- >>> exitcodeValue 'x' 99 "abc" <> exitsuccess "def" :: ExitcodeT Identity Char String
 -- ExitcodeT (Identity (Right "def"))
--- >>> exitCodeValue 99 "abc" <> exitCodeValue 88 "def" :: ExitcodeT Identity String
--- ExitcodeT (Identity (Left 88))
-instance (Semigroup a, Applicative f) => Semigroup (ExitcodeT f a) where
+-- >>> exitcodeValue 'x' 99 "abc" <> exitcodeValue 'y' 88 "def" :: ExitcodeT Identity Char String
+-- ExitcodeT (Identity (Left ('y',88)))
+instance (Semigroup a, Applicative f) => Semigroup (ExitcodeT f e a) where
   ExitcodeT a <> ExitcodeT b =
     let jn (Left _) x  = x
         jn x (Left _) = x
@@ -327,96 +483,116 @@
 
 -- |
 --
--- >>> mempty :: ExitcodeT Identity String
+-- >>> mempty :: ExitcodeT Identity () String
 -- ExitcodeT (Identity (Right ""))
-instance (Monoid a, Applicative f) => Monoid (ExitcodeT f a) where
+instance (Monoid a, Applicative f) => Monoid (ExitcodeT f e a) where
   mempty =
     ExitcodeT (pure (Right mempty))
 
 -- |
 --
--- >>> duplicated (exitfailure0 99) :: ExitcodeT Identity (ExitcodeT Identity ())
--- ExitcodeT (Identity (Right (ExitcodeT (Identity (Left 99)))))
--- >>> duplicated (exitsuccess "abc") :: ExitcodeT Identity (ExitcodeT Identity String)
+-- >>> duplicated (exitfailure () 0) :: ExitcodeT Identity () (ExitcodeT Identity () ())
+-- ExitcodeT (Identity (Right (ExitcodeT (Identity (Right ())))))
+-- >>> duplicated (exitfailure () 99) :: ExitcodeT Identity () (ExitcodeT Identity () ())
+-- ExitcodeT (Identity (Right (ExitcodeT (Identity (Left ((),99))))))
+-- >>> duplicated (exitsuccess "abc") :: ExitcodeT Identity () (ExitcodeT Identity () String)
 -- ExitcodeT (Identity (Right (ExitcodeT (Identity (Right "abc")))))
-instance Extend f => Extend (ExitcodeT f) where
+instance Extend f => Extend (ExitcodeT f e) where
   duplicated (ExitcodeT x) =
     ExitcodeT (extended (Right . ExitcodeT) x)
 
-instance (Eq1 f, Eq a) => Eq (ExitcodeT f a) where
+instance (Eq1 f, Eq e, Eq a) => Eq (ExitcodeT f e a) where
   ExitcodeT a == ExitcodeT b =
     a `eq1` b
 
-instance Eq1 f => Eq1 (ExitcodeT f) where
+instance (Eq1 f, Eq e) => Eq1 (ExitcodeT f e) where
   liftEq f (ExitcodeT a) (ExitcodeT b) =
     liftEq (liftEq f) a b
 
-instance (Ord1 f, Ord a) => Ord (ExitcodeT f a) where
+instance (Ord1 f, Ord e, Ord a) => Ord (ExitcodeT f e a) where
   ExitcodeT a `compare` ExitcodeT b =
     a `compare1` b
 
-instance (Ord1 f) => Ord1 (ExitcodeT f) where
+instance (Ord1 f, Ord e) => Ord1 (ExitcodeT f e) where
   liftCompare f (ExitcodeT a) (ExitcodeT b) =
     liftCompare (liftCompare f) a b
 
-instance (Show1 f, Show a) => Show (ExitcodeT f a) where
+instance (Show1 f, Show e, Show a) => Show (ExitcodeT f e a) where
   showsPrec d (ExitcodeT m) =
     showsUnaryWith showsPrec1 "ExitcodeT" d m
 
-instance Show1 f => Show1 (ExitcodeT f) where
+instance (Show1 f, Show e) => Show1 (ExitcodeT f e) where
   liftShowsPrec sp sl d (ExitcodeT fa) =
     let showsPrecF = liftA2 liftShowsPrec (uncurry liftShowsPrec) (uncurry liftShowList) (sp, sl)
     in showsUnaryWith showsPrecF "ExitcodeT" d fa
 
-instance Foldable f => Foldable (ExitcodeT f) where
-  foldr f z (ExitcodeT x) =
-    foldr (flip (foldr f)) z x
+instance Foldable f => Foldable (ExitcodeT f e) where
+  foldMap f (ExitcodeT x) =
+    foldMap (foldMap f) x
 
 -- |
 --
--- >>> traverse id [exitfailure0 99] :: ExitcodeT Identity [()]
--- ExitcodeT (Identity (Left 99))
--- >>> traverse id [exitfailure0 99, exitsuccess0] :: ExitcodeT Identity [()]
--- ExitcodeT (Identity (Left 99))
--- >>> traverse id [exitfailure0 99, exitsuccess0, exitfailure0 88] :: ExitcodeT Identity [()]
--- ExitcodeT (Identity (Left 99))
--- >>> traverse id [exitsuccess0, exitfailure0 88] :: ExitcodeT Identity [()]
--- ExitcodeT (Identity (Left 88))
--- >>> traverse id [exitsuccess0] :: ExitcodeT Identity [()]
+-- >>> traverse (\x -> x) [exitfailure 'x' 99] :: ExitcodeT Identity Char [()]
+-- ExitcodeT (Identity (Left ('x',99)))
+-- >>> traverse (\x -> x) [exitfailure 'x' 99, exitsuccess0] :: ExitcodeT Identity Char [()]
+-- ExitcodeT (Identity (Left ('x',99)))
+-- >>> traverse (\x -> x) [exitfailure 'x' 99, exitsuccess0, exitfailure 'y' 88] :: ExitcodeT Identity Char [()]
+-- ExitcodeT (Identity (Left ('x',99)))
+-- >>> traverse (\x -> x) [exitsuccess0, exitfailure 'x' 88] :: ExitcodeT Identity Char [()]
+-- ExitcodeT (Identity (Left ('x',88)))
+-- >>> traverse (\x -> x) [exitsuccess0] :: ExitcodeT Identity () [()]
 -- ExitcodeT (Identity (Right [()]))
-instance Traversable f => Traversable (ExitcodeT f) where
+instance Traversable f => Traversable (ExitcodeT f e) where
   traverse f (ExitcodeT x) =
     ExitcodeT <$> traverse (traverse f) x
 
-instance MonadIO f => MonadIO (ExitcodeT f) where
+instance MonadIO f => MonadIO (ExitcodeT f e) where
   liftIO io =
     ExitcodeT (Right <$> liftIO io)
 
-instance MonadTrans ExitcodeT where
-  lift =
-    ExitcodeT . (>>= pure . pure)
+liftExitcode ::
+  Functor f =>
+  f a
+  -> ExitcodeT f e a
+liftExitcode x =
+  ExitcodeT (Right <$> x)
 
-instance MonadReader r f => MonadReader r (ExitcodeT f) where
+liftExitcodeError ::
+  Functor f =>
+  f (e, Int)
+  -> a
+  -> ExitcodeT f e a
+liftExitcodeError x a =
+  ExitcodeT ((\(e, n) -> bool (Left (e, n)) (Right a) (n == 0)) <$> x)
+
+liftExitcodeError0 ::
+  Functor f =>
+  f Int
+  -> ExitcodeT f () ()
+liftExitcodeError0 x =
+  liftExitcodeError (((),) <$> x) ()
+
+instance MonadReader r f => MonadReader r (ExitcodeT f e) where
   ask =
-    lift ask
+    liftExitcode ask
   local f (ExitcodeT m) =
     ExitcodeT (local f m)
 
 -- |
 --
--- >>> writer ('x', "abc") :: ExitcodeT ((,) String) Char
+-- >>> writer ('x', "abc") :: ExitcodeT ((,) String) () Char
 -- ExitcodeT ("abc",Right 'x')
--- >>> listen (exitfailure0 99 :: ExitcodeT ((,) String) ())
--- ExitcodeT ("",Left 99)
--- >>> listen (exitsuccess 99 :: ExitcodeT ((,) String) Int)
+-- >>> listen (exitfailure 'x' 99 :: ExitcodeT ((,) String) Char ())
+-- ExitcodeT ("",Left ('x',99))
+-- >>> listen (exitsuccess 99 :: ExitcodeT ((,) String) () Int)
 -- ExitcodeT ("",Right (99,""))
--- >>> tell "abc" :: ExitcodeT ((,) String) ()
+-- >>> tell "abc" :: ExitcodeT ((,) String) () ()
 -- ExitcodeT ("abc",Right ())
--- >>> pass (exitsuccess ('x', reverse)) :: ExitcodeT ((,) String) Char
+-- >>> pass (exitsuccess ('x', reverse)) :: ExitcodeT ((,) String) () Char
 -- ExitcodeT ("",Right 'x')
--- >>> pass (('x', reverse) <$ (exitfailure0 99 :: ExitcodeT ((,) String) ()))
--- ExitcodeT ("",Left 99)
-instance MonadWriter w f => MonadWriter w (ExitcodeT f) where
+-- >>> pass (('x', reverse) <$ (exitfailure 'x' 99 :: ExitcodeT ((,) String) Char ()))
+-- ExitcodeT ("",Left ('x',99))
+instance MonadWriter w f => MonadWriter w (ExitcodeT f e) where
   writer t =
     ExitcodeT . fmap pure $ writer t
   listen (ExitcodeT m) =
@@ -428,7 +604,7 @@
         tell (f w)
         pure a
 
-instance MonadState s f => MonadState s (ExitcodeT f) where
+instance MonadState s f => MonadState s (ExitcodeT f e) where
   get =
     ExitcodeT (fmap Right get)
   put =
@@ -436,44 +612,42 @@
 
 -- |
 --
--- >>> throwError 99 :: ExitcodeT (Either Int) String
+-- >>> throwError 99 :: ExitcodeT (Either Int) () String
 -- ExitcodeT (Left 99)
--- >>> catchError exitsuccess0 exitfailure0 :: ExitcodeT (Either Int) ()
+-- >>> catchError exitsuccess0 (exitfailure 'x') :: ExitcodeT (Either Int) Char ()
 -- ExitcodeT (Right (Right ()))
--- >>> catchError (exitfailure0 99) (\_ -> exitsuccess0) :: ExitcodeT (Either Int) ()
--- ExitcodeT (Right (Left 99))
--- >>> catchError (exitfailure0 99) exitfailure0 :: ExitcodeT (Either Int) ()
--- ExitcodeT (Right (Left 99))
--- >>> catchError exitsuccess0 (\_ -> exitsuccess0) :: ExitcodeT (Either Int) ()
+-- >>> catchError (exitfailure 'x' 99) (\_ -> exitsuccess0) :: ExitcodeT (Either Int) Char ()
+-- ExitcodeT (Right (Left ('x',99)))
+-- >>> catchError (exitfailure 'x' 99) (exitfailure 'y') :: ExitcodeT (Either Int) Char ()
+-- ExitcodeT (Right (Left ('x',99)))
+-- >>> catchError exitsuccess0 (\_ -> exitsuccess0) :: ExitcodeT (Either Int) () ()
 -- ExitcodeT (Right (Right ()))
-instance MonadError e f => MonadError e (ExitcodeT f) where
+instance MonadError e f => MonadError e (ExitcodeT f e') where
   throwError =
     ExitcodeT . fmap Right . throwError
   catchError (ExitcodeT f) h =
-     ExitcodeT (catchError f (runExitcode . h))
+     ExitcodeT (catchError f (runExitcodeT . h))
 
-instance MonadRWS r w s f => MonadRWS r w s (ExitcodeT f)
+instance MonadRWS r w s f => MonadRWS r w s (ExitcodeT f e)
 
 -- Given the embedded `Either` we can only handle computations that use `Either`.
 -- This code taken from the ExceptT instance:
 --   https://hackage.haskell.org/package/transformers-0.5.4.0/docs/src/Control.Monad.Trans.Except.html#line-237
-instance MonadCont f => MonadCont (ExitcodeT f) where
+instance MonadCont f => MonadCont (ExitcodeT f e) where
   callCC =
     let liftCallCC callCC' f =
           ExitcodeT . callCC' $
-            \c -> runExitcode (f (ExitcodeT . c . Right))
+            \c -> runExitcodeT (f (ExitcodeT . c . Right))
     in  liftCallCC callCC
 
--- |
---
--- >>> hoist (\(Identity x) -> Just x) exitsuccess0
--- ExitcodeT (Just (Right ()))
--- >>> hoist (\(Identity x) -> Just x) (exitfailure0 99)
--- ExitcodeT (Just (Left 99))
-instance MFunctor ExitcodeT where
-  hoist nat (ExitcodeT x) =
-    ExitcodeT (nat x)
+instance Functor f => Bifunctor (ExitcodeT f) where
+  bimap f g (ExitcodeT x) =
+    ExitcodeT (fmap (bimap (over _1 f) g) x)
 
-instance MMonad ExitcodeT where
-  embed nat (ExitcodeT x) =
-    ExitcodeT (join <$> runExitcode (nat x))
+instance Foldable f => Bifoldable (ExitcodeT f) where
+  bifoldMap f g (ExitcodeT x) =
+    foldMap (bifoldMap (f . view _1) g) x
+
+instance Traversable f => Bitraversable (ExitcodeT f) where
+  bitraverse f g (ExitcodeT x) =
+    ExitcodeT <$> traverse (bitraverse (\(a, n) -> (, n) <$> f a) g) x
