module Theseus.Effect.State where
import Theseus.Effmodule Theseus.Effect.State where
import Theseus.EffState is a good example of a first order effect that changes the type of its output. It wraps the output in the final state.
Keeps track of some mutable value. Interpreters should follow the “Lens
Laws”. This means you Get back what you Put, Putting back what you
Get does nothing, and Putting twice is the same as Putting once.
data State s m a where
Get :: State s m s
Put :: s -> State s m ()Retrieve the mutable value
get :: State s :> es => Eff lb ub es s
get = send Get A convience function equivalent to fmap f get
gets :: State s :> es => (s -> a) -> Eff lb ub es a
gets f = fmap f getSets the mutable state
put :: State s :> es => s -> Eff lb ub es ()
put s = send $ Put sUses a function to change the mutable state
modify :: State s :> es => (s -> s) -> Eff lb ub es ()
modify f = get >>= put . f
type StateResult s = ((,) s)Runs a state effect following the Lens Laws
runState :: lb (StateResult s) => s -> Eff lb ub (State s : es) a -> Eff lb ub es (s, a)
runState s =This is an interpreter which changes the output. Instead of simply
returning a, it returns a and the final value of the state.
interpretW_ (\a -> pure (s, a)) \caseWrapping interpreters need to provide the value to continue with alongside an interpretation for the next instance of this effect. This gives us a natural way of keeping track of state.
Get -> (pure s, runState s)
Put s' -> (pure (), runState s') Runs a state using runState returning only the final state.
execState :: lb (StateResult s) => s -> Eff lb ub (State s : es) a -> Eff lb ub es s
execState s eff = fst <$> runState s eff Runs a state using runState ignoring the final state.
evalState :: lb (StateResult s) => s -> Eff lb ub (State s : es) a -> Eff lb ub es a
evalState s eff = snd <$> runState s eff Keeps track of local state changes and only commits them to the outer
state if control flow continues successfully. Something like a throw or an
empty would not commit the transaction.
transactionally :: (State s :> es, lb (StateResult s)) => Eff lb ub (State s : es) a -> Eff lb ub es a
transactionally action = do
initial <- get
(newS, a) <- runState initial action
put newS
pure a