{-# LANGUAGE DeriveFunctor, FlexibleContexts, FlexibleInstances, KindSignatures, LambdaCase, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}
module Control.Effect.State
( State(..)
, get
, gets
, put
, modify
, runState
, evalState
, execState
, StateC(..)
) where
import Control.Effect.Carrier
import Control.Effect.Sum
import Control.Effect.Internal
import Data.Coerce
data State s (m :: * -> *) k
= Get (s -> k)
| Put s k
deriving (Functor)
instance HFunctor (State s) where
hmap _ = coerce
{-# INLINE hmap #-}
instance Effect (State s) where
handle state handler (Get k) = Get (handler . (<$ state) . k)
handle state handler (Put s k) = Put s (handler . (<$ state) $ k)
get :: (Member (State s) sig, Carrier sig m) => m s
get = send (Get ret)
gets :: (Member (State s) sig, Carrier sig m, Functor m) => (s -> a) -> m a
gets f = fmap f get
put :: (Member (State s) sig, Carrier sig m) => s -> m ()
put s = send (Put s (ret ()))
modify :: (Member (State s) sig, Carrier sig m, Monad m) => (s -> s) -> m ()
modify f = do
a <- get
put $! f a
runState :: (Carrier sig m, Effect sig) => s -> Eff (StateC s m) a -> m (s, a)
runState s m = runStateC (interpret m) s
evalState :: (Carrier sig m, Effect sig, Functor m) => s -> Eff (StateC s m) a -> m a
evalState s m = fmap snd (runStateC (interpret m) s)
execState :: (Carrier sig m, Effect sig, Functor m) => s -> Eff (StateC s m) a -> m s
execState s m = fmap fst (runStateC (interpret m) s)
newtype StateC s m a = StateC { runStateC :: s -> m (s, a) }
instance (Carrier sig m, Effect sig) => Carrier (State s :+: sig) (StateC s m) where
ret a = StateC (\ s -> ret (s, a))
eff op = StateC (\ s -> handleSum (eff . handleState s runStateC) (\case
Get k -> runStateC (k s) s
Put s k -> runStateC k s) op)