Documentation
¶
Index ¶
- func Applicative[S, A, B any]() applicative.Applicative[A, B, State[S, A], State[S, B], State[S, func(A) B]]
- func ApplicativeMonoid[S, A any](m M.Monoid[A]) M.Monoid[State[S, A]]
- 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 ApplicativeMonoid ¶ added in v2.1.5
ApplicativeMonoid lifts a monoid into the State applicative functor context.
This function creates a monoid for State[S, A] values given a monoid for the base type A. It uses the State monad's applicative operations (Of, MonadMap, MonadAp) to lift the monoid operations into the State context, allowing you to combine stateful computations that produce monoidal values.
The resulting monoid combines State computations by:
- Threading the state through both computations sequentially
- Combining the produced values using the underlying monoid's Concat operation
- Returning a new State computation with the combined value and final state
The empty element is a State computation that returns the underlying monoid's empty value without modifying the state.
This is particularly useful for:
- Accumulating results across multiple stateful computations
- Building complex state transformations that aggregate values
- Combining independent stateful operations that produce monoidal results
Type Parameters:
- S: The state type that is threaded through the computations
- A: The value type that has a monoid structure
Parameters:
- m: A monoid for the base type A that defines how to combine values
Returns:
- A Monoid[State[S, A]] that combines stateful computations using the base monoid
The resulting monoid satisfies the standard monoid laws:
- Associativity: Concat(Concat(s1, s2), s3) = Concat(s1, Concat(s2, s3))
- Left identity: Concat(Empty(), s) = s
- Right identity: Concat(s, Empty()) = s
Example with integer addition:
import (
N "github.com/IBM/fp-go/v2/number"
"github.com/IBM/fp-go/v2/pair"
)
type Counter struct {
count int
}
// Create a monoid for State[Counter, int] using integer addition
intAddMonoid := N.MonoidSum[int]()
stateMonoid := state.ApplicativeMonoid[Counter](intAddMonoid)
// Create two stateful computations
s1 := state.Of[Counter](5) // Returns 5, state unchanged
s2 := state.Of[Counter](3) // Returns 3, state unchanged
// Combine them using the monoid
combined := stateMonoid.Concat(s1, s2)
result := combined(Counter{count: 10})
// result = Pair{head: Counter{count: 10}, tail: 8} // 5 + 3
// Empty element
empty := stateMonoid.Empty()
emptyResult := empty(Counter{count: 10})
// emptyResult = Pair{head: Counter{count: 10}, tail: 0}
Example with string concatenation and state modification:
import (
S "github.com/IBM/fp-go/v2/string"
)
type Logger struct {
logs []string
}
strMonoid := S.Monoid
stateMonoid := state.ApplicativeMonoid[Logger](strMonoid)
// Stateful computation that logs and returns a message
logMessage := func(msg string) state.State[Logger, string] {
return func(s Logger) pair.Pair[Logger, string] {
newState := Logger{logs: append(s.logs, msg)}
return pair.MakePair(newState, msg)
}
}
s1 := logMessage("Hello")
s2 := logMessage(" World")
// Combine the computations - both log entries are added, messages concatenated
combined := stateMonoid.Concat(s1, s2)
result := combined(Logger{logs: []string{}})
// result.head.logs = ["Hello", " World"]
// result.tail = "Hello World"
Example demonstrating monoid laws:
intAddMonoid := N.MonoidSum[int]()
m := state.ApplicativeMonoid[Counter](intAddMonoid)
s1 := state.Of[Counter](1)
s2 := state.Of[Counter](2)
s3 := state.Of[Counter](3)
initialState := Counter{count: 0}
// Associativity
left := m.Concat(m.Concat(s1, s2), s3)
right := m.Concat(s1, m.Concat(s2, s3))
// Both produce: Pair{head: Counter{count: 0}, tail: 6}
// Left identity
leftId := m.Concat(m.Empty(), s1)
// Produces: Pair{head: Counter{count: 0}, tail: 1}
// Right identity
rightId := m.Concat(s1, m.Empty())
// Produces: Pair{head: Counter{count: 0}, tail: 1}
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.
func IMap ¶ added in v2.1.6
IMap is a profunctor-like operation for State that transforms both the state and value using an isomorphism. It applies an isomorphism f to the state (contravariantly via Get and covariantly via ReverseGet) and a function g to the value (covariantly).
See: https://github.com/fantasyland/fantasy-land?tab=readme-ov-file#profunctor
This operation allows you to:
- Convert the input state from S2 to S1 using the isomorphism's Get function
- Run the State computation with S1
- Convert the output state back from S1 to S2 using the isomorphism's ReverseGet function
- Transform the result value from A to B using g
Type Parameters:
- A: The original value type produced by the State
- S2: The new state type
- S1: The original state type expected by the State
- B: The new output value type
Parameters:
- f: An isomorphism between S2 and S1
- g: Function to transform the output value from A to B
Returns:
- A Kleisli arrow that takes a State[S1, A] and returns a State[S2, B]
func MapState ¶ added in v2.1.6
MapState is a contravariant-like operation for State that transforms the state type using an isomorphism. It applies an isomorphism f to convert between state types while preserving the value type.
See: https://github.com/fantasyland/fantasy-land?tab=readme-ov-file#profunctor
This operation allows you to:
- Convert the input state from S2 to S1 using the isomorphism's Get function
- Run the State computation with S1
- Convert the output state back from S1 to S2 using the isomorphism's ReverseGet function
- Keep the value type A unchanged
Type Parameters:
- A: The value type (unchanged)
- S2: The new state type
- S1: The original state type expected by the State
Parameters:
- f: An isomorphism between S2 and S1
Returns:
- A Kleisli arrow that takes a State[S1, A] and returns a State[S2, A]
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}