module Ganeti.Logging.WriterLog
( WriterLogT
, WriterLog
, runWriterLogT
, runWriterLog
, dumpLogSeq
, execWriterLogT
, execWriterLog
) where
#define MIN_VERSION_monad_control(maj,min,rev) \
(((maj)<MONAD_CONTROL_MAJOR)|| \
(((maj)==MONAD_CONTROL_MAJOR)&&((min)<=MONAD_CONTROL_MINOR))|| \
(((maj)==MONAD_CONTROL_MAJOR)&&((min)==MONAD_CONTROL_MINOR)&& \
((rev)<=MONAD_CONTROL_REV)))
import Control.Applicative
import Control.Monad
import Control.Monad.Base
import Control.Monad.IO.Class
import Control.Monad.Trans.Control
import Control.Monad.Writer
import qualified Data.Foldable as F
import Data.Functor.Identity
import Data.Sequence
import Ganeti.Logging
type LogSeq = Seq (Priority, String)
type WriterSeq = WriterT LogSeq
newtype WriterLogT m a =
WriterLogT { unwrapWriterLogT :: WriterSeq m a }
type WriterLog = WriterLogT Identity
runWriterLogT :: WriterLogT m a -> m (a, LogSeq)
runWriterLogT = runWriterT . unwrapWriterLogT
runWriterLog :: WriterLog a -> (a, LogSeq)
runWriterLog = runIdentity . runWriterLogT
execWriterLogT :: (MonadLog m) => WriterLogT m a -> m a
execWriterLogT k = do
(r, msgs) <- runWriterLogT k
F.mapM_ (uncurry logAt) msgs
return r
dumpLogSeq :: (MonadLog m) => LogSeq -> m ()
dumpLogSeq = F.mapM_ (uncurry logAt)
execWriterLog :: (MonadLog m) => WriterLog a -> m a
execWriterLog k = do
let (r, msgs) = runWriterLog k
dumpLogSeq msgs
return r
instance (Monad m) => Functor (WriterLogT m) where
fmap = liftM
instance (Monad m) => Applicative (WriterLogT m) where
pure = return
(<*>) = ap
instance (MonadPlus m) => Alternative (WriterLogT m) where
empty = mzero
(<|>) = mplus
instance (Monad m) => Monad (WriterLogT m) where
return = WriterLogT . return
(WriterLogT k) >>= f = WriterLogT $ k >>= (unwrapWriterLogT . f)
instance (Monad m) => MonadLog (WriterLogT m) where
logAt = curry (WriterLogT . tell . singleton)
instance (MonadIO m) => MonadIO (WriterLogT m) where
liftIO = WriterLogT . liftIO
instance (MonadPlus m) => MonadPlus (WriterLogT m) where
mzero = lift mzero
mplus (WriterLogT x) (WriterLogT y) = WriterLogT $ mplus x y
instance (MonadBase IO m) => MonadBase IO (WriterLogT m) where
liftBase = WriterLogT . liftBase
instance MonadTrans WriterLogT where
lift = WriterLogT . lift
instance MonadTransControl WriterLogT where
#if MIN_VERSION_monad_control(1,0,0)
type StT WriterLogT a = (a, LogSeq)
liftWith f = WriterLogT . WriterT $ liftM (\x -> (x, mempty))
(f runWriterLogT)
restoreT = WriterLogT . WriterT
#else
newtype StT WriterLogT a =
StWriterLog { unStWriterLog :: (a, LogSeq) }
liftWith f = WriterLogT . WriterT $ liftM (\x -> (x, mempty))
(f $ liftM StWriterLog . runWriterLogT)
restoreT = WriterLogT . WriterT . liftM unStWriterLog
#endif
instance (MonadBaseControl IO m)
=> MonadBaseControl IO (WriterLogT m) where
#if MIN_VERSION_monad_control(1,0,0)
type StM (WriterLogT m) a
= ComposeSt WriterLogT m a
liftBaseWith = defaultLiftBaseWith
restoreM = defaultRestoreM
#else
newtype StM (WriterLogT m) a
= StMWriterLog { runStMWriterLog :: ComposeSt WriterLogT m a }
liftBaseWith = defaultLiftBaseWith StMWriterLog
restoreM = defaultRestoreM runStMWriterLog
#endif