module Control.Monad.Representable.State
( State
, runState
, evalState
, execState
, mapState
, StateT(..)
, stateT
, runStateT
, evalStateT
, execStateT
, mapStateT
, liftCallCC
, liftCallCC'
, get
, gets
, put
, modify
) where
import Control.Applicative
import Data.Key
import Data.Functor.Bind
import Data.Functor.Bind.Trans
import Control.Monad.State.Class
import Control.Monad.Cont.Class
import Control.Monad.Reader.Class
import Control.Monad.Writer.Class
import Control.Monad.Free.Class
import Control.Monad.Trans.Class
import Control.Monad.Identity
import Data.Functor.Representable
type State g = StateT g Identity
runState :: Indexable g
=> State g a
-> Key g
-> (a, Key g)
runState m = runIdentity . runStateT m
evalState :: Indexable g
=> State g a
-> Key g
-> a
evalState m s = fst (runState m s)
execState :: Indexable g
=> State g a
-> Key g
-> Key g
execState m s = snd (runState m s)
mapState :: Functor g => ((a, Key g) -> (b, Key g)) -> State g a -> State g b
mapState f = mapStateT (Identity . f . runIdentity)
newtype StateT g m a = StateT { getStateT :: g (m (a, Key g)) }
stateT :: Representable g => (Key g -> m (a, Key g)) -> StateT g m a
stateT = StateT . tabulate
runStateT :: Indexable g => StateT g m a -> Key g -> m (a, Key g)
runStateT (StateT m) = index m
mapStateT :: Functor g => (m (a, Key g) -> n (b, Key g)) -> StateT g m a -> StateT g n b
mapStateT f (StateT m) = StateT (fmap f m)
evalStateT :: (Indexable g, Monad m) => StateT g m a -> Key g -> m a
evalStateT m s = do
(a, _) <- runStateT m s
return a
execStateT :: (Indexable g, Monad m) => StateT g m a -> Key g -> m (Key g)
execStateT m s = do
(_, s') <- runStateT m s
return s'
instance (Functor g, Functor m) => Functor (StateT g m) where
fmap f = StateT . fmap (fmap (\ ~(a, s) -> (f a, s))) . getStateT
instance (Functor g, Indexable g, Bind m) => Apply (StateT g m) where
mf <.> ma = mf >>- \f -> fmap f ma
instance (Representable g, Functor m, Monad m) => Applicative (StateT g m) where
pure = StateT . leftAdjunctRep return
mf <*> ma = mf >>= \f -> fmap f ma
instance (Functor g, Indexable g, Bind m) => Bind (StateT g m) where
StateT m >>- f = StateT $ fmap (>>- rightAdjunctRep (runStateT . f)) m
instance (Representable g, Monad m) => Monad (StateT g m) where
return = StateT . leftAdjunctRep return
StateT m >>= f = StateT $ fmap (>>= rightAdjunctRep (runStateT . f)) m
instance Representable f => BindTrans (StateT f) where
liftB m = stateT $ \s -> fmap (\a -> (a, s)) m
instance Representable f => MonadTrans (StateT f) where
lift m = stateT $ \s -> liftM (\a -> (a, s)) m
instance (Representable g, Monad m, Key g ~ s) => MonadState s (StateT g m) where
get = stateT $ \s -> return (s, s)
put s = StateT $ pureRep $ return ((),s)
#if MIN_VERSION_transformers(0,3,0)
state f = stateT (return . f)
#endif
instance (Representable g, MonadReader e m) => MonadReader e (StateT g m) where
ask = lift ask
local = mapStateT . local
instance (Representable g, MonadWriter w m) => MonadWriter w (StateT g m) where
tell = lift . tell
listen = mapStateT $ \ma -> do
((a,s'), w) <- listen ma
return ((a,w), s')
pass = mapStateT $ \ma -> pass $ do
((a, f), s') <- ma
return ((a, s'), f)
instance (Representable g, MonadCont m) => MonadCont (StateT g m) where
callCC = liftCallCC' callCC
instance (Functor f, Representable g, MonadFree f m) => MonadFree f (StateT g m) where
wrap as = stateT $ \s -> wrap (fmap (`runStateT` s) as)
leftAdjunctRep :: Representable u => ((a, Key u) -> b) -> a -> u b
leftAdjunctRep f a = tabulate (\s -> f (a,s))
rightAdjunctRep :: Indexable u => (a -> u b) -> (a, Key u) -> b
rightAdjunctRep f ~(a, k) = f a `index` k
liftCallCC :: Representable g => ((((a,Key g) -> m (b,Key g)) -> m (a,Key g)) -> m (a,Key g)) ->
((a -> StateT g m b) -> StateT g m a) -> StateT g m a
liftCallCC callCC' f = stateT $ \s ->
callCC' $ \c ->
runStateT (f (\a -> StateT $ pureRep $ c (a, s))) s
liftCallCC' :: Representable g => ((((a,Key g) -> m (b,Key g)) -> m (a,Key g)) -> m (a,Key g)) ->
((a -> StateT g m b) -> StateT g m a) -> StateT g m a
liftCallCC' callCC' f = stateT $ \s ->
callCC' $ \c ->
runStateT (f (\a -> stateT $ \s' -> c (a, s'))) s