// m04 state (optional, Exercise 4.7): the general pattern behind Random. A State is a function // s => [A, nextS]: it reads a state, produces a value and hands on a new state. Random is State. // Nothing in the game uses this file; it is here to show that Random was one example of a bigger idea. /** @import { State } from './types' */ /** A State that gives `a` and leaves the state untouched. * @type {(a: A) => State} */ export const pure = (a) => (s) => [a, s] /** Transform the value a State produces; the state threading is unchanged. * @type {(st: State, f: (a: A) => B) => State} */ export const map = (st, f) => (s) => { const [a, next] = st(s) return [f(a), next] } /** Run `st`, let `f` pick the next State from its value, and run that with the state `st` left behind. * @type {(st: State, f: (a: A) => State) => State} */ export const flatMap = (st, f) => (s) => { const [a, next] = st(s) return f(a)(next) } /** A State whose value is the current state, which it leaves untouched. * @type {(s: S) => [S, S]} */ export const get = (s) => [s, s] /** A State that replaces the state with `s` and gives `undefined` (there is no interesting value). * @type {(s: S) => State} */ export const put = (s) => () => [undefined, s] /** A State that replaces the state `s` with `f(s)` and gives `undefined`. * @type {(f: (s: S) => S) => State} */ export const modify = (f) => (s) => [undefined, f(s)] /** Run a State from an initial state: `[value, finalState]`. * @type {(st: State, s: S) => [A, S]} */ export const run = (st, s) => st(s)