state monad

final class pythonic_fp.fptools.state.State

Bases: Generic

State monad

A pure FP implementation of the State Monad, a data structure generating values while propagating changes of state.

Note

A monad is a value in a context. The State monad wraps neither a state nor a (value, state) pair.

It wraps a transformation old_state -> (value, new_state) called a “state action”.

Class State

Instance members:

  • Property run is the state action

  • Method bind performs state action composition

  • Method eval performs the run action

    • the run action evaluates the state action by

      • supplying an initial state

      • returning the resulting value

Static members:

  • Method unit creates a State instance whose run action returns the supplied constant value.

  • Method get creates a State instance whose run action returns the current state.

  • Method set creates a State which ignores the old state and swaps in a new one.

  • Method modify creates a State instance which modifies the previous state via a function.

  • Method sequence combine a list of State instances into a State whose run action returns the list of generated values.

__init__(run: Callable[[S], tuple[A, S]]) None

init

param run:

State action.

type run:

S -> (A, S) where A is the type of the generated value and S is the type of a state.

bind(g: Callable[[A], State[S, B]]) State[S, B]

state action composition

param g:

A function that produces a State[S, B] from an A.

returns:

A State[S, B] whose state action is the composition of the state actions from self followed by the one produced by g.

eval(init: S) A

run action

Evaluate the state action by passing in an initial state and returning the produced value.

param init:

An initial state to pass into the state action.

returns:

The value produced by the run action.

map(f: Callable[[A], B]) State[S, B]

map

Map function f over the resulting value of a state action propagating the current state.

param f:

Function to map.

returns:

A new State instance whose run action produces f(a) where a is the value produced by the current State instance and just propagates the current state.

map2(sb: State[S, B], f: Callable[[A, B], C]) State[S, C]

map2

Combine two state monads, self and sb, with a function. Resulting run action just propagates the current state.

param sb:

State instance to combine with the current instance.

param f:

Function used by the resulting run action on the values produced by the run actions of the current State instance and sb using the same initial state.

both(rb: State[S, B]) State[S, tuple[A, B]]

both

Return a State instance whose run action returns a tuple from from the run actions of the current State and sb.

param sb:

A State instance to be combined with the current one.

static unit(b: B) State

unit

Create a State whose run action returns the given constant b and propagate the present state.

param b:

Value the new State’s run action will return.

returns:

A new State[ST, B] from a value b: B.

static get() State

get state

Set run action to return the current state and propagate it unchanged.

  • the current state is propagated unchanged

  • current value now set to current state

  • will need type annotation

returns:

A state monad wrapping a state action to return the current state. Propagates the current state unchanged.

static put(s: ST) State[ST, tuple[()]]

put state

Manually insert a new state.

  • ignores previous state and swaps in a new state

  • resulting run action will return an empty tuple

    • the traditional canonically meaningless value in FP

param s:

The state to swap in for current state

returns:

State monad wrapping a state action which ignores any initial state passed in when evaluated.

rtype:

State[ST, tuple[()]]

static modify(f: Callable[[ST], ST]) State[ST, tuple[()]]

modify

Modify previous state with a function. Like put, but modify previous state via f.

param f:

Function to modify the current state.

returns:

A State monad with a modified state.

rtype:

State[ST, tuple[()]]

Note

Will need type annotation. Static type checkers like mypy have no a priori knowledge of what ST could be.

static sequence(sas: list[State]) State[ST, list[AA]]

sequence a list

Combine a list of state monads into a state monad whose run action returns a list of the values returned by each run action from the original list.

param sas:

A list of state monads all of type State[ST, AA].

returns:

A state monad whose run action produces a list of the values produced by the list of State actions provided to the method.

rtype:

State[ST, list[AA]]

Note

The run action evaluates the run actions of the list front to back. The state is also propagated, not necessarily unchanged, front to back.