State

class State[S,T]( init : (S -> [S,T]) )
: MonadMapApply[T]
{
bind[A] : (T -> State[S,A]) -> State[S,A] = f -> State[S,A]( s -> init(s) | (s,t) -> f(t).init(s) )
map [A] : ([S,T] -> [S,A]) -> State[S,A] = f -> State[S,A]( s -> f(init(s)) )

Applicative.lift = t -> State[S,T]( s -> (s,t) )
}

Synopsis

State.map, apply, and bind enable the composition of the functions (containing the implied morphism : T -> A) which do and do not operate on state of type S.

Rationale

Makes the computation of state orthogonal to the state transitions of unlifted functions. Thus generally any kinds of orthogonal state can composed with any category of morphisms, without case-specific boilerplate.

The State (a Monad) eliminates the boilerplate of threading some state across functions that don't access that state so as to compose these with functions that do access that state. This allows reuse of functions without having to code separate functions for each permutation of state that one might one to compose with. The State monad is roughly analogous to a threadable scope for global variables, i.e. that state is encapsulated, so that state is only accessible to functions in the composition, and thus the functions are pure w.r.t. that state. Thus the state effects are transparent (the functions operate on that state via inputs and return value only), delimited, and composable.

Examples

See the Examples for Traversable.

Details

State.lift : T -> State[S,T] is an example of a more general function of type : T -> State[S,A], which is internally a combination of operations of types : S -> S and : T -> A.

In State.lift, these are both identity operations s -> s and t -> t, which are combined to construct a 2-tuple (s,t) of type [S,T].

There are examples with non-identity operations in the documentation for Traversable.

The general function inputs an instance of type T and outputs an instance of type State[S,A]. The output of type State[S,A], contains the constructor parameter field init which is set to a function that inputs an initial state of type S, and outputs the 2-tuple of type [S,A], which is a combination of the operations of types : S -> S and : T -> A. The function instance stored in init is called when it is desired to evaluate any state computations (that are stored in nested closures and to) return the 2-tuple.

The : S -> S operation can modify the instance of state type S, or output it unmodified.

The : T -> A operation can output a new instance of type A, or it can output the input type T (i.e. A can be a T).

State.bind : State[S,T] (T -> State[S,A]) -> State[S,A] composes the instance of this of type State[S,T], with a function of the general model. The following are then derived from State.bind: Functor.map, Applicative.apply, Monad.join, and Monad.compose.

Theory

See Theory for Event, which addresses many issues about the nature of programming with state transitions.