1
0
mirror of https://github.com/IBM/fp-go.git synced 2026-03-20 13:58:04 +02:00

Compare commits

..

5 Commits

Author SHA1 Message Date
Dr. Carsten Leue
62844b7030 fix: add Filter and FilterMap
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2026-03-15 23:33:08 +01:00
Dr. Carsten Leue
99a0ddd4b6 fix: implement filter and filtermap
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2026-03-15 23:18:14 +01:00
Dr. Carsten Leue
02acbae8f6 fix: add lenses for Hostname and Port
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2026-03-15 22:49:11 +01:00
Dr. Carsten Leue
eb27ecdc01 fix: clarify behaviour of array.Concat
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2026-03-13 18:39:55 +01:00
Dr. Carsten Leue
e5eb7d343c fix: add inline flags
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2026-03-13 09:26:39 +01:00
11 changed files with 845 additions and 617 deletions

View File

@@ -529,71 +529,116 @@ func Push[A any](a A) Operator[A, A] {
return G.Push[Operator[A, A]](a)
}
// Concat concatenates two arrays, appending the provided array to the end of the input array.
// This is a curried function that takes an array to append and returns a function that
// takes the base array and returns the concatenated result.
// Concat concatenates two arrays by appending a suffix array to a base array.
//
// The function creates a new array containing all elements from the base array followed
// by all elements from the appended array. Neither input array is modified.
// 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:
// - as: The array to append to the end of the base array
//
// - suffix: The array to append to the end of the base array
//
// Returns:
// - A function that takes a base array and returns a new array with `as` appended to its end
//
// - A function that takes a base array and returns [base... suffix...]
//
// Behavior:
// - Creates a new array with length equal to the sum of both input arrays
// - Copies all elements from the base array first
// - Appends all elements from the `as` array at the end
// - Returns the base array unchanged if `as` is empty
// - Returns `as` unchanged if the base array is empty
// - Does not modify either input array
//
// Example:
// - 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}
// toAppend := []int{4, 5, 6}
// result := array.Concat(toAppend)(base)
// 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)
// // toAppend: []int{4, 5, 6} (unchanged)
// // suffix: []int{4, 5, 6} (unchanged)
//
// Example with empty arrays:
// 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 with strings:
// Example - Strings:
//
// words1 := []string{"hello", "world"}
// words2 := []string{"foo", "bar"}
// result := array.Concat(words2)(words1)
// // result: []string{"hello", "world", "foo", "bar"}
//
// Example with functional composition:
// Example - Functional composition:
//
// numbers := []int{1, 2, 3}
// result := F.Pipe2(
// numbers,
// array.Map(N.Mul(2)),
// array.Concat([]int{10, 20}),
// array.Map(N.Mul(2)), // [2, 4, 6]
// array.Concat([]int{10, 20}), // [2, 4, 6, 10, 20]
// )
// // result: []int{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
// - Building arrays incrementally in pipelines
// - Implementing array-based data structures (queues, buffers)
// - Merging results from multiple operations
// - Creating array pipelines with functional composition
// - 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
@@ -601,9 +646,15 @@ func Push[A any](a A) Operator[A, A] {
// 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
//
//go:inline
func Concat[A any](as []A) Operator[A, A] {
return F.Bind2nd(array.Concat[[]A, A], as)
func Concat[A any](suffix []A) Operator[A, A] {
return F.Bind2nd(array.Concat[[]A, A], suffix)
}
// MonadFlap applies a value to an array of functions, producing an array of results.

View File

@@ -767,6 +767,25 @@ func TestExtendUseCases(t *testing.T) {
// TestConcat tests the Concat function
func TestConcat(t *testing.T) {
t.Run("Semantic: Concat(b)(a) produces [a... b...]", func(t *testing.T) {
a := []int{1, 2, 3}
b := []int{4, 5, 6}
// Concat(b)(a) should produce [a... b...]
result := Concat(b)(a)
expected := []int{1, 2, 3, 4, 5, 6}
assert.Equal(t, expected, result, "Concat(b)(a) should produce [a... b...]")
// Verify order: a's elements come first, then b's elements
assert.Equal(t, a[0], result[0], "First element should be from a")
assert.Equal(t, a[1], result[1], "Second element should be from a")
assert.Equal(t, a[2], result[2], "Third element should be from a")
assert.Equal(t, b[0], result[3], "Fourth element should be from b")
assert.Equal(t, b[1], result[4], "Fifth element should be from b")
assert.Equal(t, b[2], result[5], "Sixth element should be from b")
})
t.Run("Concat two non-empty arrays", func(t *testing.T) {
base := []int{1, 2, 3}
toAppend := []int{4, 5, 6}
@@ -870,6 +889,54 @@ func TestConcat(t *testing.T) {
expected := []int{1, 2, 3}
assert.Equal(t, expected, result)
})
t.Run("Explicit append semantic demonstration", func(t *testing.T) {
// Given a base array
base := []string{"A", "B", "C"}
// And a suffix to append
suffix := []string{"D", "E", "F"}
// When we apply Concat(suffix) to base
appendSuffix := Concat(suffix)
result := appendSuffix(base)
// Then the result should be base followed by suffix
expected := []string{"A", "B", "C", "D", "E", "F"}
assert.Equal(t, expected, result)
// And the base should be unchanged
assert.Equal(t, []string{"A", "B", "C"}, base)
// And the suffix should be unchanged
assert.Equal(t, []string{"D", "E", "F"}, suffix)
})
t.Run("Append semantic with different types", func(t *testing.T) {
// Integers
intResult := Concat([]int{4, 5})([]int{1, 2, 3})
assert.Equal(t, []int{1, 2, 3, 4, 5}, intResult)
// Strings
strResult := Concat([]string{"world"})([]string{"hello"})
assert.Equal(t, []string{"hello", "world"}, strResult)
// Floats
floatResult := Concat([]float64{3.3, 4.4})([]float64{1.1, 2.2})
assert.Equal(t, []float64{1.1, 2.2, 3.3, 4.4}, floatResult)
})
t.Run("Append semantic in pipeline", func(t *testing.T) {
// Start with [1, 2, 3]
// Append [4, 5] to get [1, 2, 3, 4, 5]
// Append [6, 7] to get [1, 2, 3, 4, 5, 6, 7]
result := F.Pipe2(
[]int{1, 2, 3},
Concat([]int{4, 5}),
Concat([]int{6, 7}),
)
expected := []int{1, 2, 3, 4, 5, 6, 7}
assert.Equal(t, expected, result)
})
}
// TestConcatComposition tests Concat with other array operations

View File

@@ -18,6 +18,10 @@ package readerioresult
import (
"context"
"github.com/IBM/fp-go/v2/array"
"github.com/IBM/fp-go/v2/internal/witherable"
"github.com/IBM/fp-go/v2/iterator/iter"
"github.com/IBM/fp-go/v2/option"
RIOR "github.com/IBM/fp-go/v2/readerioresult"
)
@@ -49,3 +53,43 @@ import (
func FilterOrElse[A any](pred Predicate[A], onFalse func(A) error) Operator[A, A] {
return RIOR.FilterOrElse[context.Context](pred, onFalse)
}
//go:inline
func Filter[A, HKTA any](
filter func(Predicate[A]) Endomorphism[HKTA],
) func(Predicate[A]) Operator[HKTA, HKTA] {
return witherable.Filter(
Map,
filter,
)
}
//go:inline
func FilterArray[A any](p Predicate[A]) Operator[[]A, []A] {
return Filter(array.Filter[A])(p)
}
//go:inline
func FilterIter[A any](p Predicate[A]) Operator[Seq[A], Seq[A]] {
return Filter(iter.Filter[A])(p)
}
//go:inline
func FilterMap[A, B, HKTA, HKTB any](
filter func(option.Kleisli[A, B]) Reader[HKTA, HKTB],
) func(option.Kleisli[A, B]) Operator[HKTA, HKTB] {
return witherable.FilterMap(
Map,
filter,
)
}
//go:inline
func FilterMapArray[A, B any](p option.Kleisli[A, B]) Operator[[]A, []B] {
return FilterMap(array.FilterMap[A, B])(p)
}
//go:inline
func FilterMapIter[A, B any](p option.Kleisli[A, B]) Operator[Seq[A], Seq[B]] {
return FilterMap(iter.FilterMap[A, B])(p)
}

View File

@@ -17,6 +17,7 @@ package readerioresult
import (
"context"
"iter"
"github.com/IBM/fp-go/v2/consumer"
"github.com/IBM/fp-go/v2/context/ioresult"
@@ -220,4 +221,6 @@ type (
// The first element is the CancelFunc that should be called to release resources.
// The second element is the new Context that was created.
ContextCancel = Pair[context.CancelFunc, context.Context]
Seq[A any] = iter.Seq[A]
)

View File

@@ -236,6 +236,7 @@ func Pipe4[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, T
// The final return value is the result of the last function application
//go:inline
func Flow4[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, T0, T1, T2, T3, T4 any](f1 F1, f2 F2, f3 F3, f4 F4) func(T0) T4 {
//go:inline
return func(t0 T0) T4 {
return Pipe4(t0, f1, f2, f3, f4)
}
@@ -302,6 +303,7 @@ func Pipe5[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F
// The final return value is the result of the last function application
//go:inline
func Flow5[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, T0, T1, T2, T3, T4, T5 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(T0) T5 {
//go:inline
return func(t0 T0) T5 {
return Pipe5(t0, f1, f2, f3, f4, f5)
}
@@ -370,6 +372,7 @@ func Pipe6[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F
// The final return value is the result of the last function application
//go:inline
func Flow6[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, T0, T1, T2, T3, T4, T5, T6 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6) func(T0) T6 {
//go:inline
return func(t0 T0) T6 {
return Pipe6(t0, f1, f2, f3, f4, f5, f6)
}
@@ -440,6 +443,7 @@ func Pipe7[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F
// The final return value is the result of the last function application
//go:inline
func Flow7[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, T0, T1, T2, T3, T4, T5, T6, T7 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7) func(T0) T7 {
//go:inline
return func(t0 T0) T7 {
return Pipe7(t0, f1, f2, f3, f4, f5, f6, f7)
}
@@ -512,6 +516,7 @@ func Pipe8[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F
// The final return value is the result of the last function application
//go:inline
func Flow8[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, T0, T1, T2, T3, T4, T5, T6, T7, T8 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8) func(T0) T8 {
//go:inline
return func(t0 T0) T8 {
return Pipe8(t0, f1, f2, f3, f4, f5, f6, f7, f8)
}
@@ -586,6 +591,7 @@ func Pipe9[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F
// The final return value is the result of the last function application
//go:inline
func Flow9[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9) func(T0) T9 {
//go:inline
return func(t0 T0) T9 {
return Pipe9(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9)
}
@@ -662,6 +668,7 @@ func Pipe10[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow10[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10) func(T0) T10 {
//go:inline
return func(t0 T0) T10 {
return Pipe10(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10)
}
@@ -740,6 +747,7 @@ func Pipe11[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow11[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, F11 ~func(T10) T11, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11) func(T0) T11 {
//go:inline
return func(t0 T0) T11 {
return Pipe11(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11)
}
@@ -820,6 +828,7 @@ func Pipe12[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow12[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, F11 ~func(T10) T11, F12 ~func(T11) T12, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12) func(T0) T12 {
//go:inline
return func(t0 T0) T12 {
return Pipe12(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12)
}
@@ -902,6 +911,7 @@ func Pipe13[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow13[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, F11 ~func(T10) T11, F12 ~func(T11) T12, F13 ~func(T12) T13, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13) func(T0) T13 {
//go:inline
return func(t0 T0) T13 {
return Pipe13(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13)
}
@@ -986,6 +996,7 @@ func Pipe14[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow14[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, F11 ~func(T10) T11, F12 ~func(T11) T12, F13 ~func(T12) T13, F14 ~func(T13) T14, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14) func(T0) T14 {
//go:inline
return func(t0 T0) T14 {
return Pipe14(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14)
}
@@ -1072,6 +1083,7 @@ func Pipe15[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow15[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, F11 ~func(T10) T11, F12 ~func(T11) T12, F13 ~func(T12) T13, F14 ~func(T13) T14, F15 ~func(T14) T15, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15) func(T0) T15 {
//go:inline
return func(t0 T0) T15 {
return Pipe15(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15)
}
@@ -1160,6 +1172,7 @@ func Pipe16[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow16[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, F11 ~func(T10) T11, F12 ~func(T11) T12, F13 ~func(T12) T13, F14 ~func(T13) T14, F15 ~func(T14) T15, F16 ~func(T15) T16, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15, f16 F16) func(T0) T16 {
//go:inline
return func(t0 T0) T16 {
return Pipe16(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16)
}
@@ -1250,6 +1263,7 @@ func Pipe17[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow17[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, F11 ~func(T10) T11, F12 ~func(T11) T12, F13 ~func(T12) T13, F14 ~func(T13) T14, F15 ~func(T14) T15, F16 ~func(T15) T16, F17 ~func(T16) T17, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15, f16 F16, f17 F17) func(T0) T17 {
//go:inline
return func(t0 T0) T17 {
return Pipe17(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17)
}
@@ -1342,6 +1356,7 @@ func Pipe18[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow18[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, F11 ~func(T10) T11, F12 ~func(T11) T12, F13 ~func(T12) T13, F14 ~func(T13) T14, F15 ~func(T14) T15, F16 ~func(T15) T16, F17 ~func(T16) T17, F18 ~func(T17) T18, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15, f16 F16, f17 F17, f18 F18) func(T0) T18 {
//go:inline
return func(t0 T0) T18 {
return Pipe18(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18)
}
@@ -1436,6 +1451,7 @@ func Pipe19[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow19[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, F11 ~func(T10) T11, F12 ~func(T11) T12, F13 ~func(T12) T13, F14 ~func(T13) T14, F15 ~func(T14) T15, F16 ~func(T15) T16, F17 ~func(T16) T17, F18 ~func(T17) T18, F19 ~func(T18) T19, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15, f16 F16, f17 F17, f18 F18, f19 F19) func(T0) T19 {
//go:inline
return func(t0 T0) T19 {
return Pipe19(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19)
}
@@ -1532,6 +1548,7 @@ func Pipe20[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
// The final return value is the result of the last function application
//go:inline
func Flow20[F1 ~func(T0) T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4, F5 ~func(T4) T5, F6 ~func(T5) T6, F7 ~func(T6) T7, F8 ~func(T7) T8, F9 ~func(T8) T9, F10 ~func(T9) T10, F11 ~func(T10) T11, F12 ~func(T11) T12, F13 ~func(T12) T13, F14 ~func(T13) T14, F15 ~func(T14) T15, F16 ~func(T15) T16, F17 ~func(T16) T17, F18 ~func(T17) T18, F19 ~func(T18) T19, F20 ~func(T19) T20, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15, f16 F16, f17 F17, f18 F18, f19 F19, f20 F20) func(T0) T20 {
//go:inline
return func(t0 T0) T20 {
return Pipe20(t0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20)
}

View File

@@ -0,0 +1,15 @@
package filterable
import (
"github.com/IBM/fp-go/v2/option"
"github.com/IBM/fp-go/v2/pair"
)
type (
Option[A any] = option.Option[A]
Separated[A, B any] = pair.Pair[A, B]
FilterType[A, HKTA any] = func(func(A) bool) func(HKTA) HKTA
FilterMapType[A, B, HKTA, HKTB any] = func(func(A) Option[B]) func(HKTA) HKTB
)

View File

@@ -0,0 +1,27 @@
package witherable
import (
"github.com/IBM/fp-go/v2/function"
"github.com/IBM/fp-go/v2/internal/filterable"
"github.com/IBM/fp-go/v2/internal/functor"
)
func Filter[A, HKT_G_A, HKT_F_HKT_G_A any](
fmap functor.MapType[HKT_G_A, HKT_G_A, HKT_F_HKT_G_A, HKT_F_HKT_G_A],
ffilter filterable.FilterType[A, HKT_G_A],
) func(func(A) bool) func(HKT_F_HKT_G_A) HKT_F_HKT_G_A {
return function.Flow2(
ffilter,
fmap,
)
}
func FilterMap[A, B, HKT_G_A, HKT_G_B, HKT_F_HKT_G_A, HKT_F_HKT_G_B any](
fmap functor.MapType[HKT_G_A, HKT_G_B, HKT_F_HKT_G_A, HKT_F_HKT_G_B],
ffilter filterable.FilterMapType[A, B, HKT_G_A, HKT_G_B],
) func(func(A) Option[B]) func(HKT_F_HKT_G_A) HKT_F_HKT_G_B {
return function.Flow2(
ffilter,
fmap,
)
}

View File

@@ -0,0 +1 @@
package witherable

View File

@@ -0,0 +1,7 @@
package witherable
import "github.com/IBM/fp-go/v2/option"
type (
Option[A any] = option.Option[A]
)

View File

@@ -5,6 +5,7 @@ package lenses
// 2026-01-27 16:08:47.5483589 +0100 CET m=+0.003380301
import (
"net"
url "net/url"
__iso_option "github.com/IBM/fp-go/v2/optics/iso/option"
@@ -119,6 +120,8 @@ type URLLenses struct {
RawQuery __lens.Lens[url.URL, string]
Fragment __lens.Lens[url.URL, string]
RawFragment __lens.Lens[url.URL, string]
Hostname __lens.Lens[url.URL, string]
Port __lens.Lens[url.URL, string]
// optional fields
SchemeO __lens_option.LensO[url.URL, string]
OpaqueO __lens_option.LensO[url.URL, string]
@@ -131,6 +134,8 @@ type URLLenses struct {
RawQueryO __lens_option.LensO[url.URL, string]
FragmentO __lens_option.LensO[url.URL, string]
RawFragmentO __lens_option.LensO[url.URL, string]
HostnameO __lens_option.LensO[url.URL, string]
PortO __lens_option.LensO[url.URL, string]
}
// URLRefLenses provides lenses for accessing fields of url.URL via a reference to url.URL
@@ -147,6 +152,8 @@ type URLRefLenses struct {
RawQuery __lens.Lens[*url.URL, string]
Fragment __lens.Lens[*url.URL, string]
RawFragment __lens.Lens[*url.URL, string]
Hostname __lens.Lens[*url.URL, string]
Port __lens.Lens[*url.URL, string]
// optional fields
SchemeO __lens_option.LensO[*url.URL, string]
OpaqueO __lens_option.LensO[*url.URL, string]
@@ -159,6 +166,8 @@ type URLRefLenses struct {
RawQueryO __lens_option.LensO[*url.URL, string]
FragmentO __lens_option.LensO[*url.URL, string]
RawFragmentO __lens_option.LensO[*url.URL, string]
HostnameO __lens_option.LensO[*url.URL, string]
PortO __lens_option.LensO[*url.URL, string]
}
// MakeURLLenses creates a new URLLenses with lenses for all fields
@@ -219,6 +228,38 @@ func MakeURLLenses() URLLenses {
func(s url.URL, v string) url.URL { s.RawFragment = v; return s },
"URL.RawFragment",
)
lensHostname := __lens.MakeLensWithName(
func(s url.URL) string {
host, _, err := net.SplitHostPort(s.Host)
if err != nil {
return s.Host
}
return host
},
func(s url.URL, v string) url.URL {
_, port, err := net.SplitHostPort(s.Host)
if err != nil {
s.Host = v
} else {
s.Host = net.JoinHostPort(v, port)
}
return s
},
"URL.Hostname",
)
lensPort := __lens.MakeLensWithName(
func(s url.URL) string { return s.Port() },
func(s url.URL, v string) url.URL {
host, _, err := net.SplitHostPort(s.Host)
if err != nil {
s.Host = net.JoinHostPort(s.Host, v)
} else {
s.Host = net.JoinHostPort(host, v)
}
return s
},
"URL.Port",
)
// optional lenses
lensSchemeO := __lens_option.FromIso[url.URL](__iso_option.FromZero[string]())(lensScheme)
lensOpaqueO := __lens_option.FromIso[url.URL](__iso_option.FromZero[string]())(lensOpaque)
@@ -231,6 +272,8 @@ func MakeURLLenses() URLLenses {
lensRawQueryO := __lens_option.FromIso[url.URL](__iso_option.FromZero[string]())(lensRawQuery)
lensFragmentO := __lens_option.FromIso[url.URL](__iso_option.FromZero[string]())(lensFragment)
lensRawFragmentO := __lens_option.FromIso[url.URL](__iso_option.FromZero[string]())(lensRawFragment)
lensHostnameO := __lens_option.FromIso[url.URL](__iso_option.FromZero[string]())(lensHostname)
lensPortO := __lens_option.FromIso[url.URL](__iso_option.FromZero[string]())(lensPort)
return URLLenses{
// mandatory lenses
Scheme: lensScheme,
@@ -244,6 +287,8 @@ func MakeURLLenses() URLLenses {
RawQuery: lensRawQuery,
Fragment: lensFragment,
RawFragment: lensRawFragment,
Hostname: lensHostname,
Port: lensPort,
// optional lenses
SchemeO: lensSchemeO,
OpaqueO: lensOpaqueO,
@@ -256,6 +301,8 @@ func MakeURLLenses() URLLenses {
RawQueryO: lensRawQueryO,
FragmentO: lensFragmentO,
RawFragmentO: lensRawFragmentO,
HostnameO: lensHostnameO,
PortO: lensPortO,
}
}
@@ -317,6 +364,38 @@ func MakeURLRefLenses() URLRefLenses {
func(s *url.URL, v string) *url.URL { s.RawFragment = v; return s },
"(*url.URL).RawFragment",
)
lensHostname := __lens.MakeLensStrictWithName(
func(s *url.URL) string {
host, _, err := net.SplitHostPort(s.Host)
if err != nil {
return s.Host
}
return host
},
func(s *url.URL, v string) *url.URL {
_, port, err := net.SplitHostPort(s.Host)
if err != nil {
s.Host = v
} else {
s.Host = net.JoinHostPort(v, port)
}
return s
},
"URL.Hostname",
)
lensPort := __lens.MakeLensStrictWithName(
(*url.URL).Port,
func(s *url.URL, v string) *url.URL {
host, _, err := net.SplitHostPort(s.Host)
if err != nil {
s.Host = net.JoinHostPort(s.Host, v)
} else {
s.Host = net.JoinHostPort(host, v)
}
return s
},
"URL.Port",
)
// optional lenses
lensSchemeO := __lens_option.FromIso[*url.URL](__iso_option.FromZero[string]())(lensScheme)
lensOpaqueO := __lens_option.FromIso[*url.URL](__iso_option.FromZero[string]())(lensOpaque)
@@ -329,6 +408,8 @@ func MakeURLRefLenses() URLRefLenses {
lensRawQueryO := __lens_option.FromIso[*url.URL](__iso_option.FromZero[string]())(lensRawQuery)
lensFragmentO := __lens_option.FromIso[*url.URL](__iso_option.FromZero[string]())(lensFragment)
lensRawFragmentO := __lens_option.FromIso[*url.URL](__iso_option.FromZero[string]())(lensRawFragment)
lensHostnameO := __lens_option.FromIso[*url.URL](__iso_option.FromZero[string]())(lensHostname)
lensPortO := __lens_option.FromIso[*url.URL](__iso_option.FromZero[string]())(lensPort)
return URLRefLenses{
// mandatory lenses
Scheme: lensScheme,
@@ -342,6 +423,8 @@ func MakeURLRefLenses() URLRefLenses {
RawQuery: lensRawQuery,
Fragment: lensFragment,
RawFragment: lensRawFragment,
Hostname: lensHostname,
Port: lensPort,
// optional lenses
SchemeO: lensSchemeO,
OpaqueO: lensOpaqueO,
@@ -354,6 +437,8 @@ func MakeURLRefLenses() URLRefLenses {
RawQueryO: lensRawQueryO,
FragmentO: lensFragmentO,
RawFragmentO: lensRawFragmentO,
HostnameO: lensHostnameO,
PortO: lensPortO,
}
}

File diff suppressed because it is too large Load Diff