{-# LANGUAGE PolyKinds, FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-} module System.Metrics.Monad ( MonadMetrics(..) , MetricsT , runMetricsT , Metrics ) where import Control.Monad.Catch import Control.Monad.IO.Class import Control.Monad.Reader import System.Metrics.Monad.Class import System.Metrics.Store newtype MetricsT (m :: k -> *) (a :: k) = MetricsT { runMetricsT :: MetricsStore -> m a } type Metrics = MetricsT IO instance Functor m => Functor (MetricsT m) where fmap f (MetricsT m) = MetricsT $ fmap f . m instance Applicative m => Applicative (MetricsT m) where pure = MetricsT . const . pure (MetricsT fun) <*> (MetricsT val) = MetricsT $ \store -> fun store <*> val store instance Monad m => Monad (MetricsT m) where (MetricsT val) >>= f = MetricsT $ \store -> val store >>= \a -> runMetricsT (f a) store instance MonadIO m => MonadMetrics (MetricsT m) where getTracker metric = MetricsT $ \store -> liftIO $ getMetricFromStore store metric instance MonadTrans MetricsT where lift m = MetricsT $ const m instance MonadIO m => MonadIO (MetricsT m) where liftIO act = MetricsT $ const $ liftIO act instance MonadReader r m => MonadReader r (MetricsT m) where ask = MetricsT $ const ask reader f = MetricsT $ const $ reader f local m (MetricsT rFun) = MetricsT $ local m . rFun instance MonadThrow m => MonadThrow (MetricsT m) where throwM ex = MetricsT $ const $ throwM ex instance MonadCatch m => MonadCatch (MetricsT m) where catch (MetricsT act) handler = MetricsT $ \store -> catch (act store) $ \ex -> runMetricsT (handler ex) store