{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Colog.Monad
( LoggerT (..)
, WithLog
, logMsg
, logMsgs
, withLog
, liftLogAction
, usingLoggerT
) where
import Control.Monad.Reader (MonadReader (..), ReaderT)
import Control.Monad.Trans.Class (MonadTrans (..))
import Colog.Core (HasLog (..), LogAction (..), overLogAction)
newtype LoggerT msg m a = LoggerT
{ runLoggerT :: ReaderT (LogAction (LoggerT msg m) msg) m a
} deriving (Functor, Applicative, Monad, MonadIO, MonadReader (LogAction (LoggerT msg m) msg))
instance MonadTrans (LoggerT msg) where
lift :: Monad m => m a -> LoggerT msg m a
lift = LoggerT . lift
type WithLog env msg m = (MonadReader env m, HasLog env msg m, HasCallStack)
logMsg :: forall msg env m . WithLog env msg m => msg -> m ()
logMsg msg = do
LogAction log <- asks getLogAction
log msg
logMsgs :: forall msg env f m . (Foldable f, WithLog env msg m) => f msg -> m ()
logMsgs = traverse_ logMsg
withLog :: WithLog env msg m => (LogAction m msg -> LogAction m msg) -> m a -> m a
withLog = local . overLogAction
liftLogAction :: (Monad m, MonadTrans t) => LogAction m msg -> LogAction (t m) msg
liftLogAction (LogAction action) = LogAction (lift . action)
usingLoggerT :: Monad m => LogAction m msg -> LoggerT msg m a -> m a
usingLoggerT action = flip runReaderT (liftLogAction action) . runLoggerT