{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}
module Control.Monatron.MonadInfo (
MInfo(..), MonadInfo(minfo), MonadInfoT(tminfo),
miInc
) where
import Control.Monatron.Monad
import Control.Monatron.MonadT
import Control.Monatron.IdT
import Control.Monatron.Transformer
import Control.Monatron.Zipper
import Control.Monatron.Codensity
import Data.Map (Map)
import qualified Data.Map as Map
newtype MInfo = MInfo (Map String Int)
deriving (Show, Eq, Ord)
miBase = MInfo Map.empty
miInc s (MInfo m) = MInfo $ Map.alter (\x -> case x of { Nothing -> Just 1; Just n -> Just (n+1) }) s m
undef :: a
undef = error "MonadInfo: undefined"
class Monad m => MonadInfo m where
minfo :: m a -> MInfo
class MonadT t => MonadInfoT t where
tminfo :: MonadInfo m => t m a -> MInfo
instance MonadInfoT (StateT s) where
tminfo x = miInc "StateT" (minfo $ runStateT (undef :: s) x)
instance Monoid w => MonadInfoT (WriterT w) where
tminfo x = miInc "WriterT" (minfo $ runWriterT x)
instance MonadInfoT (ReaderT s) where
tminfo x = miInc "ReaderT" (minfo $ runReaderT (undef :: s) x)
instance MonadInfoT (ExcT x) where
tminfo x = miInc "ExcT" (minfo $ runExcT x)
instance MonadInfoT (ContT x) where
tminfo x = miInc "ContT" (minfo $ runContT (undef) x)
instance MonadInfoT ListT where
tminfo x = miInc "ListT" (minfo $ runListT x)
instance Functor f => MonadInfoT (StepT f) where
tminfo x = miInc "StepT" (minfo $ runStepT x)
instance (MonadInfoT t1, MonadInfoT t2) => MonadInfoT (t1 :> t2) where
tminfo x = miInc ":>" (minfo $ runZipper x)
instance MonadInfoT Codensity where
tminfo x = miInc "Codensity" (minfo $ runCodensity x)
instance MonadInfo Id where
minfo _ = miInc "Id" miBase
instance MonadInfo Lift where
minfo _ = miInc "Lift" miBase
instance MonadInfoT IdT where
tminfo x = miInc "IdT" (minfo $ runIdT x)
instance (MonadInfo m, MonadInfoT t) => MonadInfo (t m) where
minfo x = tminfo x