diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,13 @@
 # Changelog for unliftio
 
+## 0.2.23.0
+
+* `UnliftIO.Exception` re-exports the `Handler` and sync/async exception wrappers
+  from `safe-exceptions`, instead of redefining them.
+    * With this change, you won't be able to distinguish between an asynchronous
+      exception from `UnliftIO.Exception.throwTo` and `Control.Exception.Safe.throwTo`.
+    * [#103](https://github.com/fpco/unliftio/pull/103)
+
 ## 0.2.22.0
 
 * Add `UnliftIO.STM.flushTBQueue`
diff --git a/src/UnliftIO/Exception.hs b/src/UnliftIO/Exception.hs
--- a/src/UnliftIO/Exception.hs
+++ b/src/UnliftIO/Exception.hs
@@ -47,7 +47,7 @@
   , pureTry
   , pureTryDeep
 
-  , Handler(..)
+  , ESafe.Handler (..)
   , catches
   , catchesDeep
 
@@ -66,9 +66,11 @@
   , bracketOnError_
 
     -- * Coercion to sync and async
-  , SyncExceptionWrapper (..)
+    -- | In version /0.2.23.0/, these were changed with aliases to the values
+    -- from "Control.Exception.Safe" in the @safe-exceptions@ package.
+  , ESafe.SyncExceptionWrapper(..)
   , toSyncException
-  , AsyncExceptionWrapper (..)
+  , ESafe.AsyncExceptionWrapper(..)
   , toAsyncException
   , fromExceptionUnwrap
 
@@ -105,6 +107,8 @@
 import Control.DeepSeq (NFData (..), ($!!))
 import Data.Typeable (Typeable, cast)
 import System.IO.Unsafe (unsafePerformIO)
+import qualified Control.Exception.Safe as ESafe
+import Control.Exception.Safe (Handler(..))
 
 #if MIN_VERSION_base(4,9,0)
 import GHC.Stack (prettySrcLoc)
@@ -284,15 +288,10 @@
 pureTryDeep :: NFData a => a -> Either SomeException a
 pureTryDeep = unsafePerformIO . tryAnyDeep . return
 
--- | A helper data type for usage with 'catches' and similar functions.
---
--- @since 0.1.0.0
-data Handler m a = forall e . Exception e => Handler (e -> m a)
-
 -- | Internal.
 catchesHandler :: MonadIO m => [Handler m a] -> SomeException -> m a
 catchesHandler handlers e = foldr tryHandler (liftIO (EUnsafe.throwIO e)) handlers
-    where tryHandler (Handler handler) res
+    where tryHandler (ESafe.Handler handler) res
               = case fromException e of
                 Just e' -> handler e'
                 Nothing -> res
@@ -441,23 +440,6 @@
 throwIO :: (MonadIO m, Exception e) => e -> m a
 throwIO = liftIO . EUnsafe.throwIO . toSyncException
 
--- | Wrap up an asynchronous exception to be treated as a synchronous
--- exception.
---
--- This is intended to be created via 'toSyncException'.
---
--- @since 0.1.0.0
-data SyncExceptionWrapper = forall e. Exception e => SyncExceptionWrapper e
-    deriving Typeable
--- | @since 0.1.0.0
-instance Show SyncExceptionWrapper where
-    show (SyncExceptionWrapper e) = show e
--- | @since 0.1.0.0
-instance Exception SyncExceptionWrapper where
-#if MIN_VERSION_base(4,8,0)
-    displayException (SyncExceptionWrapper e) = displayException e
-#endif
-
 -- | Convert an exception into a synchronous exception.
 --
 -- For synchronous exceptions, this is the same as 'toException'.
@@ -466,33 +448,8 @@
 --
 -- @since 0.1.0.0
 toSyncException :: Exception e => e -> SomeException
-toSyncException e =
-    case fromException se of
-        Just (SomeAsyncException _) -> toException (SyncExceptionWrapper e)
-        Nothing -> se
-  where
-    se = toException e
-
--- | Wrap up a synchronous exception to be treated as an asynchronous
--- exception.
---
--- This is intended to be created via 'toAsyncException'.
---
--- @since 0.1.0.0
-data AsyncExceptionWrapper = forall e. Exception e => AsyncExceptionWrapper e
-    deriving Typeable
--- | @since 0.1.0.0
-instance Show AsyncExceptionWrapper where
-    show (AsyncExceptionWrapper e) = show e
--- | @since 0.1.0.0
-instance Exception AsyncExceptionWrapper where
-    toException = toException . SomeAsyncException
-    fromException se = do
-        SomeAsyncException e <- fromException se
-        cast e
-#if MIN_VERSION_base(4,8,0)
-    displayException (AsyncExceptionWrapper e) = displayException e
-#endif
+toSyncException =
+    ESafe.toSyncException
 
 -- | Convert an exception into an asynchronous exception.
 --
@@ -502,12 +459,8 @@
 --
 -- @since 0.1.0.0
 toAsyncException :: Exception e => e -> SomeException
-toAsyncException e =
-    case fromException se of
-        Just (SomeAsyncException _) -> se
-        Nothing -> toException (AsyncExceptionWrapper e)
-  where
-    se = toException e
+toAsyncException =
+    ESafe.toAsyncException
 
 -- | Convert from a possibly wrapped exception.
 --
@@ -519,18 +472,16 @@
 -- @since 0.2.17
 fromExceptionUnwrap :: Exception e => SomeException -> Maybe e
 fromExceptionUnwrap se
-  | Just (AsyncExceptionWrapper e) <- fromException se = cast e
-  | Just (SyncExceptionWrapper e) <- fromException se = cast e
+  | Just (ESafe.AsyncExceptionWrapper e) <- fromException se = cast e
+  | Just (ESafe.SyncExceptionWrapper e) <- fromException se = cast e
   | otherwise = fromException se
 
 -- | Check if the given exception is synchronous.
 --
 -- @since 0.1.0.0
 isSyncException :: Exception e => e -> Bool
-isSyncException e =
-    case fromException (toException e) of
-        Just (SomeAsyncException _) -> False
-        Nothing -> True
+isSyncException =
+    ESafe.isSyncException
 
 -- | Check if the given exception is asynchronous.
 --
diff --git a/unliftio.cabal b/unliftio.cabal
--- a/unliftio.cabal
+++ b/unliftio.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.34.4.
+-- This file has been generated from package.yaml by hpack version 0.35.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           unliftio
-version:        0.2.22.0
+version:        0.2.23.0
 synopsis:       The MonadUnliftIO typeclass for unlifting monads to IO (batteries included)
 description:    Please see the documentation and README at <https://www.stackage.org/package/unliftio>
 category:       Control
@@ -55,10 +55,12 @@
     , directory
     , filepath
     , process >=1.2.0.0
+    , safe-exceptions
     , stm >=2.5
     , time
     , transformers
     , unliftio-core >=0.1.1.0
+  default-language: Haskell2010
   if os(windows)
     cpp-options: -DWINDOWS
   else
@@ -83,7 +85,6 @@
       c-sources:
           cbits/file-posix.c
           cbits/time-posix.c
-  default-language: Haskell2010
 
 test-suite unliftio-spec
   type: exitcode-stdio-1.0
@@ -110,17 +111,18 @@
     , filepath
     , hspec
     , process >=1.2.0.0
+    , safe-exceptions
     , stm >=2.5
     , time
     , transformers
     , unliftio
     , unliftio-core >=0.1.1.0
+  default-language: Haskell2010
   if os(windows)
     cpp-options: -DWINDOWS
   else
     build-depends:
         unix
-  default-language: Haskell2010
 
 benchmark conc-bench
   type: exitcode-stdio-1.0
@@ -139,14 +141,15 @@
     , filepath
     , gauge
     , process >=1.2.0.0
+    , safe-exceptions
     , stm >=2.5
     , time
     , transformers
     , unliftio
     , unliftio-core >=0.1.1.0
+  default-language: Haskell2010
   if os(windows)
     cpp-options: -DWINDOWS
   else
     build-depends:
         unix
-  default-language: Haskell2010
