diff --git a/System/Hardware/BusPirate.hs b/System/Hardware/BusPirate.hs
--- a/System/Hardware/BusPirate.hs
+++ b/System/Hardware/BusPirate.hs
@@ -10,13 +10,6 @@
   , runSpi
   ) where
 
-import Control.Monad (replicateM)
-import Control.Monad.IO.Class
-import Control.Monad.Trans.Class
-import Control.Monad.Trans.Either
-import Control.Monad.Trans.Reader
-import Control.Applicative
-
 import System.Hardware.BusPirate.Core
 import System.Hardware.BusPirate.I2C
 import System.Hardware.BusPirate.SPI
diff --git a/System/Hardware/BusPirate/Core.hs b/System/Hardware/BusPirate/Core.hs
--- a/System/Hardware/BusPirate/Core.hs
+++ b/System/Hardware/BusPirate/Core.hs
@@ -5,7 +5,7 @@
 import Control.Applicative
 import Control.Monad (when, replicateM_)
 import Control.Monad.Trans.Class
-import Control.Monad.Trans.Either
+import Control.Monad.Trans.Except
 import Control.Monad.Trans.Reader
 import Control.Monad.IO.Class
 import System.IO
@@ -22,7 +22,7 @@
 debug :: Bool
 debug = False
 
-newtype BusPirateM a = BPM (EitherT String (ReaderT Handle IO) a)
+newtype BusPirateM a = BPM (ExceptT String (ReaderT Handle IO) a)
                      deriving (Functor, Applicative, Monad, MonadIO)
 
 withDevice :: (Handle -> BusPirateM a) -> BusPirateM a
@@ -37,20 +37,20 @@
     when (not $ BS.null a) $ drainInput h
 
 -- | Attempt to enter binary mode
-initialize :: Handle -> EitherT String IO ()
+initialize :: Handle -> ExceptT String IO ()
 initialize dev = do
     liftIO $ hFlush dev
     liftIO $ BS.hPut dev "\x00"
     a <- liftIO $ BS.hGetSome dev 5
     when (a /= "BBIO1")
-      $ left "Invalid response during initialization"
+      $ throwE "Invalid response during initialization"
 
 -- | Run the given action until success up to n times
-attempt :: Monad m => Int -> EitherT e m a -> EitherT e m a
+attempt :: Monad m => Int -> ExceptT e m a -> ExceptT e m a
 attempt n action = go n
   where
     go 0 = action
-    go n = do res <- lift $ runEitherT action
+    go n = do res <- lift $ runExceptT action
               case res of
                 Right a -> return a
                 Left _  -> go (n-1)
@@ -59,10 +59,10 @@
 runBusPirate :: FilePath -> BusPirateM a -> IO (Either String a)
 runBusPirate path (BPM action) = do
     dev <- liftIO $ SP.hOpenSerial path settings
-    res <- runEitherT $ do
+    res <- runExceptT $ do
       attempt 20 (initialize dev)
       liftIO $ drainInput dev
-      EitherT $ runReaderT (runEitherT action) dev
+      ExceptT $ runReaderT (runExceptT action) dev
     replicateM_ 20 $ BS.hPut dev "\x00"
     BS.hPut dev "\x0f"
     hClose dev
diff --git a/System/Hardware/BusPirate/I2C.hs b/System/Hardware/BusPirate/I2C.hs
--- a/System/Hardware/BusPirate/I2C.hs
+++ b/System/Hardware/BusPirate/I2C.hs
@@ -29,9 +29,9 @@
   ) where
 
 import Control.Applicative
-import Control.Monad (replicateM, when, void)
+import Control.Monad (replicateM, void)
 import Control.Monad.IO.Class
-import Control.Monad.Trans.Either
+import Control.Monad.Trans.Except
 import Data.Bits
 import Data.Word
 import Data.List (intercalate)
@@ -45,7 +45,7 @@
                deriving (Functor, Applicative, Monad, MonadIO)
 
 err :: String -> I2cM a
-err = I2cM . BPM . left
+err = I2cM . BPM . throwE
 
 -- | Enter I2C mode and run given action
 i2cMode :: I2cM a -> BusPirateM a
@@ -78,7 +78,7 @@
 bulkWrite :: ByteString -> I2cM ()
 bulkWrite d
   | BS.null d = return ()
-  | BS.length d > 16 = I2cM $ BPM $ left "Too many bytes"
+  | BS.length d > 16 = err "Too many bytes"
   | otherwise = I2cM $ do
     command $ fromIntegral $ 0x10 + BS.length d - 1
     put d
diff --git a/System/Hardware/BusPirate/SPI.hs b/System/Hardware/BusPirate/SPI.hs
--- a/System/Hardware/BusPirate/SPI.hs
+++ b/System/Hardware/BusPirate/SPI.hs
@@ -17,7 +17,7 @@
 import Control.Applicative
 import Control.Monad (replicateM)
 import Control.Monad.IO.Class
-import Control.Monad.Trans.Either
+import Control.Monad.Trans.Except
 import Data.Word
 
 import qualified Data.ByteString as BS
@@ -29,7 +29,7 @@
                deriving (Functor, Applicative, Monad, MonadIO)
 
 err :: String -> SpiM a
-err = SpiM . BPM . left
+err = SpiM . BPM . throwE
 
 -- | Enter I2C mode and run given action
 spiMode :: SpiM a -> BusPirateM a
@@ -44,7 +44,7 @@
 bulkTransfer :: ByteString -> SpiM ByteString
 bulkTransfer d
   | BS.null d = return BS.empty
-  | BS.length d > 16 = SpiM $ BPM $ left "Too many bytes"
+  | BS.length d > 16 = err "Too many bytes"
   | otherwise = SpiM $ do
     command $ fromIntegral $ 0x10 + BS.length d - 1
     put d
@@ -84,6 +84,6 @@
     putWord16 readLen
     status <- getByte
     case status of
-      0 -> BPM $ left "Data too long"
+      0 -> BPM $ throwE "Data too long"
       1 -> do put write
               get (fromIntegral readLen)
diff --git a/bus-pirate.cabal b/bus-pirate.cabal
--- a/bus-pirate.cabal
+++ b/bus-pirate.cabal
@@ -1,5 +1,5 @@
 name:                bus-pirate
-version:             0.6.3
+version:             0.7.0
 synopsis:            Haskell interface to the Bus Pirate binary interface
 homepage:            http://www.github.com/bgamari/bus-pirate
 license:             BSD3
@@ -22,10 +22,9 @@
                        System.Hardware.BusPirate.I2C
                        System.Hardware.BusPirate.SPI
   other-modules:       System.Hardware.BusPirate.Core
-  build-depends:       base >=4.6 && <4.9,
+  build-depends:       base >=4.6 && <4.10,
                        serialport >=0.4 && <0.5,
                        bytestring >=0.10 && <0.11,
-                       errors >=1.4 && <3.0,
-                       transformers >=0.3 && <0.5,
-                       either
+                       errors >=2.0 && <3.0,
+                       transformers >=0.5 && <0.6
   default-language:    Haskell2010
