monad-effect-0.2.0.0: src/Control/Monad/RS/Class.hs
-- This module provides two interface MonadReadable and MonadStateful, unlike MonadReader
-- and MonadState, these interfaces do not have functional dependencies, allowing for
-- simple and extensible state and read effects.
module Control.Monad.RS.Class where
import Control.Monad.Trans
-- | A class for monads that can read a value of type 'r'.
-- without the functional dependencies, so you can read different types of values
-- This ReadOnly has no 'local' method
class Monad m => MonadReadOnly r m where
-- | Query the monad for a value of type 'r'.
query :: m r
-- | Transform the result of a query using a function.
queries :: (r -> r') -> m r'
queries f = f <$> query
{-# INLINE queries #-}
-- | A class for monads that can read a value of type 'r'.
-- without the functional dependencies, so you can read different types of values
class MonadReadOnly r m => MonadReadable r m where
local :: (r -> r) -> m a -> m a
-- | A class for monads that can maintain a state of type 's'.
-- without the functional dependencies, so you can have different types of states
class Monad m => MonadStateful s m where
{-# MINIMAL get, put #-}
-- | Get the current state.
get :: m s
gets :: (s -> a) -> m a
gets f = f <$> get
{-# INLINE gets #-}
-- | Set the state to a new value.
put :: s -> m ()
-- | Modify the current state using a function.
modify :: (s -> s) -> m ()
modify f = do
s <- get
put (f s)
{-# INLINE modify #-}
instance {-# OVERLAPPABLE #-} (MonadTrans t, MonadReadOnly r m) => MonadReadOnly r (t m) where
query = lift query
{-# INLINE query #-}
instance {-# OVERLAPPABLE #-} (MonadTrans t, MonadStateful s m) => MonadStateful s (t m) where
get = lift get
{-# INLINE get #-}
put = lift . put
{-# INLINE put #-}
modify = lift . modify
{-# INLINE modify #-}