All Downloads are FREE. Search and download functionalities are using the official Maven repository.

arrow.data.State.kt Maven / Gradle / Ivy

There is a newer version: 0.8.2
Show newest version
package arrow.data

import arrow.core.*
import arrow.typeclasses.applicative
import arrow.typeclasses.monad

/**
 * Alias that represents stateful computation of the form `(S) -> Tuple2`.
 */
typealias StateFun = StateTFun

/**
 * Alias that represents wrapped stateful computation in context `Id`.
 */
typealias StateFunKind = StateTFunKind

/**
 * Alias for StateHK
 */
typealias StateHK = StateTHK

/**
 * Alias for StateKind
 */
typealias StateKind = StateTKind

/**
 * Alias to partially apply type parameters [S] to [State]
 */
typealias StateKindPartial = StateTKindPartial

/**
 * `State` is a stateful computation that yields a value of type `A`.
 *
 * @param S the state we are preforming computation upon.
 * @param A current value of computation.
 */
typealias State = StateT

/**
 * Constructor for State.
 * State is an alias for IndexedStateT
 *
 * @param run the stateful function to wrap with [State].
 */
@Suppress("FunctionName")
fun  State(run: (S) -> Tuple2): State = StateT(Id(run.andThen { Id(it) }))

/**
 * Syntax for constructing a `StateT` from a function `(S) -> Tuple2`
 */
fun  StateFun.toState(): State = State(this)

/**
 * Syntax for constructing a `StateT` from a function `(S) -> Tuple2`
 */
fun  StateFunKind.toState(): State = State(this)

fun  State.map(sx: State, f: (T, P1) -> R): State =
        flatMap ({ t -> sx.map { x -> f(t, x) } }, monad()).ev()

fun  State.map(f: (T) -> R): State = flatMap({ t -> StateApi.pure(f(t)) }, monad()).ev()

/**
 * Alias for [StateT.run] `StateT`
 *
 * @param initial state to start stateful computation.
 */
fun  StateT.run(initial: S): Tuple2 = run(initial, monad()).value()

/**
 * Alias for [StateT.runA] `StateT`
 *
 * @param initial state to start stateful computation.
 */
fun  StateT.runA(initial: S): A = run(initial).b

/**
 * Alias for [StateT.runS] `StateT`
 *
 * @param initial state to start stateful computation.
 */
fun  StateT.runS(initial: S): S = run(initial).a

/**
 * Alias for StateId to make working with `StateT` more elegant.
 */
@Suppress("FunctionName")
fun State() = StateApi

object StateApi {

    fun  pure(t: T): State = StateT.pure(t, monad())

    /**
     * Return input without modifying it.
     */
    fun  get(): State = StateT.get(applicative())

    /**
     * Inspect a value of the state [S] with [f] `(S) -> T` without modifying the state.
     *
     * @param f the function applied to inspect [T] from [S].
     */
    fun  inspect(f: (S) -> T): State = StateT.inspect(applicative(), f)

    /**
     * Modify the state with [f] `(S) -> S` and return [Unit].
     *
     * @param f the modify function to apply.
     */
    fun  modify(f: (S) -> S): State = StateT.modify(applicative(), f)

    /**
     * Set the state to [s] and return [Unit].
     *
     * @param s value to set.
     */
    fun  set(s: S): State = StateT.set(applicative(), s)

}