gluon 0.13.1

A static, type inferred programming language for application embedding
Documentation
//! 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
}