module Control.Monad.Trans.Trace
( TraceT
, runTraceT
) where
import Control.Applicative
import Control.Monad
import Control.Monad.Base
import Control.Monad.Error.Class
import Control.Monad.Identity
import Control.Monad.Trace.Class
import Control.Monad.Trace.ErrorTrace
import Control.Monad.Trans
import Control.Monad.Trans.Control
import Control.Monad.Trans.Either
import Control.Monad.Trans.State.Strict
import Control.Monad.Trans.Reader
import Data.Monoid
import Data.Sequence as S
newtype TraceT t e m α
= TraceT
{ _traceT ∷ EitherT (ErrorTrace t e) (ReaderT (Seq t) m) α
} deriving (Functor, Monad, Applicative, Alternative, MonadIO, MonadBase b)
instance Monad m ⇒ MonadError e (TraceT t e m) where
throwError e = readTrace >>= TraceT . left . ErrorTrace e . (:[])
catchError (TraceT m) h = TraceT (lift $ runEitherT m) >>= either (h . _etError) return
instance MonadTrans (TraceT t e) where
lift = TraceT . EitherT . (>>= return . Right) . lift
instance Monad m ⇒ MonadTrace t (TraceT t e m) where
traceScope t = TraceT . mapEitherT (withReaderT (|> t)) . _traceT
readTrace = TraceT . EitherT $ ask >>= return . Right
data Welp = Welp deriving Show
instance Monoid Welp where
mempty = Welp
mappend _ _ = Welp
example ∷ String -> TraceT String Welp IO ()
example str = do
traceScope "A" $ return ()
traceScope "Z" $ readTrace >>= liftIO . print
traceScope str $ throwError Welp
runTraceT
∷ ( Functor m
, Monad m
)
⇒ TraceT t e m α
→ m (Either (ErrorTrace t e) α)
runTraceT (TraceT m) = runReaderT (runEitherT m) S.empty
instance MonadTransControl (TraceT t e) where
newtype StT (TraceT t e) α = StTraceT { unStTraceT ∷ StT (ReaderT (Seq t)) (StT (EitherT (ErrorTrace t e)) α) }
liftWith f = TraceT . liftWith $ \run → liftWith $ \run' → f $ liftM StTraceT . run' . run . _traceT
restoreT = TraceT . restoreT . restoreT . liftM unStTraceT
instance MonadBaseControl b m => MonadBaseControl b (TraceT t e m) where
newtype StM (TraceT t e m) α = StMTraceT { unStMTraceT ∷ ComposeSt (TraceT t e) m α }
liftBaseWith = defaultLiftBaseWith StMTraceT
restoreM = defaultRestoreM unStMTraceT