Documentation
¶
Overview ¶
Package array provides functional programming utilities for working with Go slices.
This package treats Go slices as immutable arrays and provides a rich set of operations for transforming, filtering, folding, and combining arrays in a functional style. All operations return new arrays rather than modifying existing ones.
Core Concepts ¶
The array package implements several functional programming abstractions:
- Functor: Transform array elements with Map
- Applicative: Apply functions in arrays to values in arrays
- Monad: Chain operations that produce arrays with Chain/FlatMap
- Foldable: Reduce arrays to single values with Reduce/Fold
- Traversable: Transform arrays while preserving structure
Basic Operations ¶
// Creating arrays
arr := array.From(1, 2, 3, 4, 5)
repeated := array.Replicate(3, "hello")
generated := array.MakeBy(5, func(i int) int { return i * 2 })
// Transforming arrays
doubled := array.Map(N.Mul(2))(arr)
filtered := array.Filter(func(x int) bool { return x > 2 })(arr)
// Combining arrays
combined := array.Flatten([][]int{{1, 2}, {3, 4}})
zipped := array.Zip([]string{"a", "b"})([]int{1, 2})
Mapping and Filtering ¶
Transform array elements with Map, or filter elements with Filter:
numbers := []int{1, 2, 3, 4, 5}
// Map transforms each element
doubled := array.Map(N.Mul(2))(numbers)
// Result: [2, 4, 6, 8, 10]
// Filter keeps elements matching a predicate
evens := array.Filter(func(x int) bool { return x%2 == 0 })(numbers)
// Result: [2, 4]
// FilterMap combines both operations
import "github.com/IBM/fp-go/v2/option"
result := array.FilterMap(func(x int) option.Option[int] {
if x%2 == 0 {
return option.Some(x * 2)
}
return option.None[int]()
})(numbers)
// Result: [4, 8]
Folding and Reducing ¶
Reduce arrays to single values:
numbers := []int{1, 2, 3, 4, 5}
// Sum all elements
sum := array.Reduce(func(acc, x int) int { return acc + x }, 0)(numbers)
// Result: 15
// Using a Monoid
import "github.com/IBM/fp-go/v2/monoid"
sum := array.Fold(monoid.MonoidSum[int]())(numbers)
// Result: 15
Chaining Operations ¶
Chain operations that produce arrays (also known as FlatMap):
numbers := []int{1, 2, 3}
result := array.Chain(func(x int) []int {
return []int{x, x * 10}
})(numbers)
// Result: [1, 10, 2, 20, 3, 30]
Finding Elements ¶
Search for elements matching predicates:
numbers := []int{1, 2, 3, 4, 5}
// Find first element > 3
first := array.FindFirst(func(x int) bool { return x > 3 })(numbers)
// Result: Some(4)
// Find last element > 3
last := array.FindLast(func(x int) bool { return x > 3 })(numbers)
// Result: Some(5)
// Get head and tail
head := array.Head(numbers) // Some(1)
tail := array.Tail(numbers) // Some([2, 3, 4, 5])
Sorting ¶
Sort arrays using Ord instances:
import "github.com/IBM/fp-go/v2/ord"
numbers := []int{3, 1, 4, 1, 5}
sorted := array.Sort(ord.FromStrictCompare[int]())(numbers)
// Result: [1, 1, 3, 4, 5]
// Sort by extracted key
type Person struct { Name string; Age int }
people := []Person{{"Alice", 30}, {"Bob", 25}}
byAge := array.SortByKey(ord.FromStrictCompare[int](), func(p Person) int {
return p.Age
})(people)
Uniqueness ¶
Remove duplicate elements:
numbers := []int{1, 2, 2, 3, 3, 3}
unique := array.StrictUniq(numbers)
// Result: [1, 2, 3]
// Unique by key
type Person struct { Name string; Age int }
people := []Person{{"Alice", 30}, {"Bob", 25}, {"Alice", 35}}
uniqueByName := array.Uniq(func(p Person) string { return p.Name })(people)
// Result: [{"Alice", 30}, {"Bob", 25}]
Zipping ¶
Combine multiple arrays:
names := []string{"Alice", "Bob", "Charlie"}
ages := []int{30, 25, 35}
// Zip into tuples
pairs := array.Zip(ages)(names)
// Result: [(Alice, 30), (Bob, 25), (Charlie, 35)]
// Zip with custom function
result := array.ZipWith(names, ages, func(name string, age int) string {
return fmt.Sprintf("%s is %d", name, age)
})
Monadic Do Notation ¶
Build complex array computations using do-notation style:
result := array.Do(
struct{ X, Y int }{},
)(
array.Bind(
func(x int) func(s struct{}) struct{ X int } {
return func(s struct{}) struct{ X int } { return struct{ X int }{x} }
},
func(s struct{}) []int { return []int{1, 2, 3} },
),
array.Bind(
func(y int) func(s struct{ X int }) struct{ X, Y int } {
return func(s struct{ X int }) struct{ X, Y int } {
return struct{ X, Y int }{s.X, y}
}
},
func(s struct{ X int }) []int { return []int{4, 5} },
),
)
// Produces all combinations: [{1,4}, {1,5}, {2,4}, {2,5}, {3,4}, {3,5}]
Sequence and Traverse ¶
Transform arrays of effects into effects of arrays:
import "github.com/IBM/fp-go/v2/option"
// Sequence: []Option[A] -> Option[[]A]
opts := []option.Option[int]{
option.Some(1),
option.Some(2),
option.Some(3),
}
result := array.ArrayOption[int]()(opts)
// Result: Some([1, 2, 3])
// If any is None, result is None
opts2 := []option.Option[int]{
option.Some(1),
option.None[int](),
option.Some(3),
}
result2 := array.ArrayOption[int]()(opts2)
// Result: None
Equality and Comparison ¶
Compare arrays for equality:
import "github.com/IBM/fp-go/v2/eq"
eq := array.Eq(eq.FromStrictEquals[int]())
equal := eq.Equals([]int{1, 2, 3}, []int{1, 2, 3})
// Result: true
Monoid Operations ¶
Combine arrays using monoid operations:
import "github.com/IBM/fp-go/v2/monoid"
// Concatenate arrays
m := array.Monoid[int]()
result := m.Concat([]int{1, 2}, []int{3, 4})
// Result: [1, 2, 3, 4]
// Concatenate multiple arrays efficiently
result := array.ArrayConcatAll(
[]int{1, 2},
[]int{3, 4},
[]int{5, 6},
)
// Result: [1, 2, 3, 4, 5, 6]
Performance Considerations ¶
Most operations create new arrays rather than modifying existing ones. For performance-critical code, consider:
- Using Copy for shallow copies when needed
- Using Clone with a custom cloning function for deep copies
- Batching operations to minimize intermediate allocations
- Using ArrayConcatAll for efficient concatenation of multiple arrays
Subpackages ¶
- array/generic: Generic implementations for custom array-like types
- array/nonempty: Operations for non-empty arrays with compile-time guarantees
- array/testing: Testing utilities for array laws and properties
Example (Any) ¶
pred := func(val int) bool {
return val&2 == 0
}
data1 := From(1, 2, 3)
fmt.Println(Any(pred)(data1))
Output: true
Example (Any_filter) ¶
pred := func(val int) bool {
return val&2 == 0
}
data1 := From(1, 2, 3)
// Any tests if any of the entries in the array matches the condition
Any := F.Flow2(
Filter(pred),
IsNonEmpty[int],
)
fmt.Println(Any(data1))
Output: true
Example (Any_find) ¶
pred := func(val int) bool {
return val&2 == 0
}
data1 := From(1, 2, 3)
// Any tests if any of the entries in the array matches the condition
Any := F.Flow2(
FindFirst(pred),
O.IsSome[int],
)
fmt.Println(Any(data1))
Output: true
Example (Basic) ¶
Example_basic adapts examples from [https://github.com/inato/fp-ts-cheatsheet#basic-manipulation]
someArray := From(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) // []int
isEven := func(num int) bool {
return num%2 == 0
}
square := func(num int) int {
return num * num
}
// filter and map
result := F.Pipe2(
someArray,
Filter(isEven),
Map(square),
) // [0 4 16 36 64]
// or in one go with filterMap
resultFilterMap := F.Pipe1(
someArray,
FilterMap(
F.Flow2(O.FromPredicate(isEven), O.Map(square)),
),
)
fmt.Println(result)
fmt.Println(resultFilterMap)
Output: [0 4 16 36 64] [0 4 16 36 64]
Example (Find) ¶
pred := func(val int) bool {
return val&2 == 0
}
data1 := From(1, 2, 3)
fmt.Println(FindFirst(pred)(data1))
Output: Some[int](1)
Example (Find_filter) ¶
pred := func(val int) bool {
return val&2 == 0
}
data1 := From(1, 2, 3)
Find := F.Flow2(
Filter(pred),
Head[int],
)
fmt.Println(Find(data1))
Output: Some[int](1)
Example (Sort) ¶
Example_sort adapts examples from [https://github.com/inato/fp-ts-cheatsheet#sort-elements-with-ord]
package main
import (
"fmt"
F "github.com/IBM/fp-go/v2/function"
I "github.com/IBM/fp-go/v2/number/integer"
O "github.com/IBM/fp-go/v2/option"
"github.com/IBM/fp-go/v2/ord"
S "github.com/IBM/fp-go/v2/string"
)
type user struct {
name string
age O.Option[int]
}
func (user user) GetName() string {
return user.name
}
func (user user) GetAge() O.Option[int] {
return user.age
}
// Example_sort adapts examples from [https://github.com/inato/fp-ts-cheatsheet#sort-elements-with-ord]
func main() {
strings := From("zyx", "abc", "klm")
sortedStrings := F.Pipe1(
strings,
Sort(S.Ord),
) // => ['abc', 'klm', 'zyx']
// reverse sort
reverseSortedStrings := F.Pipe1(
strings,
Sort(ord.Reverse(S.Ord)),
) // => ['zyx', 'klm', 'abc']
// sort Option
optionalNumbers := From(O.Some(1337), O.None[int](), O.Some(42))
sortedNums := F.Pipe1(
optionalNumbers,
Sort(O.Ord(I.Ord)),
)
// complex object with different rules
byName := F.Pipe1(
S.Ord,
ord.Contramap(user.GetName),
) // ord.Ord[user]
byAge := F.Pipe1(
O.Ord(I.Ord),
ord.Contramap(user.GetAge),
) // ord.Ord[user]
sortedUsers := F.Pipe1(
From(user{name: "a", age: O.Of(30)}, user{name: "d", age: O.Of(10)}, user{name: "c"}, user{name: "b", age: O.Of(10)}),
SortBy(From(byAge, byName)),
)
fmt.Println(sortedStrings)
fmt.Println(reverseSortedStrings)
fmt.Println(sortedNums)
fmt.Println(sortedUsers)
}
Output: [abc klm zyx] [zyx klm abc] [None[int] Some[int](42) Some[int](1337)] [{c {0 false}} {b {10 true}} {d {10 true}} {a {30 true}}]
Index ¶
- func Any[A any](pred func(A) bool) func([]A) bool
- func AnyWithIndex[A any](pred func(int, A) bool) func([]A) bool
- func Append[A any](as []A, a A) []A
- func ArrayConcatAll[A any](data ...[]A) []A
- func ConcatAll[A any](m M.Monoid[A]) func([]A) A
- func ConstNil[A any]() []A
- func Copy[A any](b []A) []A
- func Do[S any](empty S) []S
- func Empty[A any]() []A
- func Eq[T any](e E.Eq[T]) E.Eq[[]T]
- func Extract[A any](as []A) A
- func FindFirst[A any](pred func(A) bool) option.Kleisli[[]A, A]
- func FindFirstMap[A, B any](sel option.Kleisli[A, B]) option.Kleisli[[]A, B]
- func FindFirstMapWithIndex[A, B any](sel func(int, A) Option[B]) option.Kleisli[[]A, B]
- func FindFirstWithIndex[A any](pred func(int, A) bool) option.Kleisli[[]A, A]
- func FindLast[A any](pred func(A) bool) option.Kleisli[[]A, A]
- func FindLastMap[A, B any](sel option.Kleisli[A, B]) option.Kleisli[[]A, B]
- func FindLastMapWithIndex[A, B any](sel func(int, A) Option[B]) option.Kleisli[[]A, B]
- func FindLastWithIndex[A any](pred func(int, A) bool) option.Kleisli[[]A, A]
- func Flatten[A any](mma [][]A) []A
- func Fold[A any](m M.Monoid[A]) func([]A) A
- func FoldMap[A, B any](m M.Monoid[B]) func(func(A) B) func([]A) B
- func FoldMapWithIndex[A, B any](m M.Monoid[B]) func(func(int, A) B) func([]A) B
- func From[A any](data ...A) []A
- func Intercalate[A any](m M.Monoid[A]) func(A) func([]A) A
- func IsEmpty[A any](as []A) bool
- func IsNil[A any](as []A) bool
- func IsNonEmpty[A any](as []A) bool
- func IsNonNil[A any](as []A) bool
- func Lookup[A any](idx int) func([]A) Option[A]
- func MakeBy[F ~func(int) A, A any](n int, f F) []A
- func MakeTraverseType[A, B, HKT_F_B, HKT_F_T_B, HKT_F_B_T_B any]() traversable.TraverseType[A, B, []A, []B, HKT_F_B, HKT_F_T_B, HKT_F_B_T_B]
- func Match[A, B any](onEmpty func() B, onNonEmpty func([]A) B) func([]A) B
- func MatchLeft[A, B any](onEmpty func() B, onNonEmpty func(A, []A) B) func([]A) B
- func Monad[A, B any]() monad.Monad[A, B, []A, []B, []func(A) B]
- func MonadAp[B, A any](fab []func(A) B, fa []A) []B
- func MonadChain[A, B any](fa []A, f Kleisli[A, B]) []B
- func MonadFilterMap[A, B any](fa []A, f option.Kleisli[A, B]) []B
- func MonadFilterMapWithIndex[A, B any](fa []A, f func(int, A) Option[B]) []B
- func MonadFlap[B, A any](fab []func(A) B, a A) []B
- func MonadMap[A, B any](as []A, f func(A) B) []B
- func MonadMapRef[A, B any](as []A, f func(*A) B) []B
- func MonadPartition[A any](as []A, pred func(A) bool) pair.Pair[[]A, []A]
- func MonadReduce[A, B any](fa []A, f func(B, A) B, initial B) B
- func MonadReduceWithIndex[A, B any](fa []A, f func(int, B, A) B, initial B) B
- func MonadSequence[HKTA, HKTRA any](fof func(HKTA) HKTRA, m M.Monoid[HKTRA], ma []HKTA) HKTRA
- func MonadTraverse[A, B, HKTB, HKTAB, HKTRB any](fof pointed.OfType[[]B, HKTRB], ...) HKTRB
- func MonadTraverseWithIndex[A, B, HKTB, HKTAB, HKTRB any](fof pointed.OfType[[]B, HKTRB], ...) HKTRB
- func Monoid[T any]() M.Monoid[[]T]
- func Of[A any](a A) []A
- func Partition[A any](pred func(A) bool) func([]A) pair.Pair[[]A, []A]
- func Reduce[A, B any](f func(B, A) B, initial B) func([]A) B
- func ReduceRef[A, B any](f func(B, *A) B, initial B) func([]A) B
- func ReduceRight[A, B any](f func(A, B) B, initial B) func([]A) B
- func ReduceRightWithIndex[A, B any](f func(int, A, B) B, initial B) func([]A) B
- func ReduceWithIndex[A, B any](f func(int, B, A) B, initial B) func([]A) B
- func Replicate[A any](n int, a A) []A
- func Reverse[A any](as []A) []A
- func Semigroup[T any]() S.Semigroup[[]T]
- func Sequence[HKTA, HKTRA any](fof func(HKTA) HKTRA, m M.Monoid[HKTRA]) func([]HKTA) HKTRA
- func Size[A any](as []A) int
- func StrictEquals[T comparable]() E.Eq[[]T]
- func StrictUniq[A comparable](as []A) []A
- func Traverse[A, B, HKTB, HKTAB, HKTRB any](fof pointed.OfType[[]B, HKTRB], ...) func([]A) HKTRB
- func TraverseWithIndex[A, B, HKTB, HKTAB, HKTRB any](fof pointed.OfType[[]B, HKTRB], ...) func([]A) HKTRB
- func Unzip[A, B any](cs []pair.Pair[A, B]) pair.Pair[[]A, []B]
- func Zero[A any]() []A
- func Zip[A, B any](fb []B) func([]A) []pair.Pair[A, B]
- func ZipWith[FCT ~func(A, B) C, A, B, C any](fa []A, fb []B, f FCT) []C
- type Kleisli
- type Operator
- func Ap[B, A any](fa []A) Operator[func(A) B, B]
- func ApS[S1, S2, T any](setter func(T) func(S1) S2, fa []T) Operator[S1, S2]
- func Bind[S1, S2, T any](setter func(T) func(S1) S2, f Kleisli[S1, T]) Operator[S1, S2]
- func BindTo[S1, T any](setter func(T) S1) Operator[T, S1]
- func Chain[A, B any](f Kleisli[A, B]) Operator[A, B]
- func ChainOptionK[A, B any](f option.Kleisli[A, []B]) Operator[A, B]
- func Clone[A any](f func(A) A) Operator[A, A]
- func Concat[A any](suffix []A) Operator[A, A]
- func Extend[A, B any](f func([]A) B) Operator[A, B]
- func Filter[A any](pred func(A) bool) Operator[A, A]
- func FilterMap[A, B any](f option.Kleisli[A, B]) Operator[A, B]
- func FilterMapRef[A, B any](pred func(a *A) bool, f func(*A) B) Operator[A, B]
- func FilterMapWithIndex[A, B any](f func(int, A) Option[B]) Operator[A, B]
- func FilterRef[A any](pred func(*A) bool) Operator[A, A]
- func FilterWithIndex[A any](pred func(int, A) bool) Operator[A, A]
- func Flap[B, A any](a A) Operator[func(A) B, B]
- func Intersperse[A any](middle A) Operator[A, A]
- func Let[S1, S2, T any](setter func(T) func(S1) S2, f func(S1) T) Operator[S1, S2]
- func LetTo[S1, S2, T any](setter func(T) func(S1) S2, b T) Operator[S1, S2]
- func Map[A, B any](f func(A) B) Operator[A, B]
- func MapRef[A, B any](f func(*A) B) Operator[A, B]
- func MapWithIndex[A, B any](f func(int, A) B) Operator[A, B]
- func Prepend[A any](head A) Operator[A, A]
- func PrependAll[A any](middle A) Operator[A, A]
- func Push[A any](a A) Operator[A, A]
- func Slice[A any](low, high int) Operator[A, A]
- func SliceRight[A any](start int) Operator[A, A]
- func Sort[T any](ord O.Ord[T]) Operator[T, T]
- func SortBy[T any](ord []O.Ord[T]) Operator[T, T]
- func SortByKey[K, T any](ord O.Ord[K], f func(T) K) Operator[T, T]
- func Uniq[A any, K comparable](f func(A) K) Operator[A, A]
- func UpsertAt[A any](a A) Operator[A, A]
- type Option
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Any ¶
Any tests if any of the elements in the array matches the predicate. Returns true if at least one element satisfies the predicate, false otherwise. Returns false for an empty array.
Example:
hasEven := array.Any(func(x int) bool { return x%2 == 0 })
result := hasEven([]int{1, 3, 4, 5}) // true
func AnyWithIndex ¶
AnyWithIndex tests if any of the elements in the array matches the predicate. The predicate receives both the index and the element. Returns true if at least one element satisfies the predicate, false otherwise.
Example:
hasEvenAtEvenIndex := array.AnyWithIndex(func(i, x int) bool {
return i%2 == 0 && x%2 == 0
})
result := hasEvenAtEvenIndex([]int{1, 3, 4, 5}) // true (4 is at index 2)
func Append ¶
func Append[A any](as []A, a A) []A
Append adds an element to the end of an array, returning a new array. This is a non-curried version that takes both the array and element as parameters.
Example:
arr := []int{1, 2, 3}
result := array.Append(arr, 4)
// result: []int{1, 2, 3, 4}
// arr: []int{1, 2, 3} (unchanged)
For a curried version, see Push.
func ArrayConcatAll ¶
func ArrayConcatAll[A any](data ...[]A) []A
ArrayConcatAll efficiently concatenates multiple arrays into a single array. This function pre-allocates the exact amount of memory needed and performs a single copy operation for each input array, making it more efficient than repeated concatenations.
Example:
result := array.ArrayConcatAll(
[]int{1, 2},
[]int{3, 4},
[]int{5, 6},
) // [1, 2, 3, 4, 5, 6]
func ConcatAll ¶
ConcatAll concatenates all elements of an array using the provided Monoid. This reduces the array to a single value by repeatedly applying the Monoid's concat operation.
Example:
import "github.com/IBM/fp-go/v2/monoid"
// Sum all numbers
sumAll := array.ConcatAll(monoid.MonoidSum[int]())
result := sumAll([]int{1, 2, 3, 4, 5}) // 15
// Concatenate all strings
concatStrings := array.ConcatAll(monoid.MonoidString())
result2 := concatStrings([]string{"Hello", " ", "World"}) // "Hello World"
func ConstNil ¶
func ConstNil[A any]() []A
ConstNil returns a nil array.
Type Parameters ¶
- A: The type of elements in the array
Returns ¶
- A nil array of type A
func Copy ¶
func Copy[A any](b []A) []A
Copy creates a shallow copy of the array.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- b: The array to copy
Returns ¶
- A new array with the same elements
func Do ¶
func Do[S any]( empty S, ) []S
Do creates an empty context of type S to be used with the Bind operation. This is the starting point for monadic do-notation style computations.
Example:
type State struct {
X int
Y int
}
result := array.Do(State{})
func Eq ¶
Eq creates an equality checker for arrays given an equality checker for elements. Two arrays are considered equal if they have the same length and all corresponding elements are equal according to the provided Eq instance.
Example:
import "github.com/IBM/fp-go/v2/eq"
intArrayEq := array.Eq(eq.FromStrictEquals[int]())
result := intArrayEq.Equals([]int{1, 2, 3}, []int{1, 2, 3}) // true
result2 := intArrayEq.Equals([]int{1, 2, 3}, []int{1, 2, 4}) // false
func Extract ¶ added in v2.1.7
func Extract[A any](as []A) A
Extract returns the first element of an array, or a zero value if empty. This is the comonad extract operation for arrays.
Extract is the dual of the monadic return/of operation. While Of wraps a value in a context, Extract unwraps a value from its context.
Type Parameters:
- A: The type of elements in the array
Parameters:
- as: The input array
Returns:
- The first element if the array is non-empty, otherwise the zero value of type A
Behavior:
- Returns as[0] if the array has at least one element
- Returns the zero value of A if the array is empty
- Does not modify the input array
Example:
result := array.Extract([]int{1, 2, 3})
// result: 1
Example with empty array:
result := array.Extract([]int{})
// result: 0 (zero value for int)
Example with strings:
result := array.Extract([]string{"hello", "world"})
// result: "hello"
Example with empty string array:
result := array.Extract([]string{})
// result: "" (zero value for string)
Use cases:
- Extracting the current focus from a comonadic context
- Getting the head element with a default zero value
- Implementing comonad-based computations
Comonad laws:
- Extract ∘ Of == Identity (extracting from a singleton returns the value)
- Extract ∘ Extend(f) == f (extract after extend equals applying f)
Note: For a safer alternative that handles empty arrays explicitly, consider using Head which returns an Option[A].
func FindFirst ¶
FindFirst finds the first element which satisfies a predicate function. Returns Some(element) if found, None if no element matches.
Example:
findGreaterThan3 := array.FindFirst(func(x int) bool { return x > 3 })
result := findGreaterThan3([]int{1, 2, 4, 5}) // Some(4)
result2 := findGreaterThan3([]int{1, 2, 3}) // None
func FindFirstMap ¶
FindFirstMap finds the first element for which the selector function returns Some. This combines finding and mapping in a single operation.
Example:
import "strconv"
parseFirst := array.FindFirstMap(func(s string) option.Option[int] {
if n, err := strconv.Atoi(s); err == nil {
return option.Some(n)
}
return option.None[int]()
})
result := parseFirst([]string{"a", "42", "b"}) // Some(42)
func FindFirstMapWithIndex ¶
FindFirstMapWithIndex finds the first element for which the selector function returns Some. The selector receives both the index and the element.
func FindFirstWithIndex ¶
FindFirstWithIndex finds the first element which satisfies a predicate function that also receives the index. Returns Some(element) if found, None if no element matches.
Example:
findEvenAtEvenIndex := array.FindFirstWithIndex(func(i, x int) bool {
return i%2 == 0 && x%2 == 0
})
result := findEvenAtEvenIndex([]int{1, 3, 4, 5}) // Some(4)
func FindLast ¶
FindLast finds the last element which satisfies a predicate function. Returns Some(element) if found, None if no element matches.
Example:
findGreaterThan3 := array.FindLast(func(x int) bool { return x > 3 })
result := findGreaterThan3([]int{1, 4, 2, 5}) // Some(5)
func FindLastMap ¶
FindLastMap finds the last element for which the selector function returns Some. This combines finding and mapping in a single operation, searching from the end.
func FindLastMapWithIndex ¶
FindLastMapWithIndex finds the last element for which the selector function returns Some. The selector receives both the index and the element, searching from the end.
func FindLastWithIndex ¶
FindLastWithIndex finds the last element which satisfies a predicate function that also receives the index. Returns Some(element) if found, None if no element matches.
func Flatten ¶
func Flatten[A any](mma [][]A) []A
Flatten converts a nested array into a flat array by concatenating all inner arrays.
Type Parameters ¶
- A: The type of elements in the inner arrays
Parameters ¶
- mma: A nested array (array of arrays)
Returns ¶
- A flat array containing all elements from all inner arrays
Example ¶
result := array.Flatten([][]int{{1, 2}, {3, 4}, {5}})
// result: []int{1, 2, 3, 4, 5}
func Fold ¶
Fold folds the array using the provided Monoid.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- m: The Monoid to use for folding
Returns ¶
- A function that folds an array to a single value
func FoldMap ¶
FoldMap maps and folds an array. Maps each value using the iterating function, then folds the results using the provided Monoid.
Type Parameters ¶
- A: The type of elements in the input array
- B: The type of elements after mapping
Parameters ¶
- m: The Monoid to use for folding
Returns ¶
- A curried function that takes a mapping function and returns a function that folds an array
Example ¶
src := From("a", "b", "c")
fold := FoldMap[string](S.Monoid)(strings.ToUpper)
fmt.Println(fold(src))
Output: ABC
func FoldMapWithIndex ¶
FoldMapWithIndex maps and folds an array with access to indices. Maps each value using the iterating function, then folds the results using the provided Monoid.
Type Parameters ¶
- A: The type of elements in the input array
- B: The type of elements after mapping
Parameters ¶
- m: The Monoid to use for folding
Returns ¶
- A curried function that takes a mapping function and returns a function that folds an array
func From ¶
func From[A any](data ...A) []A
From constructs an array from a set of variadic arguments.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- data: Variadic arguments to include in the array
Returns ¶
- A new array containing all provided arguments
Example ¶
arr := array.From(1, 2, 3, 4, 5)
// arr: []int{1, 2, 3, 4, 5}
func Intercalate ¶
Intercalate inserts a separator between elements and concatenates them using a Monoid.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- m: The Monoid to use for concatenation
Returns ¶
- A curried function that takes a separator and returns a function that reduces an array
func IsEmpty ¶
IsEmpty checks if an array has no elements.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- as: The array to check
Returns ¶
- true if the array is empty, false otherwise
func IsNil ¶
IsNil checks if the array is set to nil.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- as: The array to check
Returns ¶
- true if the array is nil, false otherwise
func IsNonEmpty ¶
IsNonEmpty checks if an array has at least one element.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- as: The array to check
Returns ¶
- true if the array has at least one element, false otherwise
func IsNonNil ¶
IsNonNil checks if the array is not nil.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- as: The array to check
Returns ¶
- true if the array is not nil, false otherwise
func Lookup ¶
Lookup returns the element at the specified index, wrapped in an Option. Returns None if the index is out of bounds.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- idx: The index to look up
Returns ¶
- A function that retrieves an element at the given index, wrapped in an Option
Example ¶
getSecond := array.Lookup[int](1)
result := getSecond([]int{10, 20, 30})
// result: option.Some(20)
func MakeBy ¶
MakeBy returns an array of length n with element i initialized with f(i).
Type Parameters ¶
- F: Function type that takes an int and returns A
- A: The type of elements in the array
Parameters ¶
- n: The length of the array to create
- f: Function to generate each element based on its index
Returns ¶
- A new array where element at index i equals f(i)
Example ¶
squares := array.MakeBy(5, func(i int) int { return i * i })
// squares: []int{0, 1, 4, 9, 16}
func MakeTraverseType ¶ added in v2.1.13
func MakeTraverseType[A, B, HKT_F_B, HKT_F_T_B, HKT_F_B_T_B any]() traversable.TraverseType[A, B, []A, []B, HKT_F_B, HKT_F_T_B, HKT_F_B_T_B]
func Match ¶
func Match[A, B any](onEmpty func() B, onNonEmpty func([]A) B) func([]A) B
Match performs pattern matching on an array, calling onEmpty if empty or onNonEmpty if not.
func MatchLeft ¶
func MatchLeft[A, B any](onEmpty func() B, onNonEmpty func(A, []A) B) func([]A) B
MatchLeft performs pattern matching on an array, calling onEmpty if empty or onNonEmpty with head and tail if not.
func Monad ¶
Monad returns the monadic operations for an array. This provides a structured way to access all monad operations (Map, Chain, Ap, Of) for arrays in a single interface.
The Monad interface is useful when you need to pass monadic operations as parameters or when working with generic code that operates on any monad.
Example:
m := array.Monad[int, string]()
result := m.Chain([]int{1, 2, 3}, func(x int) []string {
return []string{fmt.Sprintf("%d", x), fmt.Sprintf("%d!", x)}
})
// Result: ["1", "1!", "2", "2!", "3", "3!"]
func MonadAp ¶
func MonadAp[B, A any](fab []func(A) B, fa []A) []B
MonadAp applies an array of functions to an array of values, producing all combinations. This is the monadic version that takes both arrays as parameters.
func MonadChain ¶
MonadChain applies a function that returns an array to each element and flattens the results. This is the monadic version that takes the array as the first parameter (also known as FlatMap).
func MonadFilterMap ¶
MonadFilterMap maps an array with a function that returns an Option and keeps only the Some values. This is the monadic version that takes the array as the first parameter.
func MonadFilterMapWithIndex ¶
MonadFilterMapWithIndex maps an array with a function that takes an index and returns an Option, keeping only the Some values. This is the monadic version that takes the array as the first parameter.
func MonadFlap ¶
func MonadFlap[B, A any](fab []func(A) B, a A) []B
MonadFlap applies a value to an array of functions, producing an array of results. This is the monadic version that takes both parameters.
Type Parameters ¶
- B: The type of results
- A: The type of the input value
Parameters ¶
- fab: Array of functions to apply
- a: The value to apply to each function
Returns ¶
- An array of results from applying the value to each function
func MonadMap ¶
func MonadMap[A, B any](as []A, f func(A) B) []B
MonadMap applies a function to each element of an array, returning a new array with the results. This is the monadic version of Map that takes the array as the first parameter.
func MonadMapRef ¶
func MonadMapRef[A, B any](as []A, f func(*A) B) []B
MonadMapRef applies a function to a pointer to each element of an array, returning a new array with the results. This is useful when you need to access elements by reference without copying.
Type Parameters ¶
- A: The type of elements in the input array
- B: The type of elements in the output array
Parameters ¶
- as: The input array
- f: Function that takes a pointer to an element and returns a transformed value
Returns ¶
- A new array with transformed elements
Example ¶
type Point struct { X, Y int }
points := []Point{{1, 2}, {3, 4}}
xs := array.MonadMapRef(points, func(p *Point) int { return p.X })
// xs: []int{1, 3}
func MonadPartition ¶
MonadPartition splits an array into two arrays based on a predicate. The first array contains elements for which the predicate returns false, the second contains elements for which it returns true.
func MonadReduce ¶
func MonadReduce[A, B any](fa []A, f func(B, A) B, initial B) B
MonadReduce folds an array from left to right, applying a function to accumulate a result. This is the monadic version that takes the array as the first parameter.
Type Parameters ¶
- A: The type of elements in the array
- B: The type of the accumulated result
Parameters ¶
- fa: The input array
- f: Function that combines the accumulator with each element
- initial: The initial accumulator value
Returns ¶
- The final accumulated result
func MonadReduceWithIndex ¶ added in v2.1.19
MonadReduceWithIndex folds an array from left to right with access to the index, applying a function to accumulate a result. This is the monadic version that takes the array as the first parameter.
Type Parameters ¶
- A: The type of elements in the array
- B: The type of the accumulated result
Parameters ¶
- fa: The input array
- f: Function that combines the index, accumulator, and element
- initial: The initial accumulator value
Returns ¶
- The final accumulated result
func MonadSequence ¶
func MonadTraverse ¶
func MonadTraverse[A, B, HKTB, HKTAB, HKTRB any]( fof pointed.OfType[[]B, HKTRB], fmap func(func([]B) func(B) []B) func(HKTRB) HKTAB, fap func(HKTB) func(HKTAB) HKTRB, ta []A, f func(A) HKTB) HKTRB
MonadTraverse is the monadic version of Traverse that takes the array as a parameter. It maps each element of an array to an effect (HKT), then collects the results into an effect of an array.
This is useful when you want to apply the traverse operation directly without currying.
func MonadTraverseWithIndex ¶
func Monoid ¶
Monoid returns a Monoid instance for arrays. The Monoid combines arrays through concatenation, with an empty array as the identity element.
Example:
m := array.Monoid[int]()
result := m.Concat([]int{1, 2}, []int{3, 4}) // [1, 2, 3, 4]
empty := m.Empty() // []
func Partition ¶
Partition creates two new arrays out of one. The left result contains the elements for which the predicate returns false, the right one those for which the predicate returns true.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- pred: Predicate function to test each element
Returns ¶
- A function that partitions an array into a pair of arrays
Example ¶
isEven := array.Partition(func(x int) bool { return x%2 == 0 })
result := isEven([]int{1, 2, 3, 4, 5, 6})
// result: pair.Pair{Left: []int{1, 3, 5}, Right: []int{2, 4, 6}}
func Reduce ¶
func Reduce[A, B any](f func(B, A) B, initial B) func([]A) B
Reduce folds an array from left to right, applying a function to accumulate a result.
Example:
sum := array.Reduce(func(acc, x int) int { return acc + x }, 0)
result := sum([]int{1, 2, 3, 4, 5}) // 15
func ReduceRef ¶
func ReduceRef[A, B any](f func(B, *A) B, initial B) func([]A) B
ReduceRef folds an array from left to right using pointers to elements, applying a function to accumulate a result.
Type Parameters ¶
- A: The type of elements in the array
- B: The type of the accumulated result
Parameters ¶
- f: Function that combines the accumulator with a pointer to each element
- initial: The initial accumulator value
Returns ¶
- A function that reduces an array to a single value
func ReduceRight ¶
func ReduceRight[A, B any](f func(A, B) B, initial B) func([]A) B
ReduceRight folds an array from right to left, applying a function to accumulate a result.
func ReduceRightWithIndex ¶
ReduceRightWithIndex folds an array from right to left with access to the index, applying a function to accumulate a result.
func ReduceWithIndex ¶
ReduceWithIndex folds an array from left to right with access to the index, applying a function to accumulate a result.
func Replicate ¶
Replicate creates an array containing a value repeated the specified number of times.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- n: The number of times to repeat the value
- a: The value to repeat
Returns ¶
- A new array containing n copies of a
Example ¶
zeros := array.Replicate(5, 0)
// zeros: []int{0, 0, 0, 0, 0}
func Reverse ¶
func Reverse[A any](as []A) []A
Reverse returns a new slice with elements in reverse order. This function creates a new slice containing all elements from the input slice in reverse order, without modifying the original slice.
Type Parameters:
- A: The type of elements in the slice
Parameters:
- as: The input slice to reverse
Returns:
- A new slice with elements in reverse order
Behavior:
- Creates a new slice with the same length as the input
- Copies elements from the input slice in reverse order
- Does not modify the original slice
- Returns an empty slice if the input is empty
- Returns a single-element slice unchanged if input has one element
Example:
numbers := []int{1, 2, 3, 4, 5}
reversed := array.Reverse(numbers)
// reversed: []int{5, 4, 3, 2, 1}
// numbers: []int{1, 2, 3, 4, 5} (unchanged)
Example with strings:
words := []string{"hello", "world", "foo", "bar"}
reversed := array.Reverse(words)
// reversed: []string{"bar", "foo", "world", "hello"}
Example with empty slice:
empty := []int{}
reversed := array.Reverse(empty)
// reversed: []int{} (empty slice)
Example with single element:
single := []string{"only"}
reversed := array.Reverse(single)
// reversed: []string{"only"}
Use cases:
- Reversing the order of elements for display or processing
- Implementing stack-like behavior (LIFO)
- Processing data in reverse chronological order
- Reversing transformation pipelines
- Creating palindrome checks
- Implementing undo/redo functionality
Example with processing in reverse:
events := []string{"start", "middle", "end"}
reversed := array.Reverse(events)
// Process events in reverse order
for _, event := range reversed {
fmt.Println(event) // Prints: "end", "middle", "start"
}
Example with functional composition:
numbers := []int{1, 2, 3, 4, 5}
result := F.Pipe2(
numbers,
array.Map(N.Mul(2)),
array.Reverse,
)
// result: []int{10, 8, 6, 4, 2}
Performance:
- Time complexity: O(n) where n is the length of the slice
- Space complexity: O(n) for the new slice
- Does not allocate if the input slice is empty
Note: This function is immutable - it does not modify the original slice. If you need to reverse a slice in-place, consider using a different approach or modifying the slice directly.
func Semigroup ¶
Semigroup returns a Semigroup instance for arrays. The Semigroup combines arrays through concatenation.
Example:
s := array.Semigroup[int]()
result := s.Concat([]int{1, 2}, []int{3, 4}) // [1, 2, 3, 4]
func Sequence ¶
Sequence takes an array where elements are HKT<A> (higher kinded type) and, using an applicative of that HKT, returns an HKT of []A.
For example, it can turn:
- []Either[error, string] into Either[error, []string]
- []Option[int] into Option[[]int]
Sequence requires an Applicative of the HKT you are targeting. To turn an []Either[E, A] into an Either[E, []A], it needs an Applicative for Either. To turn an []Option[A] into an Option[[]A], it needs an Applicative for Option.
Note: We need to pass the members of the applicative explicitly because Go does not support higher kinded types or template methods on structs or interfaces.
Type parameters:
- HKTA = HKT<A> (e.g., Option[A], Either[E, A])
- HKTRA = HKT<[]A> (e.g., Option[[]A], Either[E, []A])
- HKTFRA = HKT<func(A)[]A> (e.g., Option[func(A)[]A])
Example:
import "github.com/IBM/fp-go/v2/option"
opts := []option.Option[int]{
option.Some(1),
option.Some(2),
option.Some(3),
}
seq := array.Sequence(
option.Of[[]int],
option.MonadMap[[]int, func(int) []int],
option.MonadAp[[]int, int],
)
result := seq(opts) // Some([1, 2, 3])
func Size ¶
Size returns the number of elements in an array.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- as: The array to measure
Returns ¶
- The number of elements in the array
func StrictEquals ¶ added in v2.1.0
func StrictEquals[T comparable]() E.Eq[[]T]
func StrictUniq ¶
func StrictUniq[A comparable](as []A) []A
StrictUniq converts an array of arbitrary items into an array of unique items where uniqueness is determined by the built-in equality constraint (comparable). The first occurrence of each unique value is kept, subsequent duplicates are removed.
Example:
numbers := []int{1, 2, 2, 3, 3, 3, 4}
unique := array.StrictUniq(numbers) // [1, 2, 3, 4]
strings := []string{"a", "b", "a", "c", "b"}
unique2 := array.StrictUniq(strings) // ["a", "b", "c"]
func Traverse ¶
func Traverse[A, B, HKTB, HKTAB, HKTRB any]( fof pointed.OfType[[]B, HKTRB], fmap functor.MapType[[]B, func(B) []B, HKTRB, HKTAB], fap apply.ApType[HKTB, HKTRB, HKTAB], f func(A) HKTB) func([]A) HKTRB
Traverse maps each element of an array to an effect (HKT), then collects the results into an effect of an array. This is like a combination of Map and Sequence.
Unlike Sequence which works with []HKT<A> -> HKT<[]A>, Traverse works with []A -> (A -> HKT<B>) -> HKT<[]B>, allowing you to transform elements while sequencing effects.
Type parameters:
- HKTB = HKT<B> (e.g., Option[B], Either[E, B])
- HKTAB = HKT<func(B)[]B> (intermediate type for applicative)
- HKTRB = HKT<[]B> (e.g., Option[[]B], Either[E, []B])
Example:
import (
"github.com/IBM/fp-go/v2/option"
"strconv"
)
// Parse strings to ints, returning None if any parse fails
parseAll := array.Traverse(
option.Of[[]int],
option.Map[[]int, func(int) []int],
option.Ap[[]int, int],
func(s string) option.Option[int] {
if n, err := strconv.Atoi(s); err == nil {
return option.Some(n)
}
return option.None[int]()
},
)
result := parseAll([]string{"1", "2", "3"}) // Some([1, 2, 3])
result2 := parseAll([]string{"1", "x", "3"}) // None
func TraverseWithIndex ¶
func Unzip ¶
Unzip is the reverse of Zip. It takes an array of pairs (tuples) and returns two corresponding arrays, one containing all first elements and one containing all second elements.
Example:
import "github.com/IBM/fp-go/v2/tuple"
pairs := []tuple.Tuple2[string, int]{
tuple.MakeTuple2("Alice", 30),
tuple.MakeTuple2("Bob", 25),
tuple.MakeTuple2("Charlie", 35),
}
result := array.Unzip(pairs)
// Result: (["Alice", "Bob", "Charlie"], [30, 25, 35])
names := result.Head // ["Alice", "Bob", "Charlie"]
ages := result.Tail // [30, 25, 35]
func Zip ¶
Zip takes two arrays and returns an array of corresponding pairs (tuples). If one input array is shorter, excess elements of the longer array are discarded.
Example:
names := []string{"Alice", "Bob", "Charlie"}
ages := []int{30, 25, 35}
pairs := array.Zip(ages)(names)
// Result: [(Alice, 30), (Bob, 25), (Charlie, 35)]
// With different lengths
pairs2 := array.Zip([]int{1, 2})([]string{"a", "b", "c"})
// Result: [(a, 1), (b, 2)]
func ZipWith ¶
func ZipWith[FCT ~func(A, B) C, A, B, C any](fa []A, fb []B, f FCT) []C
ZipWith applies a function to pairs of elements at the same index in two arrays, collecting the results in a new array. If one input array is shorter, excess elements of the longer array are discarded.
Example:
names := []string{"Alice", "Bob", "Charlie"}
ages := []int{30, 25, 35}
result := array.ZipWith(names, ages, func(name string, age int) string {
return fmt.Sprintf("%s is %d years old", name, age)
})
// Result: ["Alice is 30 years old", "Bob is 25 years old", "Charlie is 35 years old"]
Types ¶
type Kleisli ¶
type Kleisli[A, B any] = func(A) []B
Kleisli represents a Kleisli arrow for arrays. It's a function from A to []B, used for composing operations that produce arrays.
type Operator ¶
Operator represents a function that transforms one array into another. It takes a []A and produces a []B.
func Ap ¶
func Ap[B, A any](fa []A) Operator[func(A) B, B]
Ap applies an array of functions to an array of values, producing all combinations. This is the curried version.
func ApS ¶
func ApS[S1, S2, T any]( setter func(T) func(S1) S2, fa []T, ) Operator[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 semantics). This produces all combinations of context values and array values.
Example:
result := array.ApS(
func(y int) func(s struct{ X int }) struct{ X, Y int } {
return func(s struct{ X int }) struct{ X, Y int } {
return struct{ X, Y int }{s.X, y}
}
},
[]int{10, 20},
)
func Bind ¶
Bind attaches the result of a computation to a context S1 to produce a context S2. The setter function defines how to update the context with the computation result. This enables monadic composition where each step can produce multiple results.
Example:
result := F.Pipe2(
array.Do(struct{ X, Y int }{}),
array.Bind(
func(x int) func(s struct{}) struct{ X int } {
return func(s struct{}) struct{ X int } { return struct{ X int }{x} }
},
func(s struct{}) []int { return []int{1, 2} },
),
)
func BindTo ¶
func BindTo[S1, T any]( setter func(T) S1, ) Operator[T, S1]
BindTo initializes a new state S1 from a value T. This is typically the first operation after Do to start building the context. It transforms each element of type T into a state of type S1.
Example:
type State struct{ X int }
result := F.Pipe2(
[]int{1, 2, 3},
array.BindTo(func(x int) State {
return State{X: x}
}),
)
// result: []State{{X: 1}, {X: 2}, {X: 3}}
func Chain ¶
Chain applies a function that returns an array to each element and flattens the results. This is the curried version (also known as FlatMap).
Example:
duplicate := array.Chain(func(x int) []int { return []int{x, x} })
result := duplicate([]int{1, 2, 3}) // [1, 1, 2, 2, 3, 3]
func ChainOptionK ¶ added in v2.2.16
ChainOptionK maps an array with an iterating function that returns an Option of an array. It keeps only the Some values discarding the Nones and then flattens the result.
Type Parameters ¶
- A: The type of elements in the input array
- B: The type of elements in the output array
Parameters ¶
- f: Function that maps elements to Option of arrays
Returns ¶
- A function that transforms, filters, and flattens an array
func Clone ¶
func Clone[A any](f func(A) A) Operator[A, A]
Clone creates a deep copy of the array using the provided endomorphism to clone the values.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- f: Function to clone each element
Returns ¶
- A function that creates a deep copy of an array
func Concat ¶ added in v2.1.11
func Concat[A any](suffix []A) Operator[A, A]
Concat concatenates two arrays by appending a suffix array to a base array.
This is a curried function that takes a suffix array and returns a function that takes a base array and produces a new array with the suffix appended. It follows the "data last" pattern, where the data to be operated on (base array) is provided last, making it ideal for use in functional pipelines.
Semantic: Concat(suffix)(base) produces [base... suffix...]
The function creates a new array containing all elements from the base array followed by all elements from the suffix array. Neither input array is modified.
Type Parameters:
- A: The type of elements in the arrays
Parameters:
- suffix: The array to append to the end of the base array
Returns:
- A function that takes a base array and returns [base... suffix...]
Behavior:
- Creates a new array with length equal to len(base) + len(suffix)
- Copies all elements from the base array first
- Appends all elements from the suffix array at the end
- Returns the base array unchanged if suffix is empty
- Returns suffix unchanged if the base array is empty
- Does not modify either input array
- Preserves element order within each array
Example - Basic concatenation:
base := []int{1, 2, 3}
suffix := []int{4, 5, 6}
concat := array.Concat(suffix)
result := concat(base)
// result: []int{1, 2, 3, 4, 5, 6}
// base: []int{1, 2, 3} (unchanged)
// suffix: []int{4, 5, 6} (unchanged)
Example - Direct application:
result := array.Concat([]int{4, 5, 6})([]int{1, 2, 3})
// result: []int{1, 2, 3, 4, 5, 6}
// Demonstrates: Concat(b)(a) = [a... b...]
Example - Empty arrays:
base := []int{1, 2, 3}
empty := []int{}
result := array.Concat(empty)(base)
// result: []int{1, 2, 3}
Example - Strings:
words1 := []string{"hello", "world"}
words2 := []string{"foo", "bar"}
result := array.Concat(words2)(words1)
// result: []string{"hello", "world", "foo", "bar"}
Example - Functional composition:
numbers := []int{1, 2, 3}
result := F.Pipe2(
numbers,
array.Map(N.Mul(2)), // [2, 4, 6]
array.Concat([]int{10, 20}), // [2, 4, 6, 10, 20]
)
Example - Multiple concatenations:
result := F.Pipe2(
[]int{1},
array.Concat([]int{2, 3}), // [1, 2, 3]
array.Concat([]int{4, 5}), // [1, 2, 3, 4, 5]
)
Example - Building arrays incrementally:
header := []string{"Name", "Age"}
data := []string{"Alice", "30"}
footer := []string{"Total: 1"}
result := F.Pipe2(
header,
array.Concat(data),
array.Concat(footer),
)
// result: []string{"Name", "Age", "Alice", "30", "Total: 1"}
Use cases:
- Combining multiple arrays into one
- Building arrays incrementally in pipelines
- Implementing array-based data structures (queues, buffers)
- Merging results from multiple operations
- Creating array transformation pipelines
- Appending batches of elements
Mathematical properties:
- Associativity: Concat(c)(Concat(b)(a)) == Concat(Concat(c)(b))(a)
- Identity: Concat([])(a) == a and Concat(a)([]) == a
- Length: len(Concat(b)(a)) == len(a) + len(b)
Performance:
- Time complexity: O(n + m) where n and m are the lengths of the arrays
- Space complexity: O(n + m) for the new array
- Optimized to avoid allocation when one array is empty
Note: This function is immutable - it creates a new array rather than modifying the input arrays. For appending a single element, consider using Append or Push.
See Also:
- Append: For appending a single element
- Push: Curried version of Append
- Flatten: For flattening nested arrays
func Extend ¶ added in v2.1.7
func Extend[A, B any](f func([]A) B) Operator[A, B]
Extend applies a function to every suffix of an array, creating a new array of results. This is the comonad extend operation for arrays.
The function f is applied to progressively smaller suffixes of the input array:
- f(as[0:]) for the first element
- f(as[1:]) for the second element
- f(as[2:]) for the third element
- and so on...
Type Parameters:
- A: The type of elements in the input array
- B: The type of elements in the output array
Parameters:
- f: A function that takes an array suffix and returns a value
Returns:
- A function that transforms an array of A into an array of B
Behavior:
- Creates a new array with the same length as the input
- For each position i, applies f to the suffix starting at i
- Returns an empty array if the input is empty
Example:
// Sum all elements from current position to end
sumSuffix := array.Extend(func(as []int) int {
return array.Reduce(func(acc, x int) int { return acc + x }, 0)(as)
})
result := sumSuffix([]int{1, 2, 3, 4})
// result: []int{10, 9, 7, 4}
// Explanation: [1+2+3+4, 2+3+4, 3+4, 4]
Example with length:
// Get remaining length at each position
lengths := array.Extend(array.Size[int])
result := lengths([]int{10, 20, 30})
// result: []int{3, 2, 1}
Example with head:
// Duplicate each element (extract head of each suffix)
duplicate := array.Extend(func(as []int) int {
return F.Pipe1(as, array.Head[int], O.GetOrElse(F.Constant(0)))
})
result := duplicate([]int{1, 2, 3})
// result: []int{1, 2, 3}
Use cases:
- Computing cumulative or rolling operations
- Implementing sliding window algorithms
- Creating context-aware transformations
- Building comonadic computations
Comonad laws:
- Left identity: Extend(Extract) == Identity
- Right identity: Extract ∘ Extend(f) == f
- Associativity: Extend(f) ∘ Extend(g) == Extend(f ∘ Extend(g))
func Filter ¶
Filter returns a new array with all elements from the original array that match a predicate.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- pred: Predicate function to test each element
Returns ¶
- A function that filters an array based on the predicate
Example ¶
isEven := array.Filter(func(x int) bool { return x%2 == 0 })
result := isEven([]int{1, 2, 3, 4, 5, 6})
// result: []int{2, 4, 6}
func FilterMap ¶
FilterMap maps an array with an iterating function that returns an Option and keeps only the Some values discarding the Nones.
Type Parameters ¶
- A: The type of elements in the input array
- B: The type of elements in the output array
Parameters ¶
- f: Function that maps elements to Option values
Returns ¶
- A function that transforms and filters an array
Example ¶
parseInt := array.FilterMap(func(s string) option.Option[int] {
if n, err := strconv.Atoi(s); err == nil {
return option.Some(n)
}
return option.None[int]()
})
result := parseInt([]string{"1", "bad", "3", "4"})
// result: []int{1, 3, 4}
func FilterMapRef ¶
FilterMapRef filters an array using a predicate on pointers and maps the matching elements using a function on pointers.
Type Parameters ¶
- A: The type of elements in the input array
- B: The type of elements in the output array
Parameters ¶
- pred: Predicate function that takes a pointer to an element
- f: Function that transforms a pointer to an element
Returns ¶
- A function that filters and transforms an array
func FilterMapWithIndex ¶
FilterMapWithIndex maps an array with an iterating function that returns an Option and keeps only the Some values discarding the Nones. The function receives both the index and the element.
Type Parameters ¶
- A: The type of elements in the input array
- B: The type of elements in the output array
Parameters ¶
- f: Function that takes an index and element and returns an Option
Returns ¶
- A function that transforms and filters an array
func FilterRef ¶
FilterRef returns a new array with all elements from the original array that match a predicate operating on pointers.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- pred: Predicate function that takes a pointer to an element
Returns ¶
- A function that filters an array based on the predicate
Example ¶
type Point struct { X, Y int }
filterPositiveX := array.FilterRef(func(p *Point) bool { return p.X > 0 })
points := []Point{{-1, 2}, {3, 4}, {-5, 6}}
result := filterPositiveX(points)
// result: []Point{{3, 4}}
func FilterWithIndex ¶
FilterWithIndex returns a new array with all elements from the original array that match a predicate. The predicate receives both the index and the element.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- pred: Predicate function that takes an index and element
Returns ¶
- A function that filters an array based on the predicate
Example ¶
filterOddIndices := array.FilterWithIndex(func(i int, _ int) bool { return i%2 == 1 })
result := filterOddIndices([]int{10, 20, 30, 40, 50})
// result: []int{20, 40}
func Flap ¶
func Flap[B, A any](a A) Operator[func(A) B, B]
Flap applies a value to an array of functions, producing an array of results. This is the curried version.
Type Parameters ¶
- B: The type of results
- A: The type of the input value
Parameters ¶
- a: The value to apply to each function
Returns ¶
- A function that applies the value to an array of functions
Example ¶
fns := []func(int) int{
func(x int) int { return x * 2 },
func(x int) int { return x + 10 },
func(x int) int { return x * x },
}
applyFive := array.Flap[int](5)
result := applyFive(fns)
// result: []int{10, 15, 25}
func Intersperse ¶
func Intersperse[A any](middle A) Operator[A, A]
Intersperse inserts a separator between each element of an array.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- middle: The separator to insert between elements
Returns ¶
- A function that transforms an array by inserting the separator between elements
Example ¶
result := array.Intersperse(0)([]int{1, 2, 3})
// result: []int{1, 0, 2, 0, 3}
func Let ¶
func Let[S1, S2, T any]( setter func(T) func(S1) S2, f func(S1) T, ) Operator[S1, S2]
Let attaches the result of a pure computation to a context S1 to produce a context S2. Unlike Bind, the computation function returns a plain value T rather than []T. This is useful when you need to compute a derived value from the current context without introducing additional array elements.
Example:
type State1 struct{ X int }
type State2 struct{ X, Double int }
result := F.Pipe2(
[]State1{{X: 5}, {X: 10}},
array.Let(
func(double int) func(s State1) State2 {
return func(s State1) State2 {
return State2{X: s.X, Double: double}
}
},
func(s State1) int { return s.X * 2 },
),
)
// result: []State2{{X: 5, Double: 10}, {X: 10, Double: 20}}
func LetTo ¶
func LetTo[S1, S2, T any]( setter func(T) func(S1) S2, b T, ) Operator[S1, S2]
LetTo attaches a constant value to a context S1 to produce a context S2. This is useful for adding constant values to the context without computation.
Example:
type State1 struct{ X int }
type State2 struct{ X int; Name string }
result := F.Pipe2(
[]State1{{X: 1}, {X: 2}},
array.LetTo(
func(name string) func(s State1) State2 {
return func(s State1) State2 {
return State2{X: s.X, Name: name}
}
},
"constant",
),
)
// result: []State2{{X: 1, Name: "constant"}, {X: 2, Name: "constant"}}
func Map ¶
func Map[A, B any](f func(A) B) Operator[A, B]
Map applies a function to each element of an array, returning a new array with the results. This is the curried version that returns a function.
Example:
double := array.Map(N.Mul(2))
result := double([]int{1, 2, 3}) // [2, 4, 6]
func MapRef ¶
func MapRef[A, B any](f func(*A) B) Operator[A, B]
MapRef applies a function to a pointer to each element of an array, returning a new array with the results. This is the curried version that returns a function.
Type Parameters ¶
- A: The type of elements in the input array
- B: The type of elements in the output array
Parameters ¶
- f: Function that takes a pointer to an element and returns a transformed value
Returns ¶
- A function that transforms an array of A into an array of B
Example ¶
type Point struct { X, Y int }
extractX := array.MapRef(func(p *Point) int { return p.X })
points := []Point{{1, 2}, {3, 4}}
xs := extractX(points)
// xs: []int{1, 3}
func MapWithIndex ¶
MapWithIndex applies a function to each element and its index in an array, returning a new array with the results.
func Prepend ¶
func Prepend[A any](head A) Operator[A, A]
Prepend adds an element to the beginning of an array, returning a new array.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- head: The element to add at the beginning
Returns ¶
- A function that prepends the element to an array
Example ¶
addZero := array.Prepend(0)
result := addZero([]int{1, 2, 3})
// result: []int{0, 1, 2, 3}
func PrependAll ¶
func PrependAll[A any](middle A) Operator[A, A]
PrependAll inserts a separator before each element of an array.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- middle: The separator to insert before each element
Returns ¶
- A function that transforms an array by prepending the separator to each element
Example ¶
result := array.PrependAll(0)([]int{1, 2, 3})
// result: []int{0, 1, 0, 2, 0, 3}
func Push ¶
func Push[A any](a A) Operator[A, A]
Push adds an element to the end of an array (curried version of Append).
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- a: The element to add
Returns ¶
- A function that appends the element to an array
Example ¶
addFive := array.Push(5)
result := addFive([]int{1, 2, 3})
// result: []int{1, 2, 3, 5}
See Also ¶
- Append: Non-curried version
func Slice ¶
Slice extracts a subarray from index low (inclusive) to high (exclusive).
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- low: The starting index (inclusive)
- high: The ending index (exclusive)
Returns ¶
- A function that extracts a subarray
Example ¶
middle := array.Slice[int](2, 5)
result := middle([]int{0, 1, 2, 3, 4, 5, 6})
// result: []int{2, 3, 4}
func SliceRight ¶
SliceRight extracts a subarray from the specified start index to the end.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- start: The starting index (inclusive)
Returns ¶
- A function that extracts a subarray from start to end
Example ¶
fromThird := array.SliceRight[int](2)
result := fromThird([]int{0, 1, 2, 3, 4, 5})
// result: []int{2, 3, 4, 5}
func Sort ¶
Sort implements a stable sort on the array given the provided ordering. The sort is stable, meaning that elements that compare equal retain their original order.
Example:
import "github.com/IBM/fp-go/v2/ord"
numbers := []int{3, 1, 4, 1, 5, 9, 2, 6}
sorted := array.Sort(ord.FromStrictCompare[int]())(numbers)
// Result: [1, 1, 2, 3, 4, 5, 6, 9]
func SortBy ¶
SortBy implements a stable sort on the array using multiple ordering criteria. The orderings are applied in sequence: if two elements are equal according to the first ordering, the second ordering is used, and so on.
Example:
import "github.com/IBM/fp-go/v2/ord"
type Person struct {
LastName string
FirstName string
}
people := []Person{
{"Smith", "John"},
{"Smith", "Alice"},
{"Jones", "Bob"},
}
sortByName := array.SortBy([]ord.Ord[Person]{
ord.Contramap(func(p Person) string { return p.LastName })(ord.FromStrictCompare[string]()),
ord.Contramap(func(p Person) string { return p.FirstName })(ord.FromStrictCompare[string]()),
})
sorted := sortByName(people)
// Result: [{"Jones", "Bob"}, {"Smith", "Alice"}, {"Smith", "John"}]
func SortByKey ¶
SortByKey implements a stable sort on the array given the provided ordering on an extracted key. This is useful when you want to sort complex types by a specific field.
Example:
import "github.com/IBM/fp-go/v2/ord"
type Person struct {
Name string
Age int
}
people := []Person{
{"Alice", 30},
{"Bob", 25},
{"Charlie", 35},
}
sortByAge := array.SortByKey(
ord.FromStrictCompare[int](),
func(p Person) int { return p.Age },
)
sorted := sortByAge(people)
// Result: [{"Bob", 25}, {"Alice", 30}, {"Charlie", 35}]
func Uniq ¶
func Uniq[A any, K comparable](f func(A) K) Operator[A, A]
Uniq converts an array of arbitrary items into an array of unique items where uniqueness is determined based on a key extractor function. The first occurrence of each unique key is kept, subsequent duplicates are removed.
This is useful for removing duplicates from arrays of complex types based on a specific field.
Example:
type Person struct {
Name string
Age int
}
people := []Person{
{"Alice", 30},
{"Bob", 25},
{"Alice", 35}, // duplicate name
{"Charlie", 30},
}
uniqueByName := array.Uniq(func(p Person) string { return p.Name })
result := uniqueByName(people)
// Result: [{"Alice", 30}, {"Bob", 25}, {"Charlie", 30}]
func UpsertAt ¶
func UpsertAt[A any](a A) Operator[A, A]
UpsertAt returns a function that inserts or updates an element at a specific index. If the index is out of bounds, the element is appended.
Type Parameters ¶
- A: The type of elements in the array
Parameters ¶
- a: The element to insert or update
Returns ¶
- A function that takes an index and returns a function that upserts at that index
type Option ¶
Option represents an optional value that may or may not be present.
func ArrayOption ¶
func ArrayOption[A any](ma []Option[A]) Option[[]A]
ArrayOption returns a function to convert a sequence of options into an option of a sequence. If all options are Some, returns Some containing an array of all values. If any option is None, returns None.
Example:
opts := []option.Option[int]{
option.Some(1),
option.Some(2),
option.Some(3),
}
result := array.ArrayOption[int]()(opts) // Some([1, 2, 3])
opts2 := []option.Option[int]{
option.Some(1),
option.None[int](),
option.Some(3),
}
result2 := array.ArrayOption[int]()(opts2) // None
func First ¶
func First[A any](as []A) Option[A]
First returns the first element of an array, wrapped in an Option (alias for Head). Returns None if the array is empty.
func Head ¶
func Head[A any](as []A) Option[A]
Head returns the first element of an array, wrapped in an Option. Returns None if the array is empty.