diff --git a/protolude.cabal b/protolude.cabal
--- a/protolude.cabal
+++ b/protolude.cabal
@@ -1,5 +1,5 @@
 name:                protolude
-version:             0.1.6
+version:             0.1.7
 synopsis:            A sensible set of defaults for writing custom Preludes.
 description:         A sensible set of defaults for writing custom Preludes.
 homepage:            https://github.com/sdiehl/protolude
diff --git a/src/Debug.hs b/src/Debug.hs
--- a/src/Debug.hs
+++ b/src/Debug.hs
@@ -6,8 +6,10 @@
   error,
   trace,
   traceM,
+  traceId,
   traceIO,
   traceShow,
+  traceShowId,
   traceShowM,
   notImplemented,
 ) where
@@ -16,31 +18,45 @@
 import Control.Monad (Monad, return)
 
 import qualified Base as P
-import qualified Debug.Trace as T
+import Show (Print, putStrLn)
 
+import System.IO.Unsafe (unsafePerformIO)
+
+{-# WARNING trace "'trace' remains in code" #-}
+trace :: Print b => b -> a -> a
+trace string expr = unsafePerformIO (do
+    putStrLn string
+    return expr)
+
+{-# WARNING traceIO "'traceIO' remains in code" #-}
+traceIO :: Print b => b -> a -> P.IO a
+traceIO string expr = do
+    putStrLn string
+    return expr
+
 {-# WARNING error "'error' remains in code" #-}
 error :: Text -> a
 error s = P.error (unpack s)
 
-{-# WARNING trace "'trace' remains in code" #-}
-trace :: Text -> a -> a
-trace s = T.trace (unpack s)
-
 {-# WARNING traceShow "'traceShow' remains in code" #-}
 traceShow :: P.Show a => a -> b -> b
-traceShow a b = T.trace (P.show a) b
+traceShow a b = trace (P.show a) b
 
+{-# WARNING traceShowId "'traceShowId' remains in code" #-}
+traceShowId :: P.Show a => a -> a
+traceShowId a = trace (P.show a) a
+
 {-# WARNING traceShowM "'traceShowM' remains in code" #-}
 traceShowM :: (P.Show a, Monad m) => a -> m ()
-traceShowM a = T.trace (P.show a) (return ())
+traceShowM a = trace (P.show a) (return ())
 
 {-# WARNING traceM "'traceM' remains in code" #-}
 traceM :: (Monad m) => Text -> m ()
-traceM s = T.trace (unpack s) (return ())
+traceM s = trace (unpack s) (return ())
 
-{-# WARNING traceIO "'traceIO' remains in code" #-}
-traceIO :: Text -> P.IO ()
-traceIO s = T.traceIO (unpack s)
+{-# WARNING traceId "'traceM' remains in code" #-}
+traceId :: Text -> Text
+traceId s = trace s s
 
 notImplemented :: a
 notImplemented = P.error "Not implemented"
diff --git a/src/Monad.hs b/src/Monad.hs
--- a/src/Monad.hs
+++ b/src/Monad.hs
@@ -9,6 +9,7 @@
   , (=<<)
   , (>=>)
   , (<=<)
+  , (>>)
   , forever
 
   , join
diff --git a/src/Protolude.hs b/src/Protolude.hs
--- a/src/Protolude.hs
+++ b/src/Protolude.hs
@@ -15,6 +15,8 @@
   unsnoc,
   applyN,
   print,
+  throwIO,
+  throwTo,
   show,
 
   LText,
@@ -196,6 +198,7 @@
   , get
   , gets
   , modify
+  , state
   , withState
 
   , runState
@@ -214,6 +217,7 @@
   , ask
   , asks
   , local
+  , reader
   , runReader
   , runReaderT
   )
@@ -326,12 +330,19 @@
 
 -- Concurrency and Parallelism
 import Control.Exception as X hiding (
-    throw
+    throw    -- Impure throw is forbidden.
+  , throwIO
+  , throwTo
   , assert
   , displayException
   )
+
+import qualified Control.Exception
+
 import Control.Monad.STM as X
-import Control.Concurrent as X
+import Control.Concurrent as X hiding (
+    throwTo
+  )
 import Control.Concurrent.Async as X
 
 import Foreign.Storable as X (Storable)
@@ -375,6 +386,12 @@
 
 print :: (X.MonadIO m, PBase.Show a) => a -> m ()
 print = liftIO . PBase.print
+
+throwIO :: (X.MonadIO m, Exception e) => e -> m a
+throwIO = liftIO . Control.Exception.throwIO
+
+throwTo :: (X.MonadIO m, Exception e) => ThreadId -> e -> m ()
+throwTo tid e = liftIO (Control.Exception.throwTo tid e)
 
 show :: (Show a, StringConv String b) => a -> b
 show x = toS (PBase.show x)
