Documentation
¶
Index ¶
- func Applicative[S, A, B any]() applicative.Applicative[A, B, State[S, A], State[S, B], State[S, func(A) B]]
- func Eq[S, A any](w eq.Eq[S], a eq.Eq[A]) func(S) eq.Eq[State[S, A]]
- func Evaluate[A, S any](s S) func(State[S, A]) A
- func Execute[A, S any](s S) func(State[S, A]) S
- func FromStrictEquals[S, A comparable]() func(S) eq.Eq[State[S, A]]
- func Functor[S, A, B any]() functor.Functor[A, B, State[S, A], State[S, B]]
- func Monad[S, A, B any]() monad.Monad[A, B, State[S, A], State[S, B], State[S, func(A) B]]
- func Pointed[S, A any]() pointed.Pointed[A, State[S, A]]
- type Endomorphism
- func ApSL[ST, S, T any](lens Lens[S, T], fa State[ST, T]) Endomorphism[State[ST, S]]
- func BindL[ST, S, T any](lens Lens[S, T], f Kleisli[ST, T, T]) Endomorphism[State[ST, S]]
- func LetL[ST, S, T any](lens Lens[S, T], f Endomorphism[T]) Endomorphism[State[ST, S]]
- func LetToL[ST, S, T any](lens Lens[S, T], b T) Endomorphism[State[ST, S]]
- type Kleisli
- type Lens
- type Operator
- func Ap[B, S, A any](ga State[S, A]) Operator[S, func(A) B, B]
- func ApS[ST, S1, S2, T any](setter func(T) func(S1) S2, fa State[ST, T]) Operator[ST, S1, S2]
- func Bind[ST, S1, S2, T any](setter func(T) func(S1) S2, f Kleisli[ST, S1, T]) Operator[ST, S1, S2]
- func BindTo[ST, S1, T any](setter func(T) S1) Operator[ST, T, S1]
- func Chain[S any, FCT ~func(A) State[S, B], A, B any](f FCT) Operator[S, A, B]
- func ChainFirst[S any, FCT ~func(A) State[S, B], A, B any](f FCT) Operator[S, A, A]
- func Flap[S, A, B any](a A) Operator[S, func(A) B, B]
- func Let[ST, S1, S2, T any](key func(T) func(S1) S2, f func(S1) T) Operator[ST, S1, S2]
- func LetTo[ST, S1, S2, T any](key func(T) func(S1) S2, b T) Operator[ST, S1, S2]
- func Map[S any, FCT ~func(A) B, A, B any](f FCT) Operator[S, A, B]
- type Pair
- type Reader
- type State
- func Do[ST, A any](empty A) State[ST, A]
- func Flatten[S, A any](mma State[S, State[S, A]]) State[S, A]
- func Get[S any]() State[S, S]
- func Gets[FCT ~func(S) A, A, S any](f FCT) State[S, A]
- func Modify[FCT ~func(S) S, S any](f FCT) State[S, Void]
- func MonadAp[B, S, A any](fab State[S, func(A) B], fa State[S, A]) State[S, B]
- func MonadChain[S any, FCT ~func(A) State[S, B], A, B any](fa State[S, A], f FCT) State[S, B]
- func MonadChainFirst[S any, FCT ~func(A) State[S, B], A, B any](ma State[S, A], f FCT) State[S, A]
- func MonadFlap[FAB ~func(A) B, S, A, B any](fab State[S, FAB], a A) State[S, B]
- func MonadMap[S any, FCT ~func(A) B, A, B any](fa State[S, A], f FCT) State[S, B]
- func Of[S, A any](a A) State[S, A]
- func Put[S any]() State[S, Void]
- type Void
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Applicative ¶
func Applicative[S, A, B any]() applicative.Applicative[A, B, State[S, A], State[S, B], State[S, func(A) B]]
Applicative implements the applicative operations for State
func Evaluate ¶
func Evaluate[A, S any](s S) func(State[S, A]) A
Evaluate runs a State computation with the given initial state and returns only the computed value, discarding the final state. This is useful when you only care about the result of the computation.
Example:
type Counter struct { count int }
computation := Of[Counter](42)
value := Evaluate[int, Counter](Counter{count: 5})(computation)
// value = 42
func Execute ¶
func Execute[A, S any](s S) func(State[S, A]) S
Execute runs a State computation with the given initial state and returns only the final state, discarding the computed value. This is useful when you only care about the state transformations.
Example:
type Counter struct { count int }
computation := Modify(func(c Counter) Counter { return Counter{count: c.count + 1} })
finalState := Execute[Void, Counter](Counter{count: 5})(computation)
// finalState = Counter{count: 6}
func FromStrictEquals ¶
func FromStrictEquals[S, A comparable]() func(S) eq.Eq[State[S, A]]
FromStrictEquals constructs an eq.Eq from the canonical comparison function
Types ¶
type Endomorphism ¶
type Endomorphism[A any] = endomorphism.Endomorphism[A]
Endomorphism represents a function from a type to itself (A -> A). It's an alias for endomorphism.Endomorphism[A] and is commonly used for state transformations and updates.
func ApSL ¶
func ApSL[ST, S, T any]( lens Lens[S, T], fa State[ST, T], ) Endomorphism[State[ST, S]]
ApSL is a lens-based version of ApS that uses a lens to focus on a specific field in the accumulator structure. This provides a more convenient and type-safe way to update nested fields.
A lens provides both a getter and setter for a field, making it easier to work with complex data structures without manually writing setter functions.
Parameters:
- lens: A lens focusing on field T within structure S
- fa: A State computation that produces a value of type T
Example:
type MyState struct {
counter int
}
type Accumulator struct {
value int
doubled int
}
// Create a lens for the 'doubled' field
doubledLens := MakeLens(
func(acc Accumulator) int { return acc.doubled },
func(d int) func(Accumulator) Accumulator {
return func(acc Accumulator) Accumulator {
acc.doubled = d
return acc
}
},
)
computation := ApSL(doubledLens, Of[MyState](42))
func BindL ¶
func BindL[ST, S, T any]( lens Lens[S, T], f Kleisli[ST, T, T], ) Endomorphism[State[ST, S]]
BindL is a lens-based version of Bind that focuses on a specific field, extracts its value, applies a stateful computation, and updates the field with the result. This is particularly useful for updating nested fields based on their current values.
The computation receives the current value of the focused field and produces a new value through a State computation.
Parameters:
- lens: A lens focusing on field T within structure S
- f: A Kleisli arrow that takes the current field value and produces a State computation yielding the new value
Example:
type MyState struct {
multiplier int
}
type Accumulator struct {
value int
}
valueLens := MakeLens(
func(acc Accumulator) int { return acc.value },
func(v int) func(Accumulator) Accumulator {
return func(acc Accumulator) Accumulator {
acc.value = v
return acc
}
},
)
// Double the value using state
computation := BindL(
valueLens,
func(v int) State[MyState, int] {
return Gets(func(s MyState) int {
return v * s.multiplier
})
},
)
func LetL ¶
func LetL[ST, S, T any]( lens Lens[S, T], f Endomorphism[T], ) Endomorphism[State[ST, S]]
LetL is a lens-based version of Let that focuses on a specific field, extracts its value, applies a pure transformation, and updates the field with the result. This is useful for pure transformations of nested fields.
Unlike BindL, this doesn't perform stateful computations - it only applies a pure function to the field value.
Parameters:
- lens: A lens focusing on field T within structure S
- f: An endomorphism (pure function from T to T) that transforms the field value
Example:
type Accumulator struct {
counter int
message string
}
counterLens := MakeLens(
func(acc Accumulator) int { return acc.counter },
func(c int) func(Accumulator) Accumulator {
return func(acc Accumulator) Accumulator {
acc.counter = c
return acc
}
},
)
// Increment the counter
computation := LetL(
counterLens,
func(c int) int { return c + 1 },
)
func LetToL ¶
func LetToL[ST, S, T any]( lens Lens[S, T], b T, ) Endomorphism[State[ST, S]]
LetToL is a lens-based version of LetTo that sets a specific field to a constant value. This provides a convenient way to update nested fields with known values.
Parameters:
- lens: A lens focusing on field T within structure S
- b: The constant value to set
Example:
type Accumulator struct {
status string
value int
}
statusLens := MakeLens(
func(acc Accumulator) string { return acc.status },
func(s string) func(Accumulator) Accumulator {
return func(acc Accumulator) Accumulator {
acc.status = s
return acc
}
},
)
// Set status to "completed"
computation := LetToL(statusLens, "completed")
type Kleisli ¶
Kleisli represents a Kleisli arrow for the State monad. It's a function from A to State[S, B], which allows composition of stateful computations. This is the fundamental building block for chaining operations that both depend on and modify state.
type Lens ¶
Lens represents a functional reference to a part of a data structure. It's an alias for lens.Lens[S, A] where S is the whole structure and A is the part. Lenses provide composable getters and setters for immutable data structures.
type Operator ¶
Operator is a specialized Kleisli arrow that operates on State values. It transforms a State[S, A] into a State[S, B], making it useful for building pipelines of stateful transformations while maintaining the state type S.
func Ap ¶
func Ap[B, S, A any](ga State[S, A]) Operator[S, func(A) B, B]
Ap returns a function that applies a State computation containing a function to a State computation containing a value. This is the curried version of MonadAp.
Example:
type Counter struct { count int }
computation := function.Pipe1(
Of[Counter](func(x int) int { return x * 2 }),
Ap[int](Of[Counter](21)),
)
result := computation(Counter{count: 5})
// result = Pair{head: Counter{count: 5}, tail: 42}
func ApS ¶
func ApS[ST, S1, S2, T any]( setter func(T) func(S1) S2, fa State[ST, T], ) Operator[ST, S1, S2]
ApS applies a State computation in an applicative style and binds the result to a field in the accumulator. Unlike Bind, which uses monadic sequencing, ApS uses applicative composition, which can be more efficient when the computation doesn't depend on the accumulator value.
This is useful when you have independent State computations that can be composed without depending on each other's results.
Parameters:
- setter: A function that takes the computed value T and returns a function to update the accumulator from S1 to S2
- fa: A State computation that produces a value of type T
Example:
type Accumulator struct {
counter int
timestamp int64
}
// Apply an independent state computation
getTimestamp := Gets(func(s MyState) int64 { return s.timestamp })
computation := ApS(
func(ts int64) func(Accumulator) Accumulator {
return func(acc Accumulator) Accumulator {
acc.timestamp = ts
return acc
}
},
getTimestamp,
)
func Bind ¶
func Bind[ST, S1, S2, T any]( setter func(T) func(S1) S2, f Kleisli[ST, S1, T], ) Operator[ST, S1, S2]
Bind sequences a stateful computation and binds its result to a field in an accumulator structure. This is a key building block for do-notation, allowing you to extract values from State computations and incorporate them into a growing result structure.
The setter function takes the computed value T and returns a function that updates the accumulator from S1 to S2 by setting the field to T.
Parameters:
- setter: A function that takes a value T and returns a function to update the accumulator structure from S1 to S2
- f: A Kleisli arrow that takes the current accumulator S1 and produces a State computation yielding T
Example:
type Accumulator struct {
value int
doubled int
}
// Bind the result of a computation to the 'doubled' field
computation := Bind(
func(d int) func(Accumulator) Accumulator {
return func(acc Accumulator) Accumulator {
acc.doubled = d
return acc
}
},
func(acc Accumulator) State[MyState, int] {
return Of[MyState](acc.value * 2)
},
)
func BindTo ¶
func BindTo[ST, S1, T any]( setter func(T) S1, ) Operator[ST, T, S1]
BindTo creates an initial accumulator structure from a value. This is typically the first operation in a do-notation pipeline, converting a simple value into a structure that can accumulate additional fields.
Parameters:
- setter: A function that takes a value T and creates an accumulator structure S1
Example:
type Accumulator struct {
initial int
doubled int
}
// Start a pipeline by binding the initial value
computation := function.Pipe2(
Of[MyState](42),
BindTo(func(x int) Accumulator {
return Accumulator{initial: x}
}),
Bind(func(d int) func(Accumulator) Accumulator {
return func(acc Accumulator) Accumulator {
acc.doubled = d
return acc
}
}, func(acc Accumulator) State[MyState, int] {
return Of[MyState](acc.initial * 2)
}),
)
func Chain ¶
Chain returns a function that sequences State computations. This is the curried version of MonadChain, useful for composition and pipelines.
Example:
type Counter struct { count int }
addToCounter := func(x int) State[Counter, int] {
return func(s Counter) Pair[Counter, int] {
newState := Counter{count: s.count + x}
return pair.MakePair(newState, newState.count)
}
}
computation := function.Pipe1(Of[Counter](5), Chain(addToCounter))
result := computation(Counter{count: 10})
// result = Pair{head: Counter{count: 15}, tail: 15}
func ChainFirst ¶
ChainFirst returns a function that sequences State computations but keeps the first value. This is the curried version of MonadChainFirst, useful for composition and pipelines.
Example:
type Counter struct { count int }
increment := func(x int) State[Counter, Void] {
return Modify(func(c Counter) Counter { return Counter{count: c.count + 1} })
}
computation := function.Pipe1(Of[Counter](42), ChainFirst(increment))
result := computation(Counter{count: 5})
// result = Pair{head: Counter{count: 6}, tail: 42}
func Flap ¶
func Flap[S, A, B any](a A) Operator[S, func(A) B, B]
Flap returns a function that applies a fixed value to a State computation containing a function. This is the curried version of MonadFlap.
Example:
type Counter struct { count int }
applyTwentyOne := Flap[Counter, int, int](21)
computation := function.Pipe1(
Of[Counter](func(x int) int { return x * 2 }),
applyTwentyOne,
)
result := computation(Counter{count: 5})
// result = Pair{head: Counter{count: 5}, tail: 42}
func Let ¶
func Let[ST, S1, S2, T any]( key func(T) func(S1) S2, f func(S1) T, ) Operator[ST, S1, S2]
Let computes a pure value from the current accumulator and binds it to a field. Unlike Bind, this doesn't execute a stateful computation - it simply applies a pure function to the accumulator and stores the result.
This is useful in do-notation when you need to compute derived values without performing stateful operations.
Parameters:
- key: A function that takes the computed value T and returns a function to update the accumulator from S1 to S2
- f: A pure function that extracts or computes T from the current accumulator S1
Example:
type Accumulator struct {
x int
y int
sum int
}
// Compute sum from x and y without state operations
computation := Let(
func(s int) func(Accumulator) Accumulator {
return func(acc Accumulator) Accumulator {
acc.sum = s
return acc
}
},
func(acc Accumulator) int {
return acc.x + acc.y
},
)
func LetTo ¶
func LetTo[ST, S1, S2, T any]( key func(T) func(S1) S2, b T, ) Operator[ST, S1, S2]
LetTo binds a constant value to a field in the accumulator. This is a specialized version of Let where the value is already known and doesn't need to be computed from the accumulator.
This is useful for initializing fields with constant values or for setting default values in do-notation pipelines.
Parameters:
- key: A function that takes the constant value T and returns a function to update the accumulator from S1 to S2
- b: The constant value to bind
Example:
type Accumulator struct {
status string
value int
}
// Set a constant status
computation := LetTo(
func(s string) func(Accumulator) Accumulator {
return func(acc Accumulator) Accumulator {
acc.status = s
return acc
}
},
"initialized",
)
func Map ¶
Map returns a function that transforms the value of a State computation. This is the curried version of MonadMap, useful for composition and pipelines.
Example:
type Counter struct { count int }
double := Map[Counter](func(x int) int { return x * 2 })
computation := function.Pipe1(Of[Counter](10), double)
result := computation(Counter{count: 5})
// result = Pair{head: Counter{count: 5}, tail: 20}
type Pair ¶
Pair represents a tuple of two values of types L and R. It's an alias for pair.Pair[L, R] where L is the head (left) and R is the tail (right).
type Reader ¶
Reader represents a computation that depends on an environment of type R and produces a value of type A. It's an alias for reader.Reader[R, A] and is used for dependency injection patterns.
type State ¶
State represents a stateful computation that takes an initial state of type S, performs some operation, and returns both a new state and a value of type A. It's defined as Reader[S, Pair[S, A]], meaning it's a function that: 1. Takes an initial state S as input 2. Returns a Pair where the head is the new state S and the tail is the computed value A The new state is in the head position and the value in the tail position because the pair monad operates on the tail, allowing monadic operations to transform the computed value while threading the state through the computation.
func Do ¶
func Do[ST, A any]( empty A, ) State[ST, A]
Do initializes a do-notation computation with an empty value. This is the entry point for building complex stateful computations using the do-notation pattern, which allows for imperative-style sequencing of monadic operations.
The do-notation pattern is useful for building pipelines where you need to:
- Bind intermediate results to names
- Sequence multiple stateful operations
- Build up complex state transformations step by step
Example:
type MyState struct {
x int
y int
}
type Result struct {
sum int
product int
}
computation := function.Pipe3(
Do[MyState](Result{}),
Bind(func(r Result) func(int) Result {
return func(x int) Result { r.sum = x; return r }
}, Gets(func(s MyState) int { return s.x })),
Bind(func(r Result) func(int) Result {
return func(y int) Result { r.product = r.sum * y; return r }
}, Gets(func(s MyState) int { return s.y })),
Map[MyState](func(r Result) int { return r.product }),
)
func Flatten ¶
func Flatten[S, A any](mma State[S, State[S, A]]) State[S, A]
Flatten removes one level of nesting from a State computation that produces another State computation. This is equivalent to MonadChain with the identity function.
Example:
type Counter struct { count int }
nested := Of[Counter](Of[Counter](42))
flattened := Flatten(nested)
result := flattened(Counter{count: 5})
// result = Pair{head: Counter{count: 5}, tail: 42}
func Get ¶
func Get[S any]() State[S, S]
Get returns a State computation that retrieves the current state and returns it as the value. The state is unchanged by this operation.
Example:
type Counter struct { count int }
getState := Get[Counter]()
result := getState(Counter{count: 5})
// result = Pair{head: Counter{count: 5}, tail: Counter{count: 5}}
func Gets ¶
func Gets[FCT ~func(S) A, A, S any](f FCT) State[S, A]
Gets applies a function to the current state and returns the result as the value. The state itself remains unchanged. This is useful for extracting or computing values from the state without modifying it.
Example:
type Counter struct { count int }
getDouble := Gets(func(c Counter) int { return c.count * 2 })
result := getDouble(Counter{count: 5})
// result = Pair{head: Counter{count: 5}, tail: 10}
func Modify ¶
func Modify[FCT ~func(S) S, S any](f FCT) State[S, Void]
Modify applies a transformation function to the current state, producing a new state. The returned value is Void, indicating this operation is performed for its side effect.
Example:
type Counter struct { count int }
increment := Modify(func(c Counter) Counter { return Counter{count: c.count + 1} })
result := increment(Counter{count: 5})
// result = Pair{head: Counter{count: 6}, tail: Void}
func MonadAp ¶
func MonadAp[B, S, A any](fab State[S, func(A) B], fa State[S, A]) State[S, B]
MonadAp applies a State computation containing a function to a State computation containing a value. Both computations are executed sequentially, threading the state through both. This is the Applicative interface implementation for State.
Example:
type Counter struct { count int }
fab := Of[Counter](func(x int) int { return x * 2 })
fa := Of[Counter](21)
result := MonadAp(fab, fa)(Counter{count: 5})
// result = Pair{head: Counter{count: 5}, tail: 42}
func MonadChain ¶
MonadChain sequences two State computations, where the second computation depends on the value produced by the first. The state is threaded through both computations. This is the Monad interface implementation for State.
Example:
type Counter struct { count int }
computation := Of[Counter](5)
chained := MonadChain(computation, func(x int) State[Counter, int] {
return func(s Counter) Pair[Counter, int] {
newState := Counter{count: s.count + x}
return pair.MakePair(newState, x * 2)
}
})
result := chained(Counter{count: 10})
// result = Pair{head: Counter{count: 15}, tail: 10}
func MonadChainFirst ¶
MonadChainFirst sequences two State computations but returns the value from the first computation while still threading the state through both. This is useful when you want to perform a stateful side effect but keep the original value.
Example:
type Counter struct { count int }
computation := Of[Counter](42)
increment := func(x int) State[Counter, Void] {
return Modify(func(c Counter) Counter { return Counter{count: c.count + 1} })
}
result := MonadChainFirst(computation, increment)(Counter{count: 5})
// result = Pair{head: Counter{count: 6}, tail: 42}
func MonadFlap ¶
func MonadFlap[FAB ~func(A) B, S, A, B any](fab State[S, FAB], a A) State[S, B]
MonadFlap applies a fixed value to a State computation containing a function. This is the reverse of MonadAp, where the value is known but the function is in the State context.
Example:
type Counter struct { count int }
fab := Of[Counter](func(x int) int { return x * 2 })
result := MonadFlap(fab, 21)(Counter{count: 5})
// result = Pair{head: Counter{count: 5}, tail: 42}
func MonadMap ¶
MonadMap transforms the value produced by a State computation using the given function, while preserving the state. This is the Functor interface implementation for State.
Example:
type Counter struct { count int }
computation := Of[Counter](10)
doubled := MonadMap(computation, func(x int) int { return x * 2 })
result := doubled(Counter{count: 5})
// result = Pair{head: Counter{count: 5}, tail: 20}
func Of ¶
func Of[S, A any](a A) State[S, A]
Of creates a State computation that returns the given value without modifying the state. This is the Pointed interface implementation for State, lifting a pure value into the State context.
Example:
type Counter struct { count int }
computation := Of[Counter](42)
result := computation(Counter{count: 5})
// result = Pair{head: Counter{count: 5}, tail: 42}
func Put ¶
func Put[S any]() State[S, Void]
Put returns a State computation that replaces the current state with a new state. The returned value is Void, indicating this operation is performed for its side effect.
Example:
type Counter struct { count int }
setState := Put[Counter]()
result := setState(Counter{count: 10})
// result = Pair{head: Counter{count: 10}, tail: Void}