module Control.Comonad.Store.Class
( ComonadStore(..)
, gets
, experiment
) where
import Control.Comonad
import Control.Comonad.Trans.Class
import qualified Control.Comonad.Trans.Store as T
import Control.Comonad.Trans.Discont
import Control.Comonad.Trans.Env
import Control.Comonad.Trans.Identity
import Control.Comonad.Trans.Traced
import Data.Monoid
class Comonad w => ComonadStore s w | w -> s where
get :: w a -> s
put :: s -> w a -> a
modify :: (s -> s) -> w a -> a
modify f wa = put (f (get wa)) wa
gets :: ComonadStore s w => (s -> t) -> w a -> t
gets f wa = f (get wa)
experiment :: (ComonadStore s w, Functor f) => f (s -> s) -> w a -> f a
experiment ff wa = fmap (`modify` wa) ff
instance Comonad w => ComonadStore s (T.StoreT s w) where
get = T.get
put = T.put
modify = T.modify
lowerGet :: (ComonadTrans t, ComonadStore s w) => t w a -> s
lowerGet = get . lower
lowerPut :: (ComonadTrans t, ComonadStore s w) => s -> t w a -> a
lowerPut s = put s . lower
lowerModify :: (ComonadTrans t, ComonadStore s w) => (s -> s) -> t w a -> a
lowerModify f = modify f . lower
instance ComonadStore s w => ComonadStore s (DiscontT k w) where
get = lowerGet
put = lowerPut
modify = lowerModify
instance ComonadStore s w => ComonadStore s (IdentityT w) where
get = lowerGet
put = lowerPut
modify = lowerModify
instance ComonadStore s w => ComonadStore s (EnvT e w) where
get = lowerGet
put = lowerPut
modify = lowerModify
instance (ComonadStore s w, Monoid m) => ComonadStore s (TracedT m w) where
get = lowerGet
put = lowerPut
modify = lowerModify