mirror of
https://github.com/IBM/fp-go.git
synced 2026-04-11 15:29:06 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0df62c0031 |
17
v2/AGENTS.md
17
v2/AGENTS.md
@@ -22,8 +22,10 @@ This document provides guidelines for AI agents working on the fp-go/v2 project.
|
||||
|
||||
1. **Use Standard Go Doc Format**
|
||||
- Do NOT use markdown-style links like `[text](url)`
|
||||
- Do NOT use markdown-style headers like `# Section` or `## Subsection`
|
||||
- Use simple type references: `ReaderResult`, `Validate[I, A]`, `validation.Success`
|
||||
- Go's documentation system will automatically create links
|
||||
- Use plain text with blank lines to separate sections
|
||||
|
||||
2. **Structure**
|
||||
```go
|
||||
@@ -31,24 +33,20 @@ This document provides guidelines for AI agents working on the fp-go/v2 project.
|
||||
//
|
||||
// Longer description explaining the purpose and behavior.
|
||||
//
|
||||
// # Type Parameters
|
||||
//
|
||||
// Type Parameters:
|
||||
// - T: Description of type parameter
|
||||
//
|
||||
// # Parameters
|
||||
//
|
||||
// Parameters:
|
||||
// - param: Description of parameter
|
||||
//
|
||||
// # Returns
|
||||
//
|
||||
// Returns:
|
||||
// - ReturnType: Description of return value
|
||||
//
|
||||
// # Example Usage
|
||||
// Example:
|
||||
//
|
||||
// code example here
|
||||
//
|
||||
// # See Also
|
||||
//
|
||||
// See Also:
|
||||
// - RelatedFunction: Brief description
|
||||
func FunctionName[T any](param T) ReturnType {
|
||||
```
|
||||
@@ -57,6 +55,7 @@ This document provides guidelines for AI agents working on the fp-go/v2 project.
|
||||
- Use idiomatic Go patterns
|
||||
- Prefer `result.Eitherize1(strconv.Atoi)` over manual error handling
|
||||
- Show realistic, runnable examples
|
||||
- Indent code examples with spaces (not tabs) for proper godoc rendering
|
||||
|
||||
### File Headers
|
||||
|
||||
|
||||
@@ -24,21 +24,75 @@ import (
|
||||
"github.com/IBM/fp-go/v2/pair"
|
||||
)
|
||||
|
||||
// From constructs an array from a set of variadic arguments
|
||||
// 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}
|
||||
//
|
||||
//go:inline
|
||||
func From[A any](data ...A) []A {
|
||||
return G.From[[]A](data...)
|
||||
}
|
||||
|
||||
// MakeBy returns a `Array` of length `n` with element `i` initialized with `f(i)`.
|
||||
// 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}
|
||||
//
|
||||
//go:inline
|
||||
func MakeBy[F ~func(int) A, A any](n int, f F) []A {
|
||||
return G.MakeBy[[]A](n, f)
|
||||
}
|
||||
|
||||
// Replicate creates a `Array` containing a value repeated the specified number of times.
|
||||
// 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}
|
||||
//
|
||||
//go:inline
|
||||
func Replicate[A any](n int, a A) []A {
|
||||
@@ -55,6 +109,27 @@ func MonadMap[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 MonadMapRef[A, B any](as []A, f func(*A) B) []B {
|
||||
count := len(as)
|
||||
bs := make([]B, count)
|
||||
@@ -86,6 +161,27 @@ func Map[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 MapRef[A, B any](f func(*A) B) Operator[A, B] {
|
||||
return F.Bind2nd(MonadMapRef[A, B], f)
|
||||
}
|
||||
@@ -114,14 +210,51 @@ func filterMapRef[A, B any](fa []A, pred func(*A) bool, f func(*A) B) []B {
|
||||
return result
|
||||
}
|
||||
|
||||
// Filter returns a new array with all elements from the original array that match a predicate
|
||||
// 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}
|
||||
//
|
||||
//go:inline
|
||||
func Filter[A any](pred func(A) bool) Operator[A, A] {
|
||||
return G.Filter[[]A](pred)
|
||||
}
|
||||
|
||||
// FilterWithIndex returns a new array with all elements from the original array that match a predicate
|
||||
// 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}
|
||||
//
|
||||
//go:inline
|
||||
func FilterWithIndex[A any](pred func(int, A) bool) Operator[A, A] {
|
||||
@@ -129,6 +262,26 @@ func FilterWithIndex[A any](pred func(int, A) bool) Operator[A, A] {
|
||||
}
|
||||
|
||||
// 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 FilterRef[A any](pred func(*A) bool) Operator[A, A] {
|
||||
return F.Bind2nd(filterRef[A], pred)
|
||||
}
|
||||
@@ -149,21 +302,73 @@ func MonadFilterMapWithIndex[A, B any](fa []A, f func(int, A) Option[B]) []B {
|
||||
return G.MonadFilterMapWithIndex[[]A, []B](fa, f)
|
||||
}
|
||||
|
||||
// FilterMap maps an array with an iterating function that returns an [Option] and it keeps only the Some values discarding the Nones.
|
||||
// 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}
|
||||
//
|
||||
//go:inline
|
||||
func FilterMap[A, B any](f option.Kleisli[A, B]) Operator[A, B] {
|
||||
return G.FilterMap[[]A, []B](f)
|
||||
}
|
||||
|
||||
// FilterMapWithIndex maps an array with an iterating function that returns an [Option] and it keeps only the Some values discarding the Nones.
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func FilterMapWithIndex[A, B any](f func(int, A) Option[B]) Operator[A, B] {
|
||||
return G.FilterMapWithIndex[[]A, []B](f)
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func ChainOptionK[A, B any](f option.Kleisli[A, []B]) Operator[A, B] {
|
||||
@@ -171,6 +376,20 @@ func ChainOptionK[A, B any](f option.Kleisli[A, []B]) Operator[A, B] {
|
||||
}
|
||||
|
||||
// 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 FilterMapRef[A, B any](pred func(a *A) bool, f func(*A) B) Operator[A, B] {
|
||||
return func(fa []A) []B {
|
||||
return filterMapRef(fa, pred, f)
|
||||
@@ -185,11 +404,48 @@ func reduceRef[A, B any](fa []A, f func(B, *A) B, initial B) B {
|
||||
return current
|
||||
}
|
||||
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func MonadReduce[A, B any](fa []A, f func(B, A) B, initial B) B {
|
||||
return G.MonadReduce(fa, f, initial)
|
||||
}
|
||||
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func MonadReduceWithIndex[A, B any](fa []A, f func(int, B, A) B, initial B) B {
|
||||
return G.MonadReduceWithIndex(fa, f, initial)
|
||||
@@ -232,6 +488,20 @@ func ReduceRightWithIndex[A, B any](f func(int, A, B) 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 ReduceRef[A, B any](f func(B, *A) B, initial B) func([]A) B {
|
||||
return func(as []A) B {
|
||||
return reduceRef(as, f, initial)
|
||||
@@ -257,12 +527,36 @@ func Append[A any](as []A, a A) []A {
|
||||
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func IsEmpty[A any](as []A) bool {
|
||||
return G.IsEmpty(as)
|
||||
}
|
||||
|
||||
// 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 IsNonEmpty[A any](as []A) bool {
|
||||
return len(as) > 0
|
||||
}
|
||||
@@ -372,6 +666,23 @@ func Last[A any](as []A) Option[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 PrependAll[A any](middle A) Operator[A, A] {
|
||||
return func(as []A) []A {
|
||||
count := len(as)
|
||||
@@ -389,9 +700,22 @@ func PrependAll[A any](middle A) Operator[A, A] {
|
||||
|
||||
// Intersperse inserts a separator between each element of an array.
|
||||
//
|
||||
// Example:
|
||||
// # Type Parameters
|
||||
//
|
||||
// result := array.Intersperse(0)([]int{1, 2, 3}) // [1, 0, 2, 0, 3]
|
||||
// - 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 Intersperse[A any](middle A) Operator[A, A] {
|
||||
prepend := PrependAll(middle)
|
||||
return func(as []A) []A {
|
||||
@@ -403,6 +727,18 @@ func Intersperse[A any](middle A) Operator[A, A] {
|
||||
}
|
||||
|
||||
// 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 Intercalate[A any](m M.Monoid[A]) func(A) func([]A) A {
|
||||
return func(middle A) func([]A) A {
|
||||
return Match(m.Empty, F.Flow2(Intersperse(middle), ConcatAll(m)))
|
||||
@@ -411,9 +747,22 @@ func Intercalate[A any](m M.Monoid[A]) func(A) func([]A) A {
|
||||
|
||||
// Flatten converts a nested array into a flat array by concatenating all inner arrays.
|
||||
//
|
||||
// Example:
|
||||
// # Type Parameters
|
||||
//
|
||||
// result := array.Flatten([][]int{{1, 2}, {3, 4}, {5}}) // [1, 2, 3, 4, 5]
|
||||
// - 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}
|
||||
//
|
||||
//go:inline
|
||||
func Flatten[A any](mma [][]A) []A {
|
||||
@@ -421,6 +770,25 @@ func Flatten[A any](mma [][]A) []A {
|
||||
}
|
||||
|
||||
// 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 Slice[A any](low, high int) Operator[A, A] {
|
||||
return array.Slice[[]A](low, high)
|
||||
}
|
||||
@@ -428,6 +796,24 @@ func Slice[A any](low, high int) Operator[A, A] {
|
||||
// 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)
|
||||
//
|
||||
//go:inline
|
||||
func Lookup[A any](idx int) func([]A) Option[A] {
|
||||
return G.Lookup[[]A](idx)
|
||||
@@ -436,6 +822,18 @@ func Lookup[A any](idx int) func([]A) Option[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
|
||||
//
|
||||
//go:inline
|
||||
func UpsertAt[A any](a A) Operator[A, A] {
|
||||
return G.UpsertAt[[]A](a)
|
||||
@@ -443,6 +841,18 @@ func UpsertAt[A any](a A) Operator[A, A] {
|
||||
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func Size[A any](as []A) int {
|
||||
return G.Size(as)
|
||||
@@ -457,58 +867,178 @@ func MonadPartition[A any](as []A, pred func(A) bool) pair.Pair[[]A, []A] {
|
||||
return G.MonadPartition(as, pred)
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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}}
|
||||
//
|
||||
//go:inline
|
||||
func Partition[A any](pred func(A) bool) func([]A) pair.Pair[[]A, []A] {
|
||||
return G.Partition[[]A](pred)
|
||||
}
|
||||
|
||||
// IsNil checks if the array is set to nil
|
||||
// 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 IsNil[A any](as []A) bool {
|
||||
return array.IsNil(as)
|
||||
}
|
||||
|
||||
// IsNonNil checks if the array is set to nil
|
||||
// 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 IsNonNil[A any](as []A) bool {
|
||||
return array.IsNonNil(as)
|
||||
}
|
||||
|
||||
// ConstNil returns a nil array
|
||||
// ConstNil returns a nil array.
|
||||
//
|
||||
// # Type Parameters
|
||||
//
|
||||
// - A: The type of elements in the array
|
||||
//
|
||||
// # Returns
|
||||
//
|
||||
// - A nil array of type A
|
||||
func ConstNil[A any]() []A {
|
||||
return array.ConstNil[[]A]()
|
||||
}
|
||||
|
||||
// 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}
|
||||
//
|
||||
//go:inline
|
||||
func SliceRight[A any](start int) Operator[A, A] {
|
||||
return G.SliceRight[[]A](start)
|
||||
}
|
||||
|
||||
// Copy creates a shallow copy of the array
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func Copy[A any](b []A) []A {
|
||||
return G.Copy(b)
|
||||
}
|
||||
|
||||
// Clone creates a deep copy of the array using the provided endomorphism to clone the values
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func Clone[A any](f func(A) A) Operator[A, A] {
|
||||
return G.Clone[[]A](f)
|
||||
}
|
||||
|
||||
// FoldMap maps and folds an array. Map the Array passing each value to the iterating function. Then fold the results using the provided Monoid.
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func FoldMap[A, B any](m M.Monoid[B]) func(func(A) B) func([]A) B {
|
||||
return G.FoldMap[[]A](m)
|
||||
}
|
||||
|
||||
// FoldMapWithIndex maps and folds an array. Map the Array passing each value to the iterating function. Then fold the results using the provided Monoid.
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func FoldMapWithIndex[A, B any](m M.Monoid[B]) func(func(int, A) B) func([]A) B {
|
||||
@@ -517,12 +1047,46 @@ func FoldMapWithIndex[A, B any](m M.Monoid[B]) func(func(int, A) B) func([]A) B
|
||||
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func Fold[A any](m M.Monoid[A]) func([]A) A {
|
||||
return G.Fold[[]A](m)
|
||||
}
|
||||
|
||||
// Push adds an element to the end of an array (alias for Append).
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func Push[A any](a A) Operator[A, A] {
|
||||
@@ -660,6 +1224,20 @@ func Concat[A any](suffix []A) Operator[A, A] {
|
||||
// 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
|
||||
//
|
||||
//go:inline
|
||||
func MonadFlap[B, A any](fab []func(A) B, a A) []B {
|
||||
return G.MonadFlap[func(A) B, []func(A) B, []B](fab, a)
|
||||
@@ -668,6 +1246,30 @@ func MonadFlap[B, A any](fab []func(A) B, a A) []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}
|
||||
//
|
||||
//go:inline
|
||||
func Flap[B, A any](a A) Operator[func(A) B, B] {
|
||||
return G.Flap[func(A) B, []func(A) B, []B](a)
|
||||
@@ -675,6 +1277,24 @@ func Flap[B, A any](a A) Operator[func(A) B, B] {
|
||||
|
||||
// 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}
|
||||
//
|
||||
//go:inline
|
||||
func Prepend[A any](head A) Operator[A, A] {
|
||||
return G.Prepend[Operator[A, A]](head)
|
||||
|
||||
@@ -198,11 +198,228 @@ func TestFilterMap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFoldMap(t *testing.T) {
|
||||
src := From("a", "b", "c")
|
||||
t.Run("FoldMap with 0 items", func(t *testing.T) {
|
||||
empty := []int{}
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
foldMap := FoldMap[int](sumMonoid)(N.Mul(2))
|
||||
result := foldMap(empty)
|
||||
assert.Equal(t, 0, result, "FoldMap should return monoid empty for 0 items")
|
||||
})
|
||||
|
||||
fold := FoldMap[string](S.Monoid)(strings.ToUpper)
|
||||
t.Run("FoldMap with 1 item", func(t *testing.T) {
|
||||
single := From(5)
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
foldMap := FoldMap[int](sumMonoid)(N.Mul(2))
|
||||
result := foldMap(single)
|
||||
assert.Equal(t, 10, result, "FoldMap should map and return single item")
|
||||
})
|
||||
|
||||
assert.Equal(t, "ABC", fold(src))
|
||||
t.Run("FoldMap with 2 items", func(t *testing.T) {
|
||||
two := From(3, 4)
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
foldMap := FoldMap[int](sumMonoid)(N.Mul(2))
|
||||
result := foldMap(two)
|
||||
assert.Equal(t, 14, result, "FoldMap should map and fold 2 items: (3*2) + (4*2) = 14")
|
||||
})
|
||||
|
||||
t.Run("FoldMap with many items", func(t *testing.T) {
|
||||
many := From(1, 2, 3, 4, 5)
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
foldMap := FoldMap[int](sumMonoid)(N.Mul(2))
|
||||
result := foldMap(many)
|
||||
assert.Equal(t, 30, result, "FoldMap should map and fold many items: (1*2) + (2*2) + (3*2) + (4*2) + (5*2) = 30")
|
||||
})
|
||||
|
||||
t.Run("FoldMap with string concatenation - 0 items", func(t *testing.T) {
|
||||
empty := []string{}
|
||||
fold := FoldMap[string](S.Monoid)(strings.ToUpper)
|
||||
result := fold(empty)
|
||||
assert.Equal(t, "", result, "FoldMap should return empty string for 0 items")
|
||||
})
|
||||
|
||||
t.Run("FoldMap with string concatenation - 1 item", func(t *testing.T) {
|
||||
single := From("a")
|
||||
fold := FoldMap[string](S.Monoid)(strings.ToUpper)
|
||||
result := fold(single)
|
||||
assert.Equal(t, "A", result, "FoldMap should map single string")
|
||||
})
|
||||
|
||||
t.Run("FoldMap with string concatenation - 2 items", func(t *testing.T) {
|
||||
two := From("a", "b")
|
||||
fold := FoldMap[string](S.Monoid)(strings.ToUpper)
|
||||
result := fold(two)
|
||||
assert.Equal(t, "AB", result, "FoldMap should map and concatenate 2 strings")
|
||||
})
|
||||
|
||||
t.Run("FoldMap with string concatenation - many items", func(t *testing.T) {
|
||||
many := From("a", "b", "c", "d", "e")
|
||||
fold := FoldMap[string](S.Monoid)(strings.ToUpper)
|
||||
result := fold(many)
|
||||
assert.Equal(t, "ABCDE", result, "FoldMap should map and concatenate many strings")
|
||||
})
|
||||
}
|
||||
|
||||
func TestFold(t *testing.T) {
|
||||
t.Run("Fold with 0 items", func(t *testing.T) {
|
||||
empty := []int{}
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
fold := Fold[int](sumMonoid)
|
||||
result := fold(empty)
|
||||
assert.Equal(t, 0, result, "Fold should return monoid empty for 0 items")
|
||||
})
|
||||
|
||||
t.Run("Fold with 1 item", func(t *testing.T) {
|
||||
single := From(42)
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
fold := Fold[int](sumMonoid)
|
||||
result := fold(single)
|
||||
assert.Equal(t, 42, result, "Fold should return single item")
|
||||
})
|
||||
|
||||
t.Run("Fold with 2 items", func(t *testing.T) {
|
||||
two := From(10, 20)
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
fold := Fold[int](sumMonoid)
|
||||
result := fold(two)
|
||||
assert.Equal(t, 30, result, "Fold should combine 2 items: 10 + 20 = 30")
|
||||
})
|
||||
|
||||
t.Run("Fold with many items", func(t *testing.T) {
|
||||
many := From(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
fold := Fold[int](sumMonoid)
|
||||
result := fold(many)
|
||||
assert.Equal(t, 55, result, "Fold should combine many items: 1+2+3+4+5+6+7+8+9+10 = 55")
|
||||
})
|
||||
|
||||
t.Run("Fold with string concatenation - 0 items", func(t *testing.T) {
|
||||
empty := []string{}
|
||||
fold := Fold[string](S.Monoid)
|
||||
result := fold(empty)
|
||||
assert.Equal(t, "", result, "Fold should return empty string for 0 items")
|
||||
})
|
||||
|
||||
t.Run("Fold with string concatenation - 1 item", func(t *testing.T) {
|
||||
single := From("hello")
|
||||
fold := Fold[string](S.Monoid)
|
||||
result := fold(single)
|
||||
assert.Equal(t, "hello", result, "Fold should return single string")
|
||||
})
|
||||
|
||||
t.Run("Fold with string concatenation - 2 items", func(t *testing.T) {
|
||||
two := From("hello", "world")
|
||||
fold := Fold[string](S.Monoid)
|
||||
result := fold(two)
|
||||
assert.Equal(t, "helloworld", result, "Fold should concatenate 2 strings")
|
||||
})
|
||||
|
||||
t.Run("Fold with string concatenation - many items", func(t *testing.T) {
|
||||
many := From("a", "b", "c", "d", "e", "f")
|
||||
fold := Fold[string](S.Monoid)
|
||||
result := fold(many)
|
||||
assert.Equal(t, "abcdef", result, "Fold should concatenate many strings")
|
||||
})
|
||||
|
||||
t.Run("Fold with product monoid - 0 items", func(t *testing.T) {
|
||||
empty := []int{}
|
||||
productMonoid := N.MonoidProduct[int]()
|
||||
fold := Fold[int](productMonoid)
|
||||
result := fold(empty)
|
||||
assert.Equal(t, 1, result, "Fold should return monoid empty (1) for product with 0 items")
|
||||
})
|
||||
|
||||
t.Run("Fold with product monoid - 1 item", func(t *testing.T) {
|
||||
single := From(7)
|
||||
productMonoid := N.MonoidProduct[int]()
|
||||
fold := Fold[int](productMonoid)
|
||||
result := fold(single)
|
||||
assert.Equal(t, 7, result, "Fold should return single item for product")
|
||||
})
|
||||
|
||||
t.Run("Fold with product monoid - 2 items", func(t *testing.T) {
|
||||
two := From(3, 4)
|
||||
productMonoid := N.MonoidProduct[int]()
|
||||
fold := Fold[int](productMonoid)
|
||||
result := fold(two)
|
||||
assert.Equal(t, 12, result, "Fold should multiply 2 items: 3 * 4 = 12")
|
||||
})
|
||||
|
||||
t.Run("Fold with product monoid - many items", func(t *testing.T) {
|
||||
many := From(2, 3, 4, 5)
|
||||
productMonoid := N.MonoidProduct[int]()
|
||||
fold := Fold[int](productMonoid)
|
||||
result := fold(many)
|
||||
assert.Equal(t, 120, result, "Fold should multiply many items: 2*3*4*5 = 120")
|
||||
})
|
||||
}
|
||||
func TestFoldMapWithIndex(t *testing.T) {
|
||||
t.Run("FoldMapWithIndex with 0 items", func(t *testing.T) {
|
||||
empty := []int{}
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
foldMap := FoldMapWithIndex[int](sumMonoid)(func(i, x int) int { return i + x })
|
||||
result := foldMap(empty)
|
||||
assert.Equal(t, 0, result, "FoldMapWithIndex should return monoid empty for 0 items")
|
||||
})
|
||||
|
||||
t.Run("FoldMapWithIndex with 1 item", func(t *testing.T) {
|
||||
single := From(10)
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
foldMap := FoldMapWithIndex[int](sumMonoid)(func(i, x int) int { return i + x })
|
||||
result := foldMap(single)
|
||||
assert.Equal(t, 10, result, "FoldMapWithIndex should map with index: 0 + 10 = 10")
|
||||
})
|
||||
|
||||
t.Run("FoldMapWithIndex with 2 items", func(t *testing.T) {
|
||||
two := From(10, 20)
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
foldMap := FoldMapWithIndex[int](sumMonoid)(func(i, x int) int { return i + x })
|
||||
result := foldMap(two)
|
||||
assert.Equal(t, 31, result, "FoldMapWithIndex should map with indices: (0+10) + (1+20) = 31")
|
||||
})
|
||||
|
||||
t.Run("FoldMapWithIndex with many items", func(t *testing.T) {
|
||||
many := From(5, 10, 15, 20)
|
||||
sumMonoid := N.MonoidSum[int]()
|
||||
foldMap := FoldMapWithIndex[int](sumMonoid)(func(i, x int) int { return i * x })
|
||||
result := foldMap(many)
|
||||
assert.Equal(t, 100, result, "FoldMapWithIndex should map with indices: (0*5) + (1*10) + (2*15) + (3*20) = 100")
|
||||
})
|
||||
|
||||
t.Run("FoldMapWithIndex with string concatenation - 0 items", func(t *testing.T) {
|
||||
empty := []string{}
|
||||
foldMap := FoldMapWithIndex[string](S.Monoid)(func(i int, s string) string {
|
||||
return fmt.Sprintf("%d:%s", i, s)
|
||||
})
|
||||
result := foldMap(empty)
|
||||
assert.Equal(t, "", result, "FoldMapWithIndex should return empty string for 0 items")
|
||||
})
|
||||
|
||||
t.Run("FoldMapWithIndex with string concatenation - 1 item", func(t *testing.T) {
|
||||
single := From("a")
|
||||
foldMap := FoldMapWithIndex[string](S.Monoid)(func(i int, s string) string {
|
||||
return fmt.Sprintf("%d:%s", i, s)
|
||||
})
|
||||
result := foldMap(single)
|
||||
assert.Equal(t, "0:a", result, "FoldMapWithIndex should format single item with index")
|
||||
})
|
||||
|
||||
t.Run("FoldMapWithIndex with string concatenation - 2 items", func(t *testing.T) {
|
||||
two := From("a", "b")
|
||||
foldMap := FoldMapWithIndex[string](S.Monoid)(func(i int, s string) string {
|
||||
return fmt.Sprintf("%d:%s,", i, s)
|
||||
})
|
||||
result := foldMap(two)
|
||||
assert.Equal(t, "0:a,1:b,", result, "FoldMapWithIndex should format 2 items with indices")
|
||||
})
|
||||
|
||||
t.Run("FoldMapWithIndex with string concatenation - many items", func(t *testing.T) {
|
||||
many := From("a", "b", "c", "d")
|
||||
foldMap := FoldMapWithIndex[string](S.Monoid)(func(i int, s string) string {
|
||||
return fmt.Sprintf("[%d]%s", i, s)
|
||||
})
|
||||
result := foldMap(many)
|
||||
assert.Equal(t, "[0]a[1]b[2]c[3]d", result, "FoldMapWithIndex should format many items with indices")
|
||||
})
|
||||
}
|
||||
|
||||
func ExampleFoldMap() {
|
||||
|
||||
@@ -326,9 +326,18 @@ func FoldMap[AS ~[]A, A, B any](m M.Monoid[B]) func(func(A) B) func(AS) B {
|
||||
concat := m.Concat
|
||||
return func(f func(A) B) func(AS) B {
|
||||
return func(as AS) B {
|
||||
return array.Reduce(as, func(cur B, a A) B {
|
||||
return concat(cur, f(a))
|
||||
}, m.Empty())
|
||||
switch len(as) {
|
||||
case 0:
|
||||
return m.Empty()
|
||||
case 1:
|
||||
return f(as[0])
|
||||
case 2:
|
||||
return concat(f(as[0]), f(as[1]))
|
||||
default:
|
||||
return array.Reduce(as[1:], func(cur B, a A) B {
|
||||
return concat(cur, f(a))
|
||||
}, f(as[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,7 +356,16 @@ func FoldMapWithIndex[AS ~[]A, A, B any](m M.Monoid[B]) func(func(int, A) B) fun
|
||||
func Fold[AS ~[]A, A any](m M.Monoid[A]) func(AS) A {
|
||||
concat := m.Concat
|
||||
return func(as AS) A {
|
||||
return array.Reduce(as, concat, m.Empty())
|
||||
switch len(as) {
|
||||
case 0:
|
||||
return m.Empty()
|
||||
case 1:
|
||||
return as[0]
|
||||
case 2:
|
||||
return concat(as[0], as[1])
|
||||
default:
|
||||
return array.Reduce(as[1:], concat, as[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -748,6 +748,8 @@ func Read[A, C any](c C) func(Effect[C, A]) Thunk[A] {
|
||||
//
|
||||
// # See Also
|
||||
//
|
||||
// See Also:
|
||||
//
|
||||
// - Ask: Returns the entire context as the value
|
||||
// - Map: Transforms the value after extraction
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user