//! The state monad transformer.
let { Alternative, or, empty } = import! std.alternative
let { Applicative, wrap, (<*>) } = import! std.applicative
let { (>>), (<<), ? } = import! std.function
let { Functor, map } = import! std.functor
let { Monad, (>>=) } = import! std.monad
let { Transformer } = import! std.transformer
type StateOut s a = { value : a, state : s }
type WrStateOut s m a = m { value : a, state : s }
type StateT s m a = s -> m { value : a, state : s }
let map_sout f st : (a -> b) -> StateOut s a -> StateOut s b =
{value = f st.value, state = st.state}
let functor : [Functor m] -> Functor (StateT s m) =
let stmap f sr : (a -> b) -> StateT s m a -> StateT s m b =
map (map_sout f) << sr
{ map = stmap }
// the typechecker can't find map and Functor m without help
let applicative ?mo : [Monad m] -> Applicative (StateT s m) =
let apply srf sr : StateT s m (a -> b) -> StateT s m a -> StateT s m b = \state ->
srf state >>= \fout ->
let {value = f, state = state'} = fout
mo.applicative.functor.map (map_sout f) (sr state')
let stwrap value : a -> StateT s m a = \state ->
wrap { value, state }
{ functor = functor ?mo.applicative.functor, apply, wrap = stwrap }
let monad : [Monad m] -> Monad (StateT s m) =
let flat_map f sr : (a -> StateT s m b) -> StateT s m a -> StateT s m b = \state ->
sr state >>= \sout ->
let {value, state = state'} = sout
f value state'
{ applicative, flat_map }
let transformer : Transformer (StateT s) =
let wrap_monad ma : [Monad m] -> m a -> StateT s m a = \state ->
ma >>= \value -> wrap {value, state}
{ /* monad, */ wrap_monad }
let alternative : [Monad m] -> [Alternative m] -> Alternative (StateT s m) =
let stempty = transformer.wrap_monad empty
let stor sra srb = or << sra <*> srb
{ applicative, empty = stempty, or = stor }
let put value : [Monad m] -> s -> StateT s m () = \state ->
wrap { value = (), state = value }
let get : [Monad m] -> StateT s m s = \state ->
wrap { value = state, state }
let gets f : [Monad m] -> (s -> a) -> StateT s m a =
get >>= (wrap << f)
let modify f : [Monad m] -> (s -> s) -> StateT s m () =
get >>= (put << f)
let run_state_t f state : StateT s m a -> s -> m { value : a, state : s } =
f state
let eval_state_t f state : [Functor m] -> StateT s m a -> s -> m a =
map (\x -> x.value) (run_state_t f state)
let exec_state_t f state : [Functor m] -> StateT s m a -> s -> m s =
map (\x -> x.state) (run_state_t f state)
{
StateT,
applicative,
functor,
monad,
transformer,
alternative,
put,
get,
gets,
modify,
run_state_t,
eval_state_t,
exec_state_t
}