diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
 # json-tracer
 Type-safe polymorphic json-structured tracing library
 
+[hackage](https://hackage.haskell.org/package/json-tracer)
+
 This library provides two modules
 - `Data.PolyDict`: type-safe, polymorphic, and json-structured dictionary
 - `Control.Monad.CTrace`: a monad that enables contextual tracing
diff --git a/example/Fib.hs b/example/Fib.hs
--- a/example/Fib.hs
+++ b/example/Fib.hs
@@ -3,6 +3,7 @@
 import Lens.Micro
 import Control.Monad.CTrace
 import Data.PolyDict
+import Control.Monad.IO.Class
 
 data Fib
 type instance Assoc Fib "arg"  = Int
@@ -10,7 +11,7 @@
 type instance Assoc Fib "left"  = Dict Fib
 type instance Assoc Fib "right" = Dict Fib
 
-fib :: Monad m => Int -> TracerT (Dict Fib) m Int
+fib :: MonadIO m => Int -> TracerT (Dict Fib) m Int
 fib n = do
     update (access #arg ?~ n)
     r <- case n of
diff --git a/example/Fib2.hs b/example/Fib2.hs
--- a/example/Fib2.hs
+++ b/example/Fib2.hs
@@ -2,6 +2,7 @@
 module Fib2 where
 import Fib(Fib)
 import Lens.Micro
+import Control.Monad.IO.Class
 import Control.Monad.CTrace
 import Data.PolyDict
 import Control.Monad.State.Strict
@@ -24,7 +25,7 @@
             update $ access' #calls [] %~ ((n,v):)
             return v
 
-fib :: Monad m => Int -> TracerT (Dict Fib) m Int
+fib :: MonadIO m => Int -> TracerT (Dict Fib) m Int
 fib n = do
     update (access #arg ?~ n)
     r <- evalStateT (memoFib n) (M.empty)
diff --git a/json-tracer.cabal b/json-tracer.cabal
--- a/json-tracer.cabal
+++ b/json-tracer.cabal
@@ -1,5 +1,5 @@
 name:                json-tracer
-version:             0.0.1.2
+version:             0.0.2.0
 synopsis:            A polymorphic, type-safe, json-structured tracing library
 description:         
     .
diff --git a/src/Control/Monad/CTrace.hs b/src/Control/Monad/CTrace.hs
--- a/src/Control/Monad/CTrace.hs
+++ b/src/Control/Monad/CTrace.hs
@@ -11,6 +11,7 @@
 module Control.Monad.CTrace( MonadTrace(..)
                            , TracerT
                            , zoom
+                           , mapTracerT
                            , runTracerT
                            , noTracerT
                            , ioTracerT) where
@@ -25,6 +26,7 @@
 import Control.Monad.Trans.Maybe
 import Control.Monad.Trans.Identity
 import Control.Monad.Trans.Cont
+import Control.Monad.IO.Class
 import qualified Control.Monad.Trans.State.Strict as Strict
 import qualified Control.Monad.Trans.State.Lazy as Lazy
 import qualified Control.Monad.Trans.Writer.Strict as Strict
@@ -40,7 +42,7 @@
     -- | monomorphic version of 'zoom' operation
     zoom'  :: ASetter' c c -> m a -> m a
 
-instance Monad m => MonadTrace c (TracerT c m) where
+instance MonadIO m => MonadTrace c (TracerT c m) where
     update = T.update 
     zoom' = zoom
 
diff --git a/src/Control/Monad/Trans/CTrace.hs b/src/Control/Monad/Trans/CTrace.hs
--- a/src/Control/Monad/Trans/CTrace.hs
+++ b/src/Control/Monad/Trans/CTrace.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving, FunctionalDependencies, UndecidableInstances, StandaloneDeriving #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving, FunctionalDependencies, UndecidableInstances, StandaloneDeriving, ExistentialQuantification #-}
 -- |
 -- Module      : Control.Monad.CTrace
 -- Copyright   : (c) Taku Terao, 2017 
@@ -7,7 +7,7 @@
 -- Stability   : experimental 
 -- Portability : GHC
 -- Contextual tracing monad transformer. transformers-compatible.
-module Control.Monad.Trans.CTrace(TracerT, runTracerT, zoom, update, noTracerT, ioTracerT) where
+module Control.Monad.Trans.CTrace(TracerT, mapTracerT, runTracerT, zoom, update, noTracerT, ioTracerT) where
 
 import Control.Monad.Cont.Class
 import Control.Monad.Reader
@@ -20,16 +20,20 @@
 
 -- | Contextual tracing monad transformer type.
 --   Tracing context c can be modified through this monad.
-newtype TracerT c m a = TracerT (ReaderT (Action c m) m a)
+newtype TracerT c m a = TracerT (ReaderT ((c -> c) -> IO ()) m a)
    deriving(Functor,Monad,Applicative, MonadIO, MonadFix)
 
-type Action c m = (c -> c) -> m ()
 
 -- | Perform modification on the tracing context
-update :: Monad m => (c -> c) -> TracerT c m ()
-update f = TracerT $ ReaderT $ \tracer -> tracer f
+update :: MonadIO m => (c -> c) -> TracerT c m ()
+update f = TracerT $ ReaderT $ \tracer -> liftIO (tracer f)
 {-# INLINE update #-}
 
+-- | Transform the base monad
+mapTracerT :: (m a -> n b) -> TracerT c m a -> TracerT c n b
+mapTracerT f (TracerT v) = TracerT $ mapReaderT f v
+{-# INLINE mapTracerT #-}
+
 -- | Change the tracing context. 
 zoom :: ASetter' c c' -> TracerT c' m a -> TracerT c m a
 zoom l (TracerT m) = TracerT $ ReaderT $ \action ->
@@ -41,7 +45,7 @@
     {-# INLINE lift #-}
 
 -- | Run the tracer monad with the specified update action.
-runTracerT :: ((c -> c) -> m ()) -> TracerT c m a -> m a
+runTracerT :: ((c -> c) -> IO ()) -> TracerT c m a -> m a
 runTracerT action (TracerT m) = runReaderT m action
 {-# INLINE runTracerT #-}
 
@@ -54,7 +58,7 @@
 ioTracerT :: MonadIO m => c -> TracerT c m a -> m (a,c)
 ioTracerT init m = do
     r <- liftIO $ newIORef init
-    v <- runTracerT (liftIO . modifyIORef' r) m
+    v <- runTracerT (modifyIORef' r) m
     c <- liftIO $ readIORef r
     return (v,c)
 {-# INLINE ioTracerT #-}
