Documentation
¶
Overview ¶
Package record contains monadic operations for maps as well as a rich set of utility functions
Index ¶
- func Ap[A any, K comparable, B any](m Monoid[Record[K, B]]) func(fa Record[K, A]) Operator[K, func(A) B, B]
- func ApS[S1, T any, K comparable, S2 any](m Monoid[Record[K, S2]]) func(setter func(T) func(S1) S2, fa Record[K, T]) Operator[K, S1, S2]
- func Bind[S1, T any, K comparable, S2 any](m Monoid[Record[K, S2]]) func(setter func(T) func(S1) S2, f Kleisli[K, S1, T]) Operator[K, S1, S2]
- func Chain[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]]) func(Kleisli[K, V1, V2]) Operator[K, V1, V2]
- func ChainWithIndex[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]]) func(KleisliWithIndex[K, V1, V2]) Operator[K, V1, V2]
- func Collect[K comparable, V, R any](f func(K, V) R) func(Record[K, V]) []R
- func CollectOrd[V, R any, K comparable](o ord.Ord[K]) func(func(K, V) R) func(Record[K, V]) []R
- func Eq[K comparable, V any](e E.Eq[V]) E.Eq[Record[K, V]]
- func FilterChain[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]]) func(option.Kleisli[V1, Record[K, V2]]) Operator[K, V1, V2]
- func FilterChainWithIndex[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]]) func(func(K, V1) Option[Record[K, V2]]) Operator[K, V1, V2]
- func Flatten[K comparable, V any](m Monoid[Record[K, V]]) func(Record[K, Record[K, V]]) Record[K, V]
- func Fold[K comparable, A any](m Monoid[A]) func(Record[K, A]) A
- func FoldMap[K comparable, A, B any](m Monoid[B]) func(func(A) B) func(Record[K, A]) B
- func FoldMapOrd[A, B any, K comparable](o ord.Ord[K]) func(m Monoid[B]) func(func(A) B) func(Record[K, A]) B
- func FoldMapOrdWithIndex[K comparable, A, B any](o ord.Ord[K]) func(m Monoid[B]) func(func(K, A) B) func(Record[K, A]) B
- func FoldMapWithIndex[K comparable, A, B any](m Monoid[B]) func(func(K, A) B) func(Record[K, A]) B
- func FoldOrd[A any, K comparable](o ord.Ord[K]) func(m Monoid[A]) func(Record[K, A]) A
- func FromArrayMap[A any, K comparable, V any](m Mg.Magma[V]) func(f func(A) Entry[K, V]) Kleisli[K, []A, V]
- func FromFoldableMap[...](m Mg.Magma[V], red FOLDABLE) func(f func(A) Entry[K, V]) Kleisli[K, HKTA, V]
- func FromStrictEquals[K, V comparable]() E.Eq[Record[K, V]]
- func Has[K comparable, V any](k K, r Record[K, V]) bool
- func IsEmpty[K comparable, V any](r Record[K, V]) bool
- func IsNil[K comparable, V any](m Record[K, V]) bool
- func IsNonEmpty[K comparable, V any](r Record[K, V]) bool
- func IsNonNil[K comparable, V any](m Record[K, V]) bool
- func Keys[K comparable, V any](r Record[K, V]) []K
- func KeysOrd[V any, K comparable](o ord.Ord[K]) func(r Record[K, V]) []K
- func Lookup[V any, K comparable](k K) option.Kleisli[Record[K, V], V]
- func Reduce[K comparable, V, R any](f func(R, V) R, initial R) func(Record[K, V]) R
- func ReduceOrd[V, R any, K comparable](o ord.Ord[K]) func(func(R, V) R, R) func(Record[K, V]) R
- func ReduceOrdWithIndex[V, R any, K comparable](o ord.Ord[K]) func(func(K, R, V) R, R) func(Record[K, V]) R
- func ReduceRef[K comparable, V, R any](f func(R, *V) R, initial R) func(Record[K, V]) R
- func ReduceRefWithIndex[K comparable, V, R any](f func(K, R, *V) R, initial R) func(Record[K, V]) R
- func ReduceWithIndex[K comparable, V, R any](f func(K, R, V) R, initial R) func(Record[K, V]) R
- func Sequence[K comparable, A, HKTA, HKTAA, HKTRA any](fof func(map[K]A) HKTRA, ...) HKTRA
- func Size[K comparable, V any](r Record[K, V]) int
- func Traverse[K comparable, A, B, HKTB, HKTAB, HKTRB any](fof func(map[K]B) HKTRB, ...) func(map[K]A) HKTRB
- func TraverseWithIndex[K comparable, A, B, HKTB, HKTAB, HKTRB any](fof func(map[K]B) HKTRB, ...) func(map[K]A) HKTRB
- func Union[K comparable, V any](m Mg.Magma[V]) func(Record[K, V]) Operator[K, V, V]
- func Values[K comparable, V any](r Record[K, V]) []V
- func ValuesOrd[V any, K comparable](o ord.Ord[K]) func(r Record[K, V]) []V
- type Collector
- type Endomorphism
- type Entries
- type Entry
- type Kleisli
- type KleisliWithIndex
- type Monoid
- type Operator
- func BindTo[S1, T any, K comparable](setter func(T) S1) Operator[K, T, S1]
- func DeleteAt[K comparable, V any](k K) Operator[K, V, V]
- func Filter[K comparable, V any](f Predicate[K]) Operator[K, V, V]
- func FilterMap[K comparable, V1, V2 any](f option.Kleisli[V1, V2]) Operator[K, V1, V2]
- func FilterMapWithIndex[K comparable, V1, V2 any](f func(K, V1) Option[V2]) Operator[K, V1, V2]
- func FilterWithIndex[K comparable, V any](f PredicateWithIndex[K, V]) Operator[K, V, V]
- func Flap[B any, K comparable, A any](a A) Operator[K, func(A) B, B]
- func Let[S1, T any, K comparable, S2 any](setter func(T) func(S1) S2, f func(S1) T) Operator[K, S1, S2]
- func LetTo[S1, T any, K comparable, S2 any](setter func(T) func(S1) S2, b T) Operator[K, S1, S2]
- func Map[K comparable, V, R any](f func(V) R) Operator[K, V, R]
- func MapRef[K comparable, V, R any](f func(*V) R) Operator[K, V, R]
- func MapRefWithIndex[K comparable, V, R any](f func(K, *V) R) Operator[K, V, R]
- func MapWithIndex[K comparable, V, R any](f func(K, V) R) Operator[K, V, R]
- func Merge[K comparable, V any](right Record[K, V]) Operator[K, V, V]
- func UpsertAt[K comparable, V any](k K, v V) Operator[K, V, V]
- type OperatorWithIndex
- type Option
- type Predicate
- type PredicateWithIndex
- type Record
- func ConstNil[K comparable, V any]() Record[K, V]
- func Copy[K comparable, V any](m Record[K, V]) Record[K, V]
- func Do[K comparable, S any]() Record[K, S]
- func Empty[K comparable, V any]() Record[K, V]
- func FromEntries[K comparable, V any](fa Entries[K, V]) Record[K, V]
- func MonadAp[A any, K comparable, B any](m Monoid[Record[K, B]], fab Record[K, func(A) B], fa Record[K, A]) Record[K, B]
- func MonadChain[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]], r Record[K, V1], f Kleisli[K, V1, V2]) Record[K, V2]
- func MonadChainWithIndex[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]], r Record[K, V1], f KleisliWithIndex[K, V1, V2]) Record[K, V2]
- func MonadFlap[B any, K comparable, A any](fab Record[K, func(A) B], a A) Record[K, B]
- func MonadMap[K comparable, V, R any](r Record[K, V], f func(V) R) Record[K, R]
- func MonadMapRef[K comparable, V, R any](r Record[K, V], f func(*V) R) Record[K, R]
- func MonadMapRefWithIndex[K comparable, V, R any](r Record[K, V], f func(K, *V) R) Record[K, R]
- func MonadMapWithIndex[K comparable, V, R any](r Record[K, V], f func(K, V) R) Record[K, R]
- func Of[K comparable, A any](k K, a A) Record[K, A]
- func Singleton[K comparable, V any](k K, v V) Record[K, V]
- type Reducer
- type ReducerWithIndex
- type Semigroup
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Ap ¶
func Ap[A any, K comparable, B any](m Monoid[Record[K, B]]) func(fa Record[K, A]) Operator[K, func(A) B, B]
Ap returns a function that applies a record of functions to a record of values.
This is the curried version of MonadAp, useful for composition. The applicative apply operation for records.
Example:
funcs := Record[string, func(int) int]{
"double": func(x int) int { return x * 2 },
}
applyFuncs := Ap[int, string, int](MergeMonoid[string, int]())
values := Record[string, int]{"double": 5}
result := applyFuncs(values)(funcs) // {"double": 10}
func ApS ¶
func ApS[S1, T any, K comparable, S2 any](m Monoid[Record[K, S2]]) func( setter func(T) func(S1) S2, fa Record[K, T], ) Operator[K, S1, S2]
ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently (using Applicative rather than Monad). This allows independent computations to be combined without one depending on the result of the other.
Unlike Bind, which sequences operations, ApS can be used when operations are independent and can conceptually run in parallel.
Example:
type State struct {
Name string
Count int
}
// These operations are independent and can be combined with ApS
names := map[string]string{"a": "Alice", "b": "Bob"}
counts := map[string]int{"a": 10, "b": 20}
result := F.Pipe2(
record.Do[string, State](),
record.ApS(monoid.Record[string, State]())(
func(name string) func(State) State {
return func(s State) State { s.Name = name; return s }
},
names,
),
record.ApS(monoid.Record[string, State]())(
func(count int) func(State) State {
return func(s State) State { s.Count = count; return s }
},
counts,
),
) // map[string]State{"a": {Name: "Alice", Count: 10}, "b": {Name: "Bob", Count: 20}}
func Bind ¶
func Bind[S1, T any, K comparable, S2 any](m Monoid[Record[K, S2]]) func( setter func(T) func(S1) S2, f Kleisli[K, S1, T], ) Operator[K, S1, S2]
Bind attaches the result of a computation to a context [S1] to produce a context [S2]. This enables sequential composition where each step can depend on the results of previous steps. For records, this merges values by key.
The setter function takes the result of the computation and returns a function that updates the context from S1 to S2.
Example:
type State struct {
Name string
Count int
}
result := F.Pipe2(
record.Do[string, State](),
record.Bind(monoid.Record[string, State]())(
func(name string) func(State) State {
return func(s State) State { s.Name = name; return s }
},
func(s State) map[string]string {
return map[string]string{"a": "Alice", "b": "Bob"}
},
),
record.Bind(monoid.Record[string, State]())(
func(count int) func(State) State {
return func(s State) State { s.Count = count; return s }
},
func(s State) map[string]int {
// This can access s.Name from the previous step
return map[string]int{"a": len(s.Name), "b": len(s.Name) * 2}
},
),
)
func Chain ¶
func Chain[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]]) func(Kleisli[K, V1, V2]) Operator[K, V1, V2]
Chain returns a function that chains record transformations.
This is the curried version of MonadChain, useful for composition. The monadic bind operation for records.
Example:
expand := Chain[int, string, string](MergeMonoid[string, string]())(
func(v int) Record[string, string] {
return Record[string, string]{"result": fmt.Sprint(v)}
},
)
result := expand(Record[string, int]{"a": 1})
func ChainWithIndex ¶
func ChainWithIndex[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]]) func(KleisliWithIndex[K, V1, V2]) Operator[K, V1, V2]
ChainWithIndex returns a function that chains record transformations with key-value access.
This is the curried version of MonadChainWithIndex, useful for composition.
Example:
expand := ChainWithIndex[int, string, string](MergeMonoid[string, string]())(
func(k string, v int) Record[string, string] {
return Record[string, string]{k + "_str": fmt.Sprint(v)}
},
)
result := expand(Record[string, int]{"a": 1})
func Collect ¶
func Collect[K comparable, V, R any](f func(K, V) R) func(Record[K, V]) []R
Collect transforms each key-value pair in a record using a collector function and returns the results as a slice.
The collector function receives both the key and value, allowing transformations that depend on both. The order of results is non-deterministic.
Example:
record := Record[string, int]{"a": 1, "b": 2}
toStrings := Collect(func(k string, v int) string {
return fmt.Sprintf("%s=%d", k, v)
})
result := toStrings(record) // ["a=1", "b=2"] in any order
func CollectOrd ¶
func CollectOrd[V, R any, K comparable](o ord.Ord[K]) func(func(K, V) R) func(Record[K, V]) []R
CollectOrd transforms each key-value pair in a record using a collector function and returns the results as a slice in the order specified by the Ord instance.
Unlike Collect, this function guarantees the order of results based on key ordering.
Example:
record := Record[string, int]{"c": 3, "a": 1, "b": 2}
toStrings := CollectOrd(S.Ord)(func(k string, v int) string {
return fmt.Sprintf("%s=%d", k, v)
})
result := toStrings(record) // ["a=1", "b=2", "c=3"] (ordered by key)
func FilterChain ¶
func FilterChain[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]]) func(option.Kleisli[V1, Record[K, V2]]) Operator[K, V1, V2]
FilterChain filters and chains transformations that produce records.
Similar to FilterChainWithIndex but without key access in the transformation function.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
expandEven := FilterChain[int, string, int](MergeMonoid[string, int]())(
func(v int) Option[Record[string, int]] {
if v%2 == 0 {
return O.Some(Record[string, int]{"doubled": v * 2})
}
return O.None[Record[string, int]]()
},
)
result := expandEven(record)
func FilterChainWithIndex ¶
func FilterChainWithIndex[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]]) func(func(K, V1) Option[Record[K, V2]]) Operator[K, V1, V2]
FilterChainWithIndex filters and chains transformations that produce records.
Combines filtering with chaining: the transformation returns Some(record) to include the result, or None to exclude it. Results are combined using the Monoid.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
expandEven := FilterChainWithIndex[int, string, int](MergeMonoid[string, int]())(
func(k string, v int) Option[Record[string, int]] {
if v%2 == 0 {
return O.Some(Record[string, int]{k + "_doubled": v * 2})
}
return O.None[Record[string, int]]()
},
)
result := expandEven(record) // {"b_doubled": 4}
func Flatten ¶
func Flatten[K comparable, V any](m Monoid[Record[K, V]]) func(Record[K, Record[K, V]]) Record[K, V]
Flatten converts a nested record (record of records) into a flat record.
When keys conflict between nested records, the Monoid determines how to combine values. This is the monadic join operation.
Example:
nested := Record[string, Record[string, int]]{
"group1": {"a": 1, "b": 2},
"group2": {"c": 3, "d": 4},
}
flat := Flatten(MergeMonoid[string, int]())(nested)
// flat: {"a": 1, "b": 2, "c": 3, "d": 4}
func Fold ¶
func Fold[K comparable, A any](m Monoid[A]) func(Record[K, A]) A
Fold combines all values in a record using a Monoid.
This is useful when the record values are already of the target type and you just need to combine them.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
sum := Fold(N.MonoidSum[int]())
result := sum(record) // 6
func FoldMap ¶
func FoldMap[K comparable, A, B any](m Monoid[B]) func(func(A) B) func(Record[K, A]) B
FoldMap maps each value in a record and folds the results using a Monoid.
This is a two-step operation: first map each value using the provided function, then combine all results using the Monoid's operation.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
sumDoubled := FoldMap(N.MonoidSum[int]())(func(v int) int {
return v * 2
})
result := sumDoubled(record) // 12 (2 + 4 + 6)
Example ¶
src := map[string]string{
"a": "a",
"b": "b",
"c": "c",
}
fold := FoldMapOrd[string, string](S.Ord)(S.Monoid)(strings.ToUpper)
fmt.Println(fold(src))
Output: ABC
func FoldMapOrd ¶
func FoldMapOrd[A, B any, K comparable](o ord.Ord[K]) func(m Monoid[B]) func(func(A) B) func(Record[K, A]) B
FoldMapOrd maps and folds a record with keys processed in order.
Similar to FoldMap but guarantees the order in which entries are processed based on the provided Ord instance.
Example:
record := Record[string, int]{"c": 3, "a": 1, "b": 2}
concat := FoldMapOrd(S.Ord)(S.MonoidConcat)(func(v int) string {
return fmt.Sprint(v)
})
result := concat(record) // "123" (alphabetical key order)
func FoldMapOrdWithIndex ¶
func FoldMapOrdWithIndex[K comparable, A, B any](o ord.Ord[K]) func(m Monoid[B]) func(func(K, A) B) func(Record[K, A]) B
FoldMapOrdWithIndex maps and folds a record with key-value access and ordered processing.
Combines FoldMapWithIndex with ordered key processing based on the Ord instance.
Example:
record := Record[string, int]{"c": 3, "a": 1, "b": 2}
concat := FoldMapOrdWithIndex(S.Ord)(S.MonoidConcat)(func(k string, v int) string {
return k + fmt.Sprint(v)
})
result := concat(record) // "a1b2c3" (alphabetical key order)
func FoldMapWithIndex ¶
func FoldMapWithIndex[K comparable, A, B any](m Monoid[B]) func(func(K, A) B) func(Record[K, A]) B
FoldMapWithIndex maps each key-value pair in a record and folds the results using a Monoid.
Similar to FoldMap but the mapping function receives both key and value.
Example:
record := Record[string, int]{"a": 1, "b": 2}
weightedSum := FoldMapWithIndex(N.MonoidSum[int]())(func(k string, v int) int {
return len(k) * v
})
result := weightedSum(record) // 1*1 + 1*2 = 3
func FoldOrd ¶
func FoldOrd[A any, K comparable](o ord.Ord[K]) func(m Monoid[A]) func(Record[K, A]) A
FoldOrd combines all values in a record using a Monoid with keys processed in order.
Similar to Fold but guarantees the order based on the provided Ord instance.
Example:
record := Record[string, string]{"c": "3", "a": "1", "b": "2"}
concat := FoldOrd(S.Ord)(S.MonoidConcat)
result := concat(record) // "123" (alphabetical key order)
func FromArrayMap ¶
func FromArrayMap[ A any, K comparable, V any](m Mg.Magma[V]) func(f func(A) Entry[K, V]) Kleisli[K, []A, V]
FromArrayMap converts an array to a record by mapping elements to entries.
Each element is transformed into a key-value entry. When duplicate keys occur, the Magma determines how to combine their values.
Example:
type Item struct { Name string; Count int }
items := []Item{{"apple", 5}, {"banana", 3}, {"apple", 2}}
sumMagma := Mg.MakeMagma(func(a, b int) int { return a + b })
toRecord := FromArrayMap[Item, string, int](sumMagma)(func(item Item) Entry[string, int] {
return P.MakePair(item.Name, item.Count)
})
result := toRecord(items) // {"apple": 7, "banana": 3}
func FromFoldableMap ¶
func FromFoldableMap[ FOLDABLE ~func(func(Record[K, V], A) Record[K, V], Record[K, V]) func(HKTA) Record[K, V], A any, HKTA any, K comparable, V any](m Mg.Magma[V], red FOLDABLE) func(f func(A) Entry[K, V]) Kleisli[K, HKTA, V]
FromFoldableMap converts a foldable structure to a record by mapping elements to entries.
The mapping function transforms each element into a key-value entry. When duplicate keys occur, the Magma determines how to combine their values. This is useful for building records from custom data structures.
Example:
type Person struct { ID string; Score int }
people := []Person{{"alice", 10}, {"bob", 20}, {"alice", 15}}
sumMagma := Mg.MakeMagma(func(a, b int) int { return a + b })
toRecord := FromArrayMap[Person, string, int](sumMagma)(func(p Person) Entry[string, int] {
return P.MakePair(p.ID, p.Score)
})
result := toRecord(people) // {"alice": 25, "bob": 20}
func FromStrictEquals ¶
func FromStrictEquals[K, V comparable]() E.Eq[Record[K, V]]
FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
func Has ¶
func Has[K comparable, V any](k K, r Record[K, V]) bool
Has tests if a key exists in a record.
Returns true if the key is present in the record, false otherwise.
Example:
record := Record[string, int]{"a": 1, "b": 2}
Has("a", record) // true
Has("c", record) // false
func IsEmpty ¶
func IsEmpty[K comparable, V any](r Record[K, V]) bool
IsEmpty tests if a record is empty (contains no entries).
Returns true if the record has no key-value pairs, false otherwise.
Example:
empty := Record[string, int]{}
IsEmpty(empty) // true
nonEmpty := Record[string, int]{"a": 1}
IsEmpty(nonEmpty) // false
func IsNil ¶
func IsNil[K comparable, V any](m Record[K, V]) bool
IsNil checks if the record is nil (not initialized).
Note: This checks for nil, not empty. An empty record {} is not nil.
Example:
var record Record[string, int]
IsNil(record) // true
record = Record[string, int]{}
IsNil(record) // false
func IsNonEmpty ¶
func IsNonEmpty[K comparable, V any](r Record[K, V]) bool
IsNonEmpty tests if a record is not empty (contains at least one entry).
Returns true if the record has at least one key-value pair, false otherwise. This is the logical negation of IsEmpty.
Example:
record := Record[string, int]{"a": 1}
IsNonEmpty(record) // true
func IsNonNil ¶
func IsNonNil[K comparable, V any](m Record[K, V]) bool
IsNonNil checks if the record is not nil (is initialized).
This is the logical negation of IsNil.
Example:
record := Record[string, int]{"a": 1}
IsNonNil(record) // true
func Keys ¶
func Keys[K comparable, V any](r Record[K, V]) []K
Keys returns all keys from a record as a slice.
The order of keys is non-deterministic due to Go's map iteration behavior. Use KeysOrd if you need keys in a specific order.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
keys := Keys(record) // ["a", "b", "c"] in any order
func KeysOrd ¶
func KeysOrd[V any, K comparable](o ord.Ord[K]) func(r Record[K, V]) []K
KeysOrd returns the keys from a record in the order specified by the Ord instance.
Unlike Keys, this guarantees a specific order for the returned keys.
Example:
record := Record[string, int]{"c": 3, "a": 1, "b": 2}
getKeys := KeysOrd(S.Ord)
keys := getKeys(record) // ["a", "b", "c"]
func Lookup ¶
func Lookup[V any, K comparable](k K) option.Kleisli[Record[K, V], V]
Lookup returns a function that retrieves the value for a key in a record if it exists.
Returns Some(value) if the key exists, None otherwise. This is the curried version that returns a Kleisli arrow, useful for composition.
Example:
record := Record[string, int]{"a": 1, "b": 2}
lookupA := Lookup[int]("a")
result := lookupA(record) // Some(1)
lookupC := Lookup[int]("c")
result2 := lookupC(record) // None
func Reduce ¶
func Reduce[K comparable, V, R any](f func(R, V) R, initial R) func(Record[K, V]) R
Reduce reduces a record to a single value by applying a reducer function to each value.
The reducer function receives the accumulated result and the current value, returning the new accumulated result. The iteration order is non-deterministic.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
sum := Reduce(func(acc int, v int) int {
return acc + v
}, 0)
result := sum(record) // 6
func ReduceOrd ¶
func ReduceOrd[V, R any, K comparable](o ord.Ord[K]) func(func(R, V) R, R) func(Record[K, V]) R
ReduceOrd reduces a record to a single value with keys processed in order.
Similar to ReduceOrdWithIndex but the reducer function doesn't receive keys.
Example:
record := Record[string, int]{"c": 3, "a": 1, "b": 2}
sum := ReduceOrd(S.Ord)(func(acc int, v int) int {
return acc + v
}, 0)
result := sum(record) // 6 (order doesn't affect sum)
func ReduceOrdWithIndex ¶
func ReduceOrdWithIndex[V, R any, K comparable](o ord.Ord[K]) func(func(K, R, V) R, R) func(Record[K, V]) R
ReduceOrdWithIndex reduces a record to a single value with keys processed in order.
Unlike ReduceWithIndex, this guarantees the order in which keys are processed based on the provided Ord instance.
Example:
record := Record[string, int]{"c": 3, "a": 1, "b": 2}
concat := ReduceOrdWithIndex(S.Ord)(func(k string, acc string, v int) string {
return acc + k + fmt.Sprint(v)
}, "")
result := concat(record) // "a1b2c3" (alphabetical order)
func ReduceRef ¶
func ReduceRef[K comparable, V, R any](f func(R, *V) R, initial R) func(Record[K, V]) R
ReduceRef reduces a record to a single value by applying a reducer function to each value reference.
Similar to Reduce, but passes value pointers instead of values, which can be more efficient for large value types and allows mutation if needed.
Example:
record := Record[string, LargeStruct]{...}
result := ReduceRef(func(acc int, v *LargeStruct) int {
return acc + v.Size
}, 0)(record)
func ReduceRefWithIndex ¶
func ReduceRefWithIndex[K comparable, V, R any](f func(K, R, *V) R, initial R) func(Record[K, V]) R
ReduceRefWithIndex reduces a record to a single value by applying a reducer function to each key-value pair with value references.
Combines the benefits of ReduceWithIndex and ReduceRef, providing both key access and value references for efficient processing of large value types.
Example:
record := Record[string, LargeStruct]{...}
result := ReduceRefWithIndex(func(k string, acc int, v *LargeStruct) int {
return acc + len(k) * v.Size
}, 0)(record)
func ReduceWithIndex ¶
func ReduceWithIndex[K comparable, V, R any](f func(K, R, V) R, initial R) func(Record[K, V]) R
ReduceWithIndex reduces a record to a single value by applying a reducer function to each key-value pair.
The reducer function receives the key, accumulated result, and current value, allowing reductions that depend on the key. The iteration order is non-deterministic.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
weightedSum := ReduceWithIndex(func(k string, acc int, v int) int {
weight := len(k)
return acc + (v * weight)
}, 0)
result := weightedSum(record) // 1 + 2 + 3 = 6
func Sequence ¶
func Sequence[K comparable, A, HKTA, HKTAA, HKTRA any]( fof func(map[K]A) HKTRA, fmap func(func(map[K]A) func(A) map[K]A) func(HKTRA) HKTAA, fap func(HKTA) func(HKTAA) HKTRA, ma map[K]HKTA) HKTRA
Sequence transforms a map of effects into an effect of a map. This is the dual of Traverse where the transformation function is the identity.
This is useful when you have a map where each value is already in an effect context (like Option, Either, etc.) and you want to "flip" the nesting to get a single effect containing a map of plain values.
If any value in the map is a "failure" (e.g., None, Left), the entire result will be a failure. If all values are "successes", the result will be a success containing a map of all the unwrapped values.
Type parameters:
- K: The key type (must be comparable)
- A: The value type inside the effect
- HKTA: Higher-kinded type representing the effect containing A (e.g., Option[A])
- HKTAA: Higher-kinded type representing a function from A to map[K]A in the effect
- HKTRA: Higher-kinded type representing the effect containing map[K]A
Parameters:
- fof: Lifts a pure map[K]A into the effect (the "of" or "pure" function)
- fmap: Maps a function over the effect (the "map" or "fmap" function)
- fap: Applies an effectful function to an effectful value (the "ap" function)
- ma: The input map where each value is in an effect context
Example with Option:
input := map[string]O.Option[int]{"a": O.Some(1), "b": O.Some(2)}
result := Sequence(O.Of[map[string]int], O.Map[...], O.Ap[...], input)
// result: O.Some(map[string]int{"a": 1, "b": 2})
input2 := map[string]O.Option[int]{"a": O.Some(1), "b": O.None[int]()}
result2 := Sequence(O.Of[map[string]int], O.Map[...], O.Ap[...], input2)
// result2: O.None[map[string]int]()
func Size ¶
func Size[K comparable, V any](r Record[K, V]) int
Size returns the number of key-value pairs in a record.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
Size(record) // 3
empty := Empty[string, int]()
Size(empty) // 0
func Traverse ¶
func Traverse[K comparable, A, B, HKTB, HKTAB, HKTRB any]( fof func(map[K]B) HKTRB, fmap func(func(map[K]B) func(B) map[K]B) func(HKTRB) HKTAB, fap func(HKTB) func(HKTAB) HKTRB, f func(A) HKTB) func(map[K]A) HKTRB
Traverse transforms a map of values into a value of a map by applying an effectful function to each value. Unlike TraverseWithIndex, this function does not provide access to the keys.
This is useful when you need to perform an operation that may fail or have side effects on each element of a map, and you want to collect the results in the same applicative context.
Type parameters:
- K: The key type (must be comparable)
- A: The input value type
- B: The output value type
- HKTB: Higher-kinded type representing the effect containing B (e.g., Option[B], Either[E, B])
- HKTAB: Higher-kinded type representing a function from B to map[K]B in the effect
- HKTRB: Higher-kinded type representing the effect containing map[K]B
Parameters:
- fof: Lifts a pure map[K]B into the effect (the "of" or "pure" function)
- fmap: Maps a function over the effect (the "map" or "fmap" function)
- fap: Applies an effectful function to an effectful value (the "ap" function)
- f: The transformation function that takes a value and returns an effect
Example with Option:
f := func(s string) O.Option[string] {
if s != "" {
return O.Some(strings.ToUpper(s))
}
return O.None[string]()
}
traverse := Traverse(O.Of[map[string]string], O.Map[...], O.Ap[...], f)
result := traverse(map[string]string{"a": "hello"}) // O.Some(map[string]string{"a": "HELLO"})
func TraverseWithIndex ¶
func TraverseWithIndex[K comparable, A, B, HKTB, HKTAB, HKTRB any]( fof func(map[K]B) HKTRB, fmap func(func(map[K]B) func(B) map[K]B) func(HKTRB) HKTAB, fap func(HKTB) func(HKTAB) HKTRB, f func(K, A) HKTB) func(map[K]A) HKTRB
TraverseWithIndex transforms a map of values into a value of a map by applying an effectful function to each key-value pair. The function has access to both the key and value.
This is useful when you need to perform an operation that may fail or have side effects on each element of a map, and you want to collect the results in the same applicative context.
Type parameters:
- K: The key type (must be comparable)
- A: The input value type
- B: The output value type
- HKTB: Higher-kinded type representing the effect containing B (e.g., Option[B], Either[E, B])
- HKTAB: Higher-kinded type representing a function from B to map[K]B in the effect
- HKTRB: Higher-kinded type representing the effect containing map[K]B
Parameters:
- fof: Lifts a pure map[K]B into the effect (the "of" or "pure" function)
- fmap: Maps a function over the effect (the "map" or "fmap" function)
- fap: Applies an effectful function to an effectful value (the "ap" function)
- f: The transformation function that takes a key and value and returns an effect
Example with Option:
f := func(k string, n int) O.Option[int] {
if n > 0 {
return O.Some(n * 2)
}
return O.None[int]()
}
traverse := TraverseWithIndex(O.Of[map[string]int], O.Map[...], O.Ap[...], f)
result := traverse(map[string]int{"a": 1, "b": 2}) // O.Some(map[string]int{"a": 2, "b": 4})
func Union ¶
func Union[K comparable, V any](m Mg.Magma[V]) func(Record[K, V]) Operator[K, V, V]
Union combines two records using the provided Magma to resolve conflicts for duplicate keys.
The Magma defines how to combine values when the same key exists in both records. This is useful for custom merge strategies beyond simple replacement.
Example:
// Sum values for duplicate keys
sumMagma := Mg.MakeMagma(func(a, b int) int { return a + b })
unionSum := Union(sumMagma)
r1 := Record[string, int]{"a": 1, "b": 2}
r2 := Record[string, int]{"b": 3, "c": 4}
result := unionSum(r1)(r2) // {"a": 1, "b": 5, "c": 4}
func Values ¶
func Values[K comparable, V any](r Record[K, V]) []V
Values returns all values from a record as a slice.
The order of values is non-deterministic due to Go's map iteration behavior. Use ValuesOrd if you need values ordered by their keys.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
values := Values(record) // [1, 2, 3] in any order
func ValuesOrd ¶
func ValuesOrd[V any, K comparable](o ord.Ord[K]) func(r Record[K, V]) []V
ValuesOrd returns the values from a record ordered by their keys.
The values are returned in the order determined by sorting the keys using the Ord instance.
Example:
record := Record[string, int]{"c": 3, "a": 1, "b": 2}
getValues := ValuesOrd(S.Ord)
values := getValues(record) // [1, 2, 3] (ordered by key: a, b, c)
Example ¶
src := map[string]string{
"c": "a",
"b": "b",
"a": "c",
}
getValues := ValuesOrd[string](S.Ord)
fmt.Println(getValues(src))
Output: [c b a]
Types ¶
type Collector ¶ added in v2.0.1
type Collector[K comparable, V, R any] = func(K, V) R
Collector transforms key-value pairs into a result type and collects them into an array.
Example:
toStrings := Collect(func(k string, v int) string {
return fmt.Sprintf("%s=%d", k, v)
})
type Endomorphism ¶ added in v2.0.2
type Endomorphism[A any] = endomorphism.Endomorphism[A]
Endomorphism represents a function from a type to itself (A -> A).
func Clone ¶
func Clone[K comparable, V any](f Endomorphism[V]) Endomorphism[Record[K, V]]
Clone creates a deep copy of a record using the provided endomorphism to clone values.
The endomorphism is applied to each value to create a deep copy. This is useful when values contain pointers or other references that need to be duplicated.
Example:
type Data struct { Value int }
cloneData := func(d Data) Data { return Data{Value: d.Value} }
original := Record[string, Data]{"a": {Value: 1}}
deepCopy := Clone(cloneData)(original)
type Entries ¶ added in v2.0.1
type Entries[K comparable, V any] = []Entry[K, V]
Entries is a slice of key-value pairs.
Example:
entries := Entries[string, int]{
T.MakeTuple2("a", 1),
T.MakeTuple2("b", 2),
}
record := FromEntries(entries)
func ToArray ¶
func ToArray[K comparable, V any](r Record[K, V]) Entries[K, V]
ToArray converts a record to a slice of key-value pairs (entries).
The order of entries is non-deterministic due to Go's map iteration behavior.
Example:
record := Record[string, int]{"a": 1, "b": 2}
entries := ToArray(record)
// entries: []Entry[string, int]{{F1: "a", F2: 1}, {F1: "b", F2: 2}} in any order
func ToEntries ¶
func ToEntries[K comparable, V any](r Record[K, V]) Entries[K, V]
ToEntries converts a record to a slice of key-value pairs (entries).
This is an alias for ToArray, providing semantic clarity when working with entries.
Example:
record := Record[string, int]{"a": 1, "b": 2}
entries := ToEntries(record)
type Entry ¶ added in v2.0.1
type Entry[K comparable, V any] = pair.Pair[K, V]
Entry represents a single key-value pair from a record. This is an alias for Tuple2 to provide semantic clarity.
Example:
entries := ToEntries(record)
for _, entry := range entries {
key := entry.F1
value := entry.F2
}
type Kleisli ¶ added in v2.0.1
type Kleisli[K comparable, V1, V2 any] = func(V1) Record[K, V2]
Kleisli represents a monadic function that transforms a value into a record. Used in chain operations for composing record-producing functions.
Example:
expand := func(x int) Record[string, int] {
return Record[string, int]{
"double": x * 2,
"triple": x * 3,
}
}
func FromArray ¶
func FromArray[ K comparable, V any](m Mg.Magma[V]) Kleisli[K, Entries[K, V], V]
FromArray converts an array of entries to a record.
When duplicate keys occur, the Magma determines how to combine their values. This is useful for aggregating data with the same keys.
Example:
entries := Entries[string, int]{
P.MakePair("a", 1),
P.MakePair("b", 2),
P.MakePair("a", 3),
}
sumMagma := Mg.MakeMagma(func(a, b int) int { return a + b })
toRecord := FromArray(sumMagma)
result := toRecord(entries) // {"a": 4, "b": 2}
func FromFoldable ¶
func FromFoldable[ HKTA any, FOLDABLE ~func(func(Record[K, V], Entry[K, V]) Record[K, V], Record[K, V]) func(HKTA) Record[K, V], K comparable, V any](m Mg.Magma[V], red FOLDABLE) Kleisli[K, HKTA, V]
FromFoldable converts a foldable structure of entries to a record.
The foldable structure should contain Entry[K, V] elements. When duplicate keys occur, the Magma determines how to combine their values.
Example:
entries := []Entry[string, int]{
P.MakePair("a", 1),
P.MakePair("b", 2),
P.MakePair("a", 3),
}
sumMagma := Mg.MakeMagma(func(a, b int) int { return a + b })
toRecord := FromArray(sumMagma)
result := toRecord(entries) // {"a": 4, "b": 2}
type KleisliWithIndex ¶ added in v2.0.1
type KleisliWithIndex[K comparable, V1, V2 any] = func(K, V1) Record[K, V2]
KleisliWithIndex is a monadic function that uses both key and value to produce a record.
Example:
expandWithKey := func(k string, v int) Record[string, int] {
return Record[string, int]{
k + "_double": v * 2,
k + "_triple": v * 3,
}
}
type Monoid ¶ added in v2.0.2
Monoid represents a monoid structure with an associative binary operation and identity element.
func MergeMonoid ¶
func MergeMonoid[K comparable, V any]() Monoid[Record[K, V]]
MergeMonoid computes the union of two maps of the same type giving the last map precedence
func UnionFirstMonoid ¶
func UnionFirstMonoid[K comparable, V any]() Monoid[Record[K, V]]
UnionFirstMonoid computes the union of two maps of the same type giving the first map precedence
func UnionLastMonoid ¶
func UnionLastMonoid[K comparable, V any]() Monoid[Record[K, V]]
UnionLastMonoid computes the union of two maps of the same type giving the last map precedence
func UnionMonoid ¶
func UnionMonoid[K comparable, V any](s S.Semigroup[V]) Monoid[Record[K, V]]
UnionMonoid computes the union of two maps of the same type
type Operator ¶ added in v2.0.1
type Operator[K comparable, V1, V2 any] = func(Record[K, V1]) Record[K, V2]
Operator transforms a record from one value type to another while preserving keys. This is the fundamental transformation type for record operations.
Example:
doubleValues := Map(func(x int) int { return x * 2 })
result := doubleValues(Record[string, int]{"a": 1, "b": 2})
// result: {"a": 2, "b": 4}
func BindTo ¶
func BindTo[S1, T any, K comparable](setter func(T) S1) Operator[K, T, S1]
BindTo initializes a new state [S1] from a value [T]. This is typically used as the first step in a do-notation chain to convert a simple map of values into a map of state objects.
Example:
type State struct {
Name string
}
result := F.Pipe1(
map[string]string{"a": "Alice", "b": "Bob"},
record.BindTo(func(name string) State { return State{Name: name} }),
) // map[string]State{"a": {Name: "Alice"}, "b": {Name: "Bob"}}
func DeleteAt ¶
func DeleteAt[K comparable, V any](k K) Operator[K, V, V]
DeleteAt returns a function that removes a key from a record.
If the key doesn't exist, the record is returned unchanged. The original record is not modified; a new record is returned.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
removeB := DeleteAt[string, int]("b")
result := removeB(record) // {"a": 1, "c": 3}
func Filter ¶
func Filter[K comparable, V any](f Predicate[K]) Operator[K, V, V]
Filter creates a new record with only the entries whose keys match the predicate.
The predicate tests keys only, not values. Use FilterWithIndex to test both.
Example:
record := Record[string, int]{"apple": 1, "banana": 2, "cherry": 3}
startsWithA := Filter[string, int](func(k string) bool {
return strings.HasPrefix(k, "a")
})
result := startsWithA(record) // {"apple": 1}
func FilterMap ¶
func FilterMap[K comparable, V1, V2 any](f option.Kleisli[V1, V2]) Operator[K, V1, V2]
FilterMap filters and transforms a record based on values only.
Similar to FilterMapWithIndex but the transformation function only receives values. Returns Some(value) to keep and transform, None to exclude.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
evenDoubled := FilterMap(func(v int) Option[int] {
if v%2 == 0 {
return O.Some(v * 2)
}
return O.None[int]()
})
result := evenDoubled(record) // {"b": 4}
func FilterMapWithIndex ¶
func FilterMapWithIndex[K comparable, V1, V2 any](f func(K, V1) Option[V2]) Operator[K, V1, V2]
FilterMapWithIndex filters and transforms a record simultaneously.
The transformation function returns Some(value) to keep and transform an entry, or None to exclude it. This combines filtering and mapping in a single pass.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
evenDoubled := FilterMapWithIndex(func(k string, v int) Option[int] {
if v%2 == 0 {
return O.Some(v * 2)
}
return O.None[int]()
})
result := evenDoubled(record) // {"b": 4}
func FilterWithIndex ¶
func FilterWithIndex[K comparable, V any](f PredicateWithIndex[K, V]) Operator[K, V, V]
FilterWithIndex creates a new record with only the entries that match the predicate.
The predicate receives both key and value, allowing filtering based on both.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
evenValues := FilterWithIndex(func(k string, v int) bool {
return v%2 == 0
})
result := evenValues(record) // {"b": 2}
func Flap ¶
func Flap[B any, K comparable, A any](a A) Operator[K, func(A) B, B]
Flap returns a function that applies a value to a record of functions.
This is the curried version of MonadFlap, useful for composition. It's the "flipped" version of Ap where the value is fixed and functions vary.
Example:
funcs := Record[string, func(int) int]{
"double": func(x int) int { return x * 2 },
"triple": func(x int) int { return x * 3 },
}
applyFive := Flap[int, string, int](5)
result := applyFive(funcs) // {"double": 10, "triple": 15}
func Let ¶
func Let[S1, T any, K comparable, S2 any]( setter func(T) func(S1) S2, f func(S1) T, ) Operator[K, S1, S2]
Let attaches the result of a computation to a context [S1] to produce a context [S2]. Unlike Bind, Let does not require a Monoid because it transforms each value independently without merging multiple maps.
The setter function takes the computed value and returns a function that updates the context. The computation function f takes the current context and produces a value.
Example:
type State struct {
Name string
Length int
}
result := F.Pipe2(
map[string]State{"a": {Name: "Alice"}},
record.Let(
func(length int) func(State) State {
return func(s State) State { s.Length = length; return s }
},
func(s State) int { return len(s.Name) },
),
) // map[string]State{"a": {Name: "Alice", Length: 5}}
func LetTo ¶
func LetTo[S1, T any, K comparable, S2 any]( setter func(T) func(S1) S2, b T, ) Operator[K, S1, S2]
LetTo attaches a constant value to a context [S1] to produce a context [S2]. This is similar to Let but uses a fixed value instead of computing it from the context.
The setter function takes the value and returns a function that updates the context.
Example:
type State struct {
Name string
Version int
}
result := F.Pipe2(
map[string]State{"a": {Name: "Alice"}},
record.LetTo(
func(version int) func(State) State {
return func(s State) State { s.Version = version; return s }
},
2,
),
) // map[string]State{"a": {Name: "Alice", Version: 2}}
func Map ¶
func Map[K comparable, V, R any](f func(V) R) Operator[K, V, R]
Map returns a function that transforms each value in a record using the provided function.
This is the Functor map operation for records, creating a new record with transformed values while preserving all keys. This is one of the most commonly used operations.
Example:
record := Record[string, int]{"a": 1, "b": 2, "c": 3}
double := Map(func(v int) int { return v * 2 })
result := double(record) // {"a": 2, "b": 4, "c": 6}
func MapRef ¶
func MapRef[K comparable, V, R any](f func(*V) R) Operator[K, V, R]
MapRef returns a function that transforms each value in a record using the provided function with value references.
More efficient than Map for large value types as it avoids copying values.
Example:
record := Record[string, LargeStruct]{...}
extractSize := MapRef(func(v *LargeStruct) int { return v.Size })
result := extractSize(record)
func MapRefWithIndex ¶
func MapRefWithIndex[K comparable, V, R any](f func(K, *V) R) Operator[K, V, R]
MapRefWithIndex returns a function that transforms each key-value pair in a record using the provided function with value references.
Combines the benefits of MapWithIndex and MapRef for efficient key-aware transformations of large value types.
Example:
record := Record[string, LargeStruct]{...}
transform := MapRefWithIndex(func(k string, v *LargeStruct) int {
return len(k) + v.Size
})
result := transform(record)
func MapWithIndex ¶
func MapWithIndex[K comparable, V, R any](f func(K, V) R) Operator[K, V, R]
MapWithIndex returns a function that transforms each key-value pair in a record using the provided function.
Useful when the transformation depends on both the key and value.
Example:
record := Record[string, int]{"a": 1, "b": 2}
prefixWithKey := MapWithIndex(func(k string, v int) string {
return fmt.Sprintf("%s:%d", k, v)
})
result := prefixWithKey(record) // {"a": "a:1", "b": "b:2"}
func Merge ¶
func Merge[K comparable, V any](right Record[K, V]) Operator[K, V, V]
Merge combines two records, giving precedence to values in the right record for duplicate keys.
This is a simpler alternative to Union that always takes the right value when keys conflict. Also see MergeMonoid for the monoid version.
Example:
r1 := Record[string, int]{"a": 1, "b": 2}
r2 := Record[string, int]{"b": 3, "c": 4}
result := Merge(r2)(r1) // {"a": 1, "b": 3, "c": 4}
func UpsertAt ¶
func UpsertAt[K comparable, V any](k K, v V) Operator[K, V, V]
UpsertAt returns a function that inserts or updates a key-value pair in a record.
If the key exists, its value is updated. If the key doesn't exist, it's added. The original record is not modified; a new record is returned.
Example:
record := Record[string, int]{"a": 1, "b": 2}
addC := UpsertAt("c", 3)
result := addC(record) // {"a": 1, "b": 2, "c": 3}
updateA := UpsertAt("a", 10)
result2 := updateA(record) // {"a": 10, "b": 2}
type OperatorWithIndex ¶ added in v2.0.1
type OperatorWithIndex[K comparable, V1, V2 any] = func(func(K, V1) V2) Operator[K, V1, V2]
OperatorWithIndex transforms a record using both key and value information. Useful when the transformation depends on the key.
Example:
prefixWithKey := MapWithIndex(func(k string, v string) string {
return k + ":" + v
})
type Option ¶ added in v2.0.2
Option represents an optional value that may or may not be present.
func MonadLookup ¶
func MonadLookup[V any, K comparable](m Record[K, V], k K) Option[V]
MonadLookup retrieves the value for a key in a record if it exists.
This is the monadic version of Lookup, taking the record as the first parameter. Returns Some(value) if the key exists, None otherwise.
Example:
record := Record[string, int]{"a": 1, "b": 2}
result := MonadLookup(record, "a") // Some(1)
result2 := MonadLookup(record, "c") // None
type Predicate ¶ added in v2.0.1
Predicate is a function that tests whether a key satisfies a condition. Used in filtering operations to determine which entries to keep.
Example:
isVowel := func(k string) bool {
return strings.ContainsAny(k, "aeiou")
}
type PredicateWithIndex ¶ added in v2.0.1
type PredicateWithIndex[K comparable, V any] = func(K, V) bool
PredicateWithIndex is a function that tests whether a key-value pair satisfies a condition. Used in filtering operations that need access to both key and value.
Example:
isAdult := func(name string, user User) bool {
return user.Age >= 18
}
type Record ¶ added in v2.0.1
type Record[K comparable, V any] = map[K]V
Record represents a map with comparable keys and values of any type. This is the primary data structure for the record package, providing functional operations over Go's native map type.
Example:
type UserRecord = Record[string, User]
users := UserRecord{
"alice": User{Name: "Alice", Age: 30},
"bob": User{Name: "Bob", Age: 25},
}
func ConstNil ¶
func ConstNil[K comparable, V any]() Record[K, V]
ConstNil returns a nil record.
This is useful as a constant function that always returns nil, particularly in functional composition scenarios.
Example:
nilRecord := ConstNil[string, int]() IsNil(nilRecord) // true
func Copy ¶
func Copy[K comparable, V any](m Record[K, V]) Record[K, V]
Copy creates a shallow copy of a record.
The keys and values are copied, but if values are pointers or contain pointers, they will point to the same underlying data. Use Clone for deep copying.
Example:
original := Record[string, int]{"a": 1, "b": 2}
copy := Copy(original)
// Modifying copy doesn't affect original
func Do ¶
func Do[K comparable, S any]() Record[K, S]
Do creates an empty context of type [S] to be used with the Bind operation. This is the starting point for do-notation style composition.
Example:
type State struct {
Name string
Count int
}
result := record.Do[string, State]()
func Empty ¶
func Empty[K comparable, V any]() Record[K, V]
Empty creates an empty record with no entries.
This is useful as an identity element for record operations or as a starting point for building records incrementally.
Example:
empty := Empty[string, int]() IsEmpty(empty) // true
func FromEntries ¶
func FromEntries[K comparable, V any](fa Entries[K, V]) Record[K, V]
FromEntries creates a record from a slice of key-value pairs.
If duplicate keys exist in the slice, the last occurrence wins.
Example:
entries := Entries[string, int]{
P.MakePair("a", 1),
P.MakePair("b", 2),
}
record := FromEntries(entries) // {"a": 1, "b": 2}
func MonadAp ¶
func MonadAp[A any, K comparable, B any](m Monoid[Record[K, B]], fab Record[K, func(A) B], fa Record[K, A]) Record[K, B]
MonadAp applies a record of functions to a record of values, producing a record of results.
This is the applicative apply operation for records. For each matching key in both records, the function is applied to the value. When keys exist in both records, results are combined using the provided Monoid.
Example:
funcs := Record[string, func(int) int]{
"double": func(x int) int { return x * 2 },
"triple": func(x int) int { return x * 3 },
}
values := Record[string, int]{"double": 5, "triple": 7}
result := MonadAp(MergeMonoid[string, int](), funcs, values)
// result: {"double": 10, "triple": 21}
func MonadChain ¶
func MonadChain[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]], r Record[K, V1], f Kleisli[K, V1, V2]) Record[K, V2]
MonadChain chains a record transformation that produces records, combining results using a Monoid.
Similar to MonadChainWithIndex but the transformation function only receives values. This is the monadic bind (flatMap) operation for records.
Example:
record := Record[string, int]{"a": 1, "b": 2}
expand := func(v int) Record[string, int] {
return Record[string, int]{
"double": v * 2,
"triple": v * 3,
}
}
result := MonadChain(MergeMonoid[string, int](), record, expand)
func MonadChainWithIndex ¶
func MonadChainWithIndex[V1 any, K comparable, V2 any](m Monoid[Record[K, V2]], r Record[K, V1], f KleisliWithIndex[K, V1, V2]) Record[K, V2]
MonadChainWithIndex chains a record transformation that produces records, combining results using a Monoid.
This is the monadic bind operation for records. Each value is transformed into a record, and all resulting records are combined using the provided Monoid. The transformation function receives both key and value.
Example:
record := Record[string, int]{"a": 1, "b": 2}
expand := func(k string, v int) Record[string, int] {
return Record[string, int]{
k + "_double": v * 2,
k + "_triple": v * 3,
}
}
result := MonadChainWithIndex(MergeMonoid[string, int](), record, expand)
// result: {"a_double": 2, "a_triple": 3, "b_double": 4, "b_triple": 6}
func MonadFlap ¶
func MonadFlap[B any, K comparable, A any](fab Record[K, func(A) B], a A) Record[K, B]
MonadFlap applies a value to a record of functions, producing a record of results.
This is the monadic version of Flap. Each function in the record is applied to the value, preserving the keys.
Example:
funcs := Record[string, func(int) int]{
"double": func(x int) int { return x * 2 },
"triple": func(x int) int { return x * 3 },
}
result := MonadFlap(funcs, 5)
// result: {"double": 10, "triple": 15}
func MonadMap ¶
func MonadMap[K comparable, V, R any](r Record[K, V], f func(V) R) Record[K, R]
MonadMap transforms each value in a record using the provided function.
This is the monadic version of Map, taking the record as the first parameter. Useful for method chaining or when the record is already available.
Example:
record := Record[string, int]{"a": 1, "b": 2}
result := MonadMap(record, func(v int) int { return v * 2 })
// result: {"a": 2, "b": 4}
func MonadMapRef ¶
func MonadMapRef[K comparable, V, R any](r Record[K, V], f func(*V) R) Record[K, R]
MonadMapRef transforms each value in a record using the provided function with value references.
This is the monadic version of MapRef, useful for efficient processing of large value types.
Example:
record := Record[string, LargeStruct]{...}
result := MonadMapRef(record, func(v *LargeStruct) int {
return v.Size
})
func MonadMapRefWithIndex ¶
func MonadMapRefWithIndex[K comparable, V, R any](r Record[K, V], f func(K, *V) R) Record[K, R]
MonadMapRefWithIndex transforms each key-value pair in a record using the provided function with value references.
Combines MonadMapWithIndex with reference passing for efficient processing of large values.
Example:
record := Record[string, LargeStruct]{...}
result := MonadMapRefWithIndex(record, func(k string, v *LargeStruct) int {
return len(k) + v.Size
})
func MonadMapWithIndex ¶
func MonadMapWithIndex[K comparable, V, R any](r Record[K, V], f func(K, V) R) Record[K, R]
MonadMapWithIndex transforms each key-value pair in a record using the provided function.
This is the monadic version of MapWithIndex, taking the record as the first parameter.
Example:
record := Record[string, int]{"a": 1, "b": 2}
result := MonadMapWithIndex(record, func(k string, v int) string {
return fmt.Sprintf("%s=%d", k, v)
})
// result: {"a": "a=1", "b": "b=2"}
func Of ¶ added in v2.0.1
func Of[K comparable, A any](k K, a A) Record[K, A]
Of creates a record with a single key-value pair.
This is the pointed functor operation for records, lifting a value into the record context. It's an alias for Singleton but follows the standard functional programming naming convention.
Example:
record := Of("key", 42)
// record: {"key": 42}
func Singleton ¶
func Singleton[K comparable, V any](k K, v V) Record[K, V]
Singleton creates a new record with a single key-value pair.
This is useful for creating records with one entry or as a building block for more complex record operations.
Example:
record := Singleton("key", 42)
// record: {"key": 42}
type Reducer ¶ added in v2.0.1
type Reducer[V, R any] = func(R, V) R
Reducer accumulates values from a record into a single result. The function receives the accumulator and current value, returning the new accumulator.
Example:
sum := Reduce(func(acc int, v int) int {
return acc + v
}, 0)
type ReducerWithIndex ¶ added in v2.0.1
type ReducerWithIndex[K comparable, V, R any] = func(K, R, V) R
ReducerWithIndex accumulates values using both key and value information.
Example:
weightedSum := ReduceWithIndex(func(k string, acc int, v int) int {
weight := len(k)
return acc + (v * weight)
}, 0)
type Semigroup ¶ added in v2.0.2
Semigroup represents a semigroup structure with an associative binary operation.
func UnionFirstSemigroup ¶
func UnionFirstSemigroup[K comparable, V any]() Semigroup[Record[K, V]]
UnionFirstSemigroup creates a semigroup for maps where the first (left) value wins when the same key exists in both maps being concatenated.
This is useful when you want to preserve original values and ignore updates for keys that already exist.
When concatenating two maps:
- Keys that exist in only one map are included in the result
- Keys that exist in both maps keep the value from the first (left) map
Example:
semigroup := UnionFirstSemigroup[string, int]()
map1 := map[string]int{"a": 1, "b": 2}
map2 := map[string]int{"b": 3, "c": 4}
result := semigroup.Concat(map1, map2)
// result: {"a": 1, "b": 2, "c": 4} // b keeps value from map1 (first wins)
This is useful for:
- Default values (defaults are set first, user values don't override)
- Caching (first cached value is kept, subsequent updates ignored)
- Immutable registries (first registration wins, duplicates are ignored)
func UnionLastSemigroup ¶
func UnionLastSemigroup[K comparable, V any]() Semigroup[Record[K, V]]
UnionLastSemigroup creates a semigroup for maps where the last (right) value wins when the same key exists in both maps being concatenated.
This is the most common conflict resolution strategy and is equivalent to using the standard map merge operation where right-side values take precedence.
When concatenating two maps:
- Keys that exist in only one map are included in the result
- Keys that exist in both maps take the value from the second (right) map
Example:
semigroup := UnionLastSemigroup[string, int]()
map1 := map[string]int{"a": 1, "b": 2}
map2 := map[string]int{"b": 3, "c": 4}
result := semigroup.Concat(map1, map2)
// result: {"a": 1, "b": 3, "c": 4} // b takes value from map2 (last wins)
This is useful for:
- Configuration overrides (later configs override earlier ones)
- Applying updates to a base map
- Merging user preferences where newer values should win
func UnionSemigroup ¶
func UnionSemigroup[K comparable, V any](s Semigroup[V]) Semigroup[Record[K, V]]
UnionSemigroup creates a semigroup for maps that combines two maps using the provided semigroup for resolving conflicts when the same key exists in both maps.
When concatenating two maps:
- Keys that exist in only one map are included in the result
- Keys that exist in both maps have their values combined using the provided semigroup
This is useful when you want custom conflict resolution logic beyond simple "first wins" or "last wins" semantics.
Example:
// Create a semigroup that sums values for duplicate keys
sumSemigroup := number.SemigroupSum[int]()
mapSemigroup := UnionSemigroup[string, int](sumSemigroup)
map1 := map[string]int{"a": 1, "b": 2}
map2 := map[string]int{"b": 3, "c": 4}
result := mapSemigroup.Concat(map1, map2)
// result: {"a": 1, "b": 5, "c": 4} // b values are summed: 2 + 3 = 5
Example with string concatenation:
stringSemigroup := string.Semigroup
mapSemigroup := UnionSemigroup[string, string](stringSemigroup)
map1 := map[string]string{"a": "Hello", "b": "World"}
map2 := map[string]string{"b": "!", "c": "Goodbye"}
result := mapSemigroup.Concat(map1, map2)
// result: {"a": "Hello", "b": "World!", "c": "Goodbye"}