{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Prometheus.MonadMonitor (
MonadMonitor (..)
, Monitor
, runMonitor
, MonitorT
, runMonitorT
) where
import Control.Applicative (Applicative)
import Control.Monad.Identity (Identity, runIdentity)
import Control.Monad.Trans.Class
import Control.Monad.Trans.Class (MonadTrans)
import Control.Monad.Trans.Error (ErrorT, Error)
import Control.Monad.Trans.Except (ExceptT)
import Control.Monad.Trans.Identity (IdentityT)
import Control.Monad.Trans.Maybe (MaybeT)
import qualified Control.Monad.Trans.RWS.Lazy as L
import qualified Control.Monad.Trans.RWS.Strict as S
import Control.Monad.Trans.Reader (ReaderT)
import qualified Control.Monad.Trans.State.Lazy as L
import qualified Control.Monad.Trans.State.Strict as S
import qualified Control.Monad.Trans.Writer.Lazy as L
import qualified Control.Monad.Trans.Writer.Strict as S
import Control.Monad.Writer.Strict (WriterT, runWriterT, tell)
import Data.Monoid (Monoid)
class Monad m => MonadMonitor m where
doIO :: IO () -> m ()
default doIO :: (MonadTrans t, MonadMonitor n, m ~ t n) => IO () -> m ()
doIO = lift . doIO
instance MonadMonitor IO where
doIO = id
instance (Error e, MonadMonitor m) => MonadMonitor (ErrorT e m)
instance (MonadMonitor m) => MonadMonitor (ExceptT e m)
instance (MonadMonitor m) => MonadMonitor (IdentityT m)
instance (MonadMonitor m) => MonadMonitor (MaybeT m)
instance (MonadMonitor m, Monoid w) => MonadMonitor (L.RWST r w s m)
instance (MonadMonitor m, Monoid w) => MonadMonitor (S.RWST r w s m)
instance (MonadMonitor m) => MonadMonitor (ReaderT r m)
instance (MonadMonitor m) => MonadMonitor (L.StateT s m)
instance (MonadMonitor m) => MonadMonitor (S.StateT s m)
instance (MonadMonitor m, Monoid w) => MonadMonitor (L.WriterT w m)
instance (MonadMonitor m, Monoid w) => MonadMonitor (S.WriterT w m)
type Monitor a = MonitorT Identity a
newtype MonitorT m a = MkMonitorT (WriterT [IO ()] m a)
deriving (Applicative, Functor, Monad, MonadTrans)
instance Monad m => MonadMonitor (MonitorT m) where
doIO f = MkMonitorT $ tell [f]
runMonitor :: Monitor a -> (a, IO ())
runMonitor a = runIdentity $ runMonitorT a
runMonitorT :: Monad m => MonitorT m a -> m (a, IO ())
runMonitorT (MkMonitorT writerT) = do
(v, operations) <- runWriterT writerT
return (v, sequence_ operations)