diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,45 @@
+# 2.3.0
+
+* BREAKING CHANGE: `syncIO` now expects a `MonadIO` constraint instead of
+  `UnexceptionalIO`
+    * `syncIO` also changes how it detects asynchronous exceptions.  It now
+      decides based on whether or not an exception inherits from
+      `SomeAsyncException`
+    * See: https://github.com/Gabriel439/Haskell-Errors-Library/pull/53
+
+# 2.2.5
+
+* Increase upper bound on `exceptions`
+
+# 2.2.4
+
+* Increase upper bound on `exceptions`
+
+# 2.2.3
+
+* Increase upper bound on `transformers-compat`
+
+# 2.2.2
+
+* Support GHC 8.4 through compatibility with Semigroup/Monoid proposal
+
+# 2.2.1
+
+* Add precedence and fixity for `(?:)`
+
+# 2.2.0
+
+* BREAKING CHANGE: Use `Text` instead of `String`
+* Add `handleExceptT`
+
+# 2.1.3
+
+* Support older versions of `ghc`
+
+# 2.1.2
+
+* Increase upper bound on `transformers` dependency
+
 # 2.1.1
 
 * Increase upper bound on `transformers-compat`
diff --git a/Control/Error.hs b/Control/Error.hs
--- a/Control/Error.hs
+++ b/Control/Error.hs
@@ -10,7 +10,7 @@
       'EitherT', and 'MonadPlus' variations on total functions
 
     * "Control.Error.Script": Support for simple scripts that catch all errors
-      and transform them to 'String's
+      and transform them to 'Text'
 
     * "Control.Error.Util": Utility functions and conversions between common
       error-handling types
diff --git a/Control/Error/Script.hs b/Control/Error/Script.hs
--- a/Control/Error/Script.hs
+++ b/Control/Error/Script.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE OverloadedStrings #-}
+
 {-|
-    Use this module if you like to write simple scripts with 'String'-based
+    Use this module if you like to write simple scripts with 'Text'-based
     errors, but you prefer to use 'ExceptT' to handle errors rather than
     @Control.Exception@.
 
@@ -24,6 +26,8 @@
 import Control.Monad.Trans.Except (ExceptT(ExceptT), runExceptT)
 import Control.Error.Util (errLn)
 import Data.EitherR (fmapL)
+import Data.Monoid ((<>))
+import Data.Text (Text)
 import System.Environment (getProgName)
 import System.Exit (exitFailure)
 
@@ -31,9 +35,11 @@
 import Control.Monad.Trans.Class (lift)
 import System.IO (stderr)
 
--- | An 'IO' action that can fail with a 'String' error message
-type Script = ExceptT String IO
+import qualified Data.Text
 
+-- | An 'IO' action that can fail with a 'Text' error message
+type Script = ExceptT Text IO
+
 {-| Runs the 'Script' monad
 
     Prints the first error to 'stderr' and exits with 'exitFailure'
@@ -43,17 +49,18 @@
     e <- runExceptT s
     case e of
         Left  e -> do
-            errLn =<< liftM (++ ": " ++ e) getProgName
+            let adapt str = Data.Text.pack str <> ": " <> e
+            errLn =<< liftM adapt getProgName
             exitFailure
         Right a -> return a
 
 {-| 'scriptIO' resembles 'lift', except it catches all exceptions and converts
-    them to 'String's.
+    them to 'Text'
 
     Note that 'scriptIO' is compatible with the 'Script' monad.
 -}
-scriptIO :: (MonadIO m) => IO a -> ExceptT String m a
+scriptIO :: (MonadIO m) => IO a -> ExceptT Text m a
 scriptIO = ExceptT
          . liftIO
-         . liftM (fmapL show)
+         . liftM (fmapL (Data.Text.pack . show))
          . (try :: IO a -> IO (Either SomeException a))
diff --git a/Control/Error/Util.hs b/Control/Error/Util.hs
--- a/Control/Error/Util.hs
+++ b/Control/Error/Util.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 -- | This module exports miscellaneous error-handling functions.
 
 module Control.Error.Util (
@@ -47,24 +49,27 @@
 
     -- * Exceptions
     tryIO,
+    handleExceptT,
     syncIO
     ) where
 
 import Control.Applicative (Applicative, pure, (<$>))
-import Control.Exception (Handler(..), IOException, SomeException)
+import Control.Exception (IOException, SomeException, Exception)
 import Control.Monad (liftM)
+import Control.Monad.Catch (MonadCatch, try)
 import Control.Monad.IO.Class (MonadIO(liftIO))
 import Control.Monad.Trans.Except (ExceptT(ExceptT), runExceptT)
 import Control.Monad.Trans.Maybe (MaybeT(MaybeT), runMaybeT)
-import Data.Dynamic (Dynamic)
 import Data.Monoid (Monoid(mempty, mappend))
+#if MIN_VERSION_base(4,9,0)
+import Data.Semigroup
+#endif
 import Data.Maybe (fromMaybe)
-import System.Exit (ExitCode)
-import System.IO (hPutStr, hPutStrLn, stderr)
-import UnexceptionalIO (UIO, Unexceptional)
+import Data.Text (Text)
+import System.IO (stderr)
 
 import qualified Control.Exception as Exception
-import qualified UnexceptionalIO   as UIO
+import qualified Data.Text.IO
 
 -- | Fold an 'ExceptT' by providing one continuation for each constructor
 exceptT :: Monad m => (a -> m c) -> (b -> m c) -> ExceptT a m b -> m c
@@ -123,6 +128,8 @@
 maybeA ?: b = fromMaybe b maybeA
 {-# INLINABLE (?:) #-}
 
+infixr 0 ?:
+
 {-| Convert a 'Maybe' value into the 'ExceptT' monad
 
     Named version of ('??') with arguments flipped
@@ -191,12 +198,22 @@
 -}
 newtype AllE e r = AllE { runAllE :: Either e r }
 
+#if MIN_VERSION_base(4,9,0)
+instance (Semigroup e, Semigroup r) => Semigroup (AllE e r) where
+    AllE (Right x) <> AllE (Right y) = AllE (Right (x <> y))
+    AllE (Right _) <> AllE (Left  y) = AllE (Left y)
+    AllE (Left  x) <> AllE (Right _) = AllE (Left x)
+    AllE (Left  x) <> AllE (Left  y) = AllE (Left  (x <> y))
+#endif
+
 instance (Monoid e, Monoid r) => Monoid (AllE e r) where
     mempty = AllE (Right mempty)
+#if !(MIN_VERSION_base(4,11,0))
     mappend (AllE (Right x)) (AllE (Right y)) = AllE (Right (mappend x y))
     mappend (AllE (Right _)) (AllE (Left  y)) = AllE (Left y)
     mappend (AllE (Left  x)) (AllE (Right _)) = AllE (Left x)
     mappend (AllE (Left  x)) (AllE (Left  y)) = AllE (Left  (mappend x y))
+#endif
 
 {-| Run multiple 'Either' computations and succeed if any of them succeed
 
@@ -204,12 +221,22 @@
 -}
 newtype AnyE e r = AnyE { runAnyE :: Either e r }
 
+#if MIN_VERSION_base(4,9,0)
+instance (Semigroup e, Semigroup r) => Semigroup (AnyE e r) where
+    AnyE (Right x) <> AnyE (Right y) = AnyE (Right (x <> y))
+    AnyE (Right x) <> AnyE (Left  _) = AnyE (Right x)
+    AnyE (Left  _) <> AnyE (Right y) = AnyE (Right y)
+    AnyE (Left  x) <> AnyE (Left  y) = AnyE (Left  (x <> y))
+#endif
+
 instance (Monoid e, Monoid r) => Monoid (AnyE e r) where
     mempty = AnyE (Right mempty)
+#if !(MIN_VERSION_base(4,11,0))
     mappend (AnyE (Right x)) (AnyE (Right y)) = AnyE (Right (mappend x y))
     mappend (AnyE (Right x)) (AnyE (Left  _)) = AnyE (Right x)
     mappend (AnyE (Left  _)) (AnyE (Right y)) = AnyE (Right y)
     mappend (AnyE (Left  x)) (AnyE (Left  y)) = AnyE (Left  (mappend x y))
+#endif
 
 -- | Analogous to 'isLeft', but for 'ExceptT'
 isLeftT :: (Monad m) => ExceptT a m b -> m Bool
@@ -228,19 +255,30 @@
 fmapRT = liftM
 
 -- | Write a string to standard error
-err :: String -> IO ()
-err = hPutStr stderr
+err :: Text -> IO ()
+err = Data.Text.IO.hPutStr stderr
 
 -- | Write a string with a newline to standard error
-errLn :: String -> IO ()
-errLn = hPutStrLn stderr
+errLn :: Text -> IO ()
+errLn = Data.Text.IO.hPutStrLn stderr
 
 -- | Catch 'IOException's and convert them to the 'ExceptT' monad
 tryIO :: MonadIO m => IO a -> ExceptT IOException m a
 tryIO = ExceptT . liftIO . Exception.try
 
+-- | Run a monad action which may throw an exception in the `ExceptT` monad
+handleExceptT :: (Exception e, Functor m, MonadCatch m) => (e -> x) -> m a -> ExceptT x m a
+handleExceptT handler = bimapExceptT handler id . ExceptT . try
+
+
 {-| Catch all exceptions, except for asynchronous exceptions found in @base@
     and convert them to the 'ExceptT' monad
 -}
-syncIO :: Unexceptional m => IO a -> ExceptT SomeException m a
-syncIO = ExceptT . UIO.liftUIO . UIO.fromIO
+syncIO :: MonadIO m => IO a -> ExceptT SomeException m a
+syncIO = ExceptT . liftIO . trySync
+
+trySync :: IO a -> IO (Either SomeException a)
+trySync io = (fmap Right io) `Exception.catch` \e ->
+  case Exception.fromException e of
+    Just (Exception.SomeAsyncException _) -> Exception.throwIO e
+    Nothing -> return (Left e)
diff --git a/Data/EitherR.hs b/Data/EitherR.hs
--- a/Data/EitherR.hs
+++ b/Data/EitherR.hs
@@ -173,7 +173,7 @@
 succeedT :: (Monad m) => r -> ExceptRT r m e
 succeedT r = ExceptRT (return r)
 
--- | 'catchT' with the arguments flipped
+-- | 'catchE' with the arguments flipped
 handleE :: (Monad m) => (a -> ExceptT b m r) -> ExceptT a m r -> ExceptT b m r
 handleE = flip catchE
 
diff --git a/errors.cabal b/errors.cabal
--- a/errors.cabal
+++ b/errors.cabal
@@ -1,8 +1,8 @@
 Name: errors
-Version: 2.1.3
+Version: 2.3.0
 Cabal-Version: >=1.8.0.2
 Build-Type: Simple
-Tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.2, GHC == 8.0.1
+Tested-With: GHC == 7.8.4, GHC == 7.10.2, GHC == 8.0.1
 License: BSD3
 License-File: LICENSE
 Copyright: 2012, 2013 Gabriel Gonzalez
@@ -24,10 +24,11 @@
 
 Library
     Build-Depends:
-        base                >= 4     && < 5  ,
-        transformers        >= 0.2   && < 0.6,
-        transformers-compat >= 0.4   && < 0.6,
-        unexceptionalio     >= 0.3   && < 0.4
+        base                >= 4.7   && < 5   ,
+        exceptions          >= 0.6   && < 0.11,
+        text                            < 1.3 ,
+        transformers        >= 0.2   && < 0.6 ,
+        transformers-compat >= 0.4   && < 0.7
     if impl(ghc <= 7.6.3)
         Build-Depends:
             safe            >= 0.3.3 && < 0.3.10
