{-# LANGUAGE GeneralizedNewtypeDeriving, FunctionalDependencies, UndecidableInstances, StandaloneDeriving, ExistentialQuantification #-}
module Control.Monad.Trans.CTrace(TracerT, mapTracerT, runTracerT, zoom, update, noTracerT, ioTracerT) where
import Control.Monad.Cont.Class
import Control.Monad.Reader
import Control.Monad.Writer.Class
import Control.Monad.Error.Class
import Control.Monad.State.Class
import Control.Monad.RWS.Class
import Lens.Micro
import Data.IORef
newtype TracerT c m a = TracerT (ReaderT ((c -> c) -> IO ()) m a)
deriving(Functor,Monad,Applicative, MonadIO, MonadFix)
update :: MonadIO m => (c -> c) -> TracerT c m ()
update f = TracerT $ ReaderT $ \tracer -> liftIO (tracer f)
{-# INLINE update #-}
mapTracerT :: (m a -> n b) -> TracerT c m a -> TracerT c n b
mapTracerT f (TracerT v) = TracerT $ mapReaderT f v
{-# INLINE mapTracerT #-}
zoom :: ASetter' c c' -> TracerT c' m a -> TracerT c m a
zoom l (TracerT m) = TracerT $ ReaderT $ \action ->
runReaderT m (\updateFunc -> action (over l updateFunc))
{-# INLINE zoom #-}
instance MonadTrans (TracerT c) where
lift = TracerT . lift
{-# INLINE lift #-}
runTracerT :: ((c -> c) -> IO ()) -> TracerT c m a -> m a
runTracerT action (TracerT m) = runReaderT m action
{-# INLINE runTracerT #-}
noTracerT :: Monad m => TracerT c m a -> m a
noTracerT = runTracerT (const (return ()))
{-# INLINE noTracerT #-}
ioTracerT :: MonadIO m => c -> TracerT c m a -> m (a,c)
ioTracerT init m = do
r <- liftIO $ newIORef init
v <- runTracerT (modifyIORef' r) m
c <- liftIO $ readIORef r
return (v,c)
{-# INLINE ioTracerT #-}
instance MonadReader r m => MonadReader r (TracerT c m) where
ask = lift ask
reader = lift . reader
local f (TracerT m) = TracerT (ReaderT $ local f . runReaderT m)
deriving instance MonadWriter w m => MonadWriter w (TracerT c m)
deriving instance MonadError e m => MonadError e (TracerT c m)
deriving instance MonadState s m => MonadState s (TracerT c m)
deriving instance MonadRWS r w s m => MonadRWS r w s (TracerT c m)
deriving instance MonadCont m => MonadCont (TracerT c m)