mirror of
https://github.com/IBM/fp-go.git
synced 2025-11-29 22:38:29 +02:00
fix: traverse
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
@@ -260,6 +260,8 @@ func Empty[A any]() []A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Zero returns an empty array of type A (alias for Empty).
|
// Zero returns an empty array of type A (alias for Empty).
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
func Zero[A any]() []A {
|
func Zero[A any]() []A {
|
||||||
return Empty[A]()
|
return Empty[A]()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Of constructs a single element array
|
// Of constructs a single element array
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
func Of[GA ~[]A, A any](value A) GA {
|
func Of[GA ~[]A, A any](value A) GA {
|
||||||
return GA{value}
|
return array.Of[GA](value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Reduce[GA ~[]A, A, B any](f func(B, A) B, initial B) func(GA) B {
|
func Reduce[GA ~[]A, A, B any](f func(B, A) B, initial B) func(GA) B {
|
||||||
|
|||||||
34
v2/array/generic/monoid.go
Normal file
34
v2/array/generic/monoid.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package generic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IBM/fp-go/v2/internal/array"
|
||||||
|
M "github.com/IBM/fp-go/v2/monoid"
|
||||||
|
S "github.com/IBM/fp-go/v2/semigroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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() // []
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
|
func Monoid[GT ~[]T, T any]() M.Monoid[GT] {
|
||||||
|
return M.MakeMonoid(array.Concat[GT], Empty[GT]())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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]
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
|
func Semigroup[GT ~[]T, T any]() S.Semigroup[GT] {
|
||||||
|
return S.MakeSemigroup(array.Concat[GT])
|
||||||
|
}
|
||||||
@@ -18,7 +18,6 @@ package array
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
O "github.com/IBM/fp-go/v2/option"
|
|
||||||
OR "github.com/IBM/fp-go/v2/ord"
|
OR "github.com/IBM/fp-go/v2/ord"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -103,39 +102,6 @@ func TestSortByKey(t *testing.T) {
|
|||||||
assert.Equal(t, "Charlie", result[2].Name)
|
assert.Equal(t, "Charlie", result[2].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMonadTraverse(t *testing.T) {
|
|
||||||
result := MonadTraverse(
|
|
||||||
O.Of[[]int],
|
|
||||||
O.Map[[]int, func(int) []int],
|
|
||||||
O.Ap[[]int, int],
|
|
||||||
[]int{1, 3, 5},
|
|
||||||
func(n int) O.Option[int] {
|
|
||||||
if n%2 == 1 {
|
|
||||||
return O.Some(n * 2)
|
|
||||||
}
|
|
||||||
return O.None[int]()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, O.Some([]int{2, 6, 10}), result)
|
|
||||||
|
|
||||||
// Test with None case
|
|
||||||
result2 := MonadTraverse(
|
|
||||||
O.Of[[]int],
|
|
||||||
O.Map[[]int, func(int) []int],
|
|
||||||
O.Ap[[]int, int],
|
|
||||||
[]int{1, 2, 3},
|
|
||||||
func(n int) O.Option[int] {
|
|
||||||
if n%2 == 1 {
|
|
||||||
return O.Some(n * 2)
|
|
||||||
}
|
|
||||||
return O.None[int]()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, O.None[[]int](), result2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUniqByKey(t *testing.T) {
|
func TestUniqByKey(t *testing.T) {
|
||||||
type Person struct {
|
type Person struct {
|
||||||
Name string
|
Name string
|
||||||
|
|||||||
@@ -16,27 +16,12 @@
|
|||||||
package array
|
package array
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
G "github.com/IBM/fp-go/v2/array/generic"
|
||||||
"github.com/IBM/fp-go/v2/internal/array"
|
"github.com/IBM/fp-go/v2/internal/array"
|
||||||
M "github.com/IBM/fp-go/v2/monoid"
|
M "github.com/IBM/fp-go/v2/monoid"
|
||||||
S "github.com/IBM/fp-go/v2/semigroup"
|
S "github.com/IBM/fp-go/v2/semigroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
func concat[T any](left, right []T) []T {
|
|
||||||
// some performance checks
|
|
||||||
ll := len(left)
|
|
||||||
if ll == 0 {
|
|
||||||
return right
|
|
||||||
}
|
|
||||||
lr := len(right)
|
|
||||||
if lr == 0 {
|
|
||||||
return left
|
|
||||||
}
|
|
||||||
// need to copy
|
|
||||||
buf := make([]T, ll+lr)
|
|
||||||
copy(buf[copy(buf, left):], right)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
|
|
||||||
// Monoid returns a Monoid instance for arrays.
|
// Monoid returns a Monoid instance for arrays.
|
||||||
// The Monoid combines arrays through concatenation, with an empty array as the identity element.
|
// The Monoid combines arrays through concatenation, with an empty array as the identity element.
|
||||||
//
|
//
|
||||||
@@ -45,8 +30,10 @@ func concat[T any](left, right []T) []T {
|
|||||||
// m := array.Monoid[int]()
|
// m := array.Monoid[int]()
|
||||||
// result := m.Concat([]int{1, 2}, []int{3, 4}) // [1, 2, 3, 4]
|
// result := m.Concat([]int{1, 2}, []int{3, 4}) // [1, 2, 3, 4]
|
||||||
// empty := m.Empty() // []
|
// empty := m.Empty() // []
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
func Monoid[T any]() M.Monoid[[]T] {
|
func Monoid[T any]() M.Monoid[[]T] {
|
||||||
return M.MakeMonoid(concat[T], Empty[T]())
|
return G.Monoid[[]T]()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Semigroup returns a Semigroup instance for arrays.
|
// Semigroup returns a Semigroup instance for arrays.
|
||||||
@@ -56,8 +43,10 @@ func Monoid[T any]() M.Monoid[[]T] {
|
|||||||
//
|
//
|
||||||
// s := array.Semigroup[int]()
|
// s := array.Semigroup[int]()
|
||||||
// result := s.Concat([]int{1, 2}, []int{3, 4}) // [1, 2, 3, 4]
|
// result := s.Concat([]int{1, 2}, []int{3, 4}) // [1, 2, 3, 4]
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
func Semigroup[T any]() S.Semigroup[[]T] {
|
func Semigroup[T any]() S.Semigroup[[]T] {
|
||||||
return S.MakeSemigroup(concat[T])
|
return G.Semigroup[[]T]()
|
||||||
}
|
}
|
||||||
|
|
||||||
func addLen[A any](count int, data []A) int {
|
func addLen[A any](count int, data []A) int {
|
||||||
|
|||||||
@@ -16,10 +16,18 @@
|
|||||||
package array
|
package array
|
||||||
|
|
||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/v2/function"
|
"github.com/IBM/fp-go/v2/internal/array"
|
||||||
|
M "github.com/IBM/fp-go/v2/monoid"
|
||||||
O "github.com/IBM/fp-go/v2/option"
|
O "github.com/IBM/fp-go/v2/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func MonadSequence[HKTA, HKTRA any](
|
||||||
|
fof func(HKTA) HKTRA,
|
||||||
|
m M.Monoid[HKTRA],
|
||||||
|
ma []HKTA) HKTRA {
|
||||||
|
return array.MonadSequence(fof, m.Empty(), m.Concat, ma)
|
||||||
|
}
|
||||||
|
|
||||||
// Sequence takes an array where elements are HKT<A> (higher kinded type) and,
|
// Sequence takes an array where elements are HKT<A> (higher kinded type) and,
|
||||||
// using an applicative of that HKT, returns an HKT of []A.
|
// using an applicative of that HKT, returns an HKT of []A.
|
||||||
//
|
//
|
||||||
@@ -55,16 +63,11 @@ import (
|
|||||||
// option.MonadAp[[]int, int],
|
// option.MonadAp[[]int, int],
|
||||||
// )
|
// )
|
||||||
// result := seq(opts) // Some([1, 2, 3])
|
// result := seq(opts) // Some([1, 2, 3])
|
||||||
func Sequence[A, HKTA, HKTRA, HKTFRA any](
|
func Sequence[HKTA, HKTRA any](
|
||||||
_of func([]A) HKTRA,
|
fof func(HKTA) HKTRA,
|
||||||
_map func(HKTRA, func([]A) func(A) []A) HKTFRA,
|
m M.Monoid[HKTRA],
|
||||||
_ap func(HKTFRA, HKTA) HKTRA,
|
|
||||||
) func([]HKTA) HKTRA {
|
) func([]HKTA) HKTRA {
|
||||||
ca := F.Curry2(Append[A])
|
return array.Sequence[[]HKTA](fof, m.Empty(), m.Concat)
|
||||||
empty := _of(Empty[A]())
|
|
||||||
return Reduce(func(fas HKTRA, fa HKTA) HKTRA {
|
|
||||||
return _ap(_map(fas, ca), fa)
|
|
||||||
}, empty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArrayOption returns a function to convert a sequence of options into an option of a sequence.
|
// ArrayOption returns a function to convert a sequence of options into an option of a sequence.
|
||||||
@@ -86,10 +89,10 @@ func Sequence[A, HKTA, HKTRA, HKTFRA any](
|
|||||||
// option.Some(3),
|
// option.Some(3),
|
||||||
// }
|
// }
|
||||||
// result2 := array.ArrayOption[int]()(opts2) // None
|
// result2 := array.ArrayOption[int]()(opts2) // None
|
||||||
func ArrayOption[A any]() func([]Option[A]) Option[[]A] {
|
func ArrayOption[A any](ma []Option[A]) Option[[]A] {
|
||||||
return Sequence(
|
return MonadSequence(
|
||||||
O.Of[[]A],
|
O.Map(Of[A]),
|
||||||
O.MonadMap[[]A, func(A) []A],
|
O.ApplicativeMonoid(Monoid[A]()),
|
||||||
O.MonadAp[[]A, A],
|
ma,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestSequenceOption(t *testing.T) {
|
func TestSequenceOption(t *testing.T) {
|
||||||
seq := ArrayOption[int]()
|
|
||||||
|
|
||||||
assert.Equal(t, O.Of([]int{1, 3}), seq([]O.Option[int]{O.Of(1), O.Of(3)}))
|
assert.Equal(t, O.Of([]int{1, 3}), ArrayOption([]O.Option[int]{O.Of(1), O.Of(3)}))
|
||||||
assert.Equal(t, O.None[[]int](), seq([]O.Option[int]{O.Of(1), O.None[int]()}))
|
assert.Equal(t, O.None[[]int](), ArrayOption([]O.Option[int]{O.Of(1), O.None[int]()}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,3 +80,25 @@ func MonadTraverse[A, B, HKTB, HKTAB, HKTRB any](
|
|||||||
|
|
||||||
return array.MonadTraverse(fof, fmap, fap, ta, f)
|
return array.MonadTraverse(fof, fmap, fap, ta, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func TraverseWithIndex[A, B, HKTB, HKTAB, HKTRB any](
|
||||||
|
fof func([]B) HKTRB,
|
||||||
|
fmap func(func([]B) func(B) []B) func(HKTRB) HKTAB,
|
||||||
|
fap func(HKTB) func(HKTAB) HKTRB,
|
||||||
|
|
||||||
|
f func(int, A) HKTB) func([]A) HKTRB {
|
||||||
|
return array.TraverseWithIndex[[]A](fof, fmap, fap, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func MonadTraverseWithIndex[A, B, HKTB, HKTAB, HKTRB any](
|
||||||
|
fof func([]B) HKTRB,
|
||||||
|
fmap func(func([]B) func(B) []B) func(HKTRB) HKTAB,
|
||||||
|
fap func(HKTB) func(HKTAB) HKTRB,
|
||||||
|
|
||||||
|
ta []A,
|
||||||
|
f func(int, A) HKTB) HKTRB {
|
||||||
|
|
||||||
|
return array.MonadTraverseWithIndex(fof, fmap, fap, ta, f)
|
||||||
|
}
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ func TestMonadChainFirstLeft(t *testing.T) {
|
|||||||
Left[int](originalErr),
|
Left[int](originalErr),
|
||||||
func(e error) ReaderIOResult[int] {
|
func(e error) ReaderIOResult[int] {
|
||||||
capturedError = e
|
capturedError = e
|
||||||
return Right[int](999) // This Right value is ignored
|
return Right(999) // This Right value is ignored
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
actualResult := result(ctx)()
|
actualResult := result(ctx)()
|
||||||
@@ -324,7 +324,7 @@ func TestMonadChainFirstLeft(t *testing.T) {
|
|||||||
t.Run("Right value passes through", func(t *testing.T) {
|
t.Run("Right value passes through", func(t *testing.T) {
|
||||||
sideEffectCalled := false
|
sideEffectCalled := false
|
||||||
result := MonadChainFirstLeft(
|
result := MonadChainFirstLeft(
|
||||||
Right[int](42),
|
Right(42),
|
||||||
func(e error) ReaderIOResult[int] {
|
func(e error) ReaderIOResult[int] {
|
||||||
sideEffectCalled = true
|
sideEffectCalled = true
|
||||||
return Left[int](fmt.Errorf("should not be called"))
|
return Left[int](fmt.Errorf("should not be called"))
|
||||||
@@ -343,7 +343,7 @@ func TestMonadChainFirstLeft(t *testing.T) {
|
|||||||
func(e error) ReaderIOResult[int] {
|
func(e error) ReaderIOResult[int] {
|
||||||
effectCount++
|
effectCount++
|
||||||
// Try to return Right, but original Left should still be returned
|
// Try to return Right, but original Left should still be returned
|
||||||
return Right[int](999)
|
return Right(999)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
actualResult := result(ctx)()
|
actualResult := result(ctx)()
|
||||||
@@ -378,7 +378,7 @@ func TestChainFirstLeft(t *testing.T) {
|
|||||||
originalErr := fmt.Errorf("test error")
|
originalErr := fmt.Errorf("test error")
|
||||||
chainFn := ChainFirstLeft[int](func(e error) ReaderIOResult[int] {
|
chainFn := ChainFirstLeft[int](func(e error) ReaderIOResult[int] {
|
||||||
captured = e
|
captured = e
|
||||||
return Right[int](42) // This Right is ignored
|
return Right(42) // This Right is ignored
|
||||||
})
|
})
|
||||||
result := F.Pipe1(
|
result := F.Pipe1(
|
||||||
Left[int](originalErr),
|
Left[int](originalErr),
|
||||||
@@ -394,10 +394,10 @@ func TestChainFirstLeft(t *testing.T) {
|
|||||||
called := false
|
called := false
|
||||||
chainFn := ChainFirstLeft[int](func(e error) ReaderIOResult[int] {
|
chainFn := ChainFirstLeft[int](func(e error) ReaderIOResult[int] {
|
||||||
called = true
|
called = true
|
||||||
return Right[int](0)
|
return Right(0)
|
||||||
})
|
})
|
||||||
result := F.Pipe1(
|
result := F.Pipe1(
|
||||||
Right[int](100),
|
Right(100),
|
||||||
chainFn,
|
chainFn,
|
||||||
)
|
)
|
||||||
assert.False(t, called)
|
assert.False(t, called)
|
||||||
@@ -409,7 +409,7 @@ func TestChainFirstLeft(t *testing.T) {
|
|||||||
originalErr := fmt.Errorf("original")
|
originalErr := fmt.Errorf("original")
|
||||||
chainFn := ChainFirstLeft[int](func(e error) ReaderIOResult[int] {
|
chainFn := ChainFirstLeft[int](func(e error) ReaderIOResult[int] {
|
||||||
// Try to return Right, but original Left should still be returned
|
// Try to return Right, but original Left should still be returned
|
||||||
return Right[int](999)
|
return Right(999)
|
||||||
})
|
})
|
||||||
|
|
||||||
result := F.Pipe1(
|
result := F.Pipe1(
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
package readerioresult
|
package readerioresult
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/IBM/fp-go/v2/array"
|
||||||
"github.com/IBM/fp-go/v2/function"
|
"github.com/IBM/fp-go/v2/function"
|
||||||
"github.com/IBM/fp-go/v2/internal/array"
|
|
||||||
"github.com/IBM/fp-go/v2/internal/record"
|
"github.com/IBM/fp-go/v2/internal/record"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ import (
|
|||||||
//
|
//
|
||||||
// Returns a function that transforms an array into a ReaderIOResult of an array.
|
// Returns a function that transforms an array into a ReaderIOResult of an array.
|
||||||
func TraverseArray[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
func TraverseArray[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
||||||
return array.Traverse[[]A](
|
return array.Traverse(
|
||||||
Of[[]B],
|
Of[[]B],
|
||||||
Map[[]B, func(B) []B],
|
Map[[]B, func(B) []B],
|
||||||
Ap[[]B, B],
|
Ap[[]B, B],
|
||||||
@@ -46,7 +46,7 @@ func TraverseArray[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
|||||||
//
|
//
|
||||||
// Returns a function that transforms an array into a ReaderIOResult of an array.
|
// Returns a function that transforms an array into a ReaderIOResult of an array.
|
||||||
func TraverseArrayWithIndex[A, B any](f func(int, A) ReaderIOResult[B]) Kleisli[[]A, []B] {
|
func TraverseArrayWithIndex[A, B any](f func(int, A) ReaderIOResult[B]) Kleisli[[]A, []B] {
|
||||||
return array.TraverseWithIndex[[]A](
|
return array.TraverseWithIndex(
|
||||||
Of[[]B],
|
Of[[]B],
|
||||||
Map[[]B, func(B) []B],
|
Map[[]B, func(B) []B],
|
||||||
Ap[[]B, B],
|
Ap[[]B, B],
|
||||||
@@ -135,22 +135,20 @@ func MonadTraverseArraySeq[A, B any](as []A, f Kleisli[A, B]) ReaderIOResult[[]B
|
|||||||
//
|
//
|
||||||
// Returns a function that transforms an array into a ReaderIOResult of an array.
|
// Returns a function that transforms an array into a ReaderIOResult of an array.
|
||||||
func TraverseArraySeq[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
func TraverseArraySeq[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
||||||
return array.Traverse[[]A](
|
return array.Traverse(
|
||||||
Of[[]B],
|
Of[[]B],
|
||||||
Map[[]B, func(B) []B],
|
Map[[]B, func(B) []B],
|
||||||
ApSeq[[]B, B],
|
ApSeq[[]B, B],
|
||||||
|
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TraverseArrayWithIndexSeq uses transforms an array [[]A] into [[]ReaderIOResult[B]] and then resolves that into a [ReaderIOResult[[]B]]
|
// TraverseArrayWithIndexSeq uses transforms an array [[]A] into [[]ReaderIOResult[B]] and then resolves that into a [ReaderIOResult[[]B]]
|
||||||
func TraverseArrayWithIndexSeq[A, B any](f func(int, A) ReaderIOResult[B]) Kleisli[[]A, []B] {
|
func TraverseArrayWithIndexSeq[A, B any](f func(int, A) ReaderIOResult[B]) Kleisli[[]A, []B] {
|
||||||
return array.TraverseWithIndex[[]A](
|
return array.TraverseWithIndex(
|
||||||
Of[[]B],
|
Of[[]B],
|
||||||
Map[[]B, func(B) []B],
|
Map[[]B, func(B) []B],
|
||||||
ApSeq[[]B, B],
|
ApSeq[[]B, B],
|
||||||
|
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -230,22 +228,20 @@ func MonadTraverseArrayPar[A, B any](as []A, f Kleisli[A, B]) ReaderIOResult[[]B
|
|||||||
//
|
//
|
||||||
// Returns a function that transforms an array into a ReaderIOResult of an array.
|
// Returns a function that transforms an array into a ReaderIOResult of an array.
|
||||||
func TraverseArrayPar[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
func TraverseArrayPar[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
||||||
return array.Traverse[[]A](
|
return array.Traverse(
|
||||||
Of[[]B],
|
Of[[]B],
|
||||||
Map[[]B, func(B) []B],
|
Map[[]B, func(B) []B],
|
||||||
ApPar[[]B, B],
|
ApPar[[]B, B],
|
||||||
|
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TraverseArrayWithIndexPar uses transforms an array [[]A] into [[]ReaderIOResult[B]] and then resolves that into a [ReaderIOResult[[]B]]
|
// TraverseArrayWithIndexPar uses transforms an array [[]A] into [[]ReaderIOResult[B]] and then resolves that into a [ReaderIOResult[[]B]]
|
||||||
func TraverseArrayWithIndexPar[A, B any](f func(int, A) ReaderIOResult[B]) Kleisli[[]A, []B] {
|
func TraverseArrayWithIndexPar[A, B any](f func(int, A) ReaderIOResult[B]) Kleisli[[]A, []B] {
|
||||||
return array.TraverseWithIndex[[]A](
|
return array.TraverseWithIndex(
|
||||||
Of[[]B],
|
Of[[]B],
|
||||||
Map[[]B, func(B) []B],
|
Map[[]B, func(B) []B],
|
||||||
ApPar[[]B, B],
|
ApPar[[]B, B],
|
||||||
|
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,10 @@
|
|||||||
|
|
||||||
package array
|
package array
|
||||||
|
|
||||||
|
func Of[GA ~[]A, A any](a A) GA {
|
||||||
|
return GA{a}
|
||||||
|
}
|
||||||
|
|
||||||
func Slice[GA ~[]A, A any](low, high int) func(as GA) GA {
|
func Slice[GA ~[]A, A any](low, high int) func(as GA) GA {
|
||||||
return func(as GA) GA {
|
return func(as GA) GA {
|
||||||
length := len(as)
|
length := len(as)
|
||||||
@@ -140,7 +144,7 @@ func UpsertAt[GA ~[]A, A any](a A) func(GA) GA {
|
|||||||
func MonadMap[GA ~[]A, GB ~[]B, A, B any](as GA, f func(a A) B) GB {
|
func MonadMap[GA ~[]A, GB ~[]B, A, B any](as GA, f func(a A) B) GB {
|
||||||
count := len(as)
|
count := len(as)
|
||||||
bs := make(GB, count)
|
bs := make(GB, count)
|
||||||
for i := count - 1; i >= 0; i-- {
|
for i := range count {
|
||||||
bs[i] = f(as[i])
|
bs[i] = f(as[i])
|
||||||
}
|
}
|
||||||
return bs
|
return bs
|
||||||
@@ -155,7 +159,7 @@ func Map[GA ~[]A, GB ~[]B, A, B any](f func(a A) B) func(GA) GB {
|
|||||||
func MonadMapWithIndex[GA ~[]A, GB ~[]B, A, B any](as GA, f func(idx int, a A) B) GB {
|
func MonadMapWithIndex[GA ~[]A, GB ~[]B, A, B any](as GA, f func(idx int, a A) B) GB {
|
||||||
count := len(as)
|
count := len(as)
|
||||||
bs := make(GB, count)
|
bs := make(GB, count)
|
||||||
for i := count - 1; i >= 0; i-- {
|
for i := range count {
|
||||||
bs[i] = f(i, as[i])
|
bs[i] = f(i, as[i])
|
||||||
}
|
}
|
||||||
return bs
|
return bs
|
||||||
@@ -164,3 +168,19 @@ func MonadMapWithIndex[GA ~[]A, GB ~[]B, A, B any](as GA, f func(idx int, a A) B
|
|||||||
func ConstNil[GA ~[]A, A any]() GA {
|
func ConstNil[GA ~[]A, A any]() GA {
|
||||||
return (GA)(nil)
|
return (GA)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Concat[GT ~[]T, T any](left, right GT) GT {
|
||||||
|
// some performance checks
|
||||||
|
ll := len(left)
|
||||||
|
if ll == 0 {
|
||||||
|
return right
|
||||||
|
}
|
||||||
|
lr := len(right)
|
||||||
|
if lr == 0 {
|
||||||
|
return left
|
||||||
|
}
|
||||||
|
// need to copy
|
||||||
|
buf := make(GT, ll+lr)
|
||||||
|
copy(buf[copy(buf, left):], right)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,72 @@ import (
|
|||||||
F "github.com/IBM/fp-go/v2/function"
|
F "github.com/IBM/fp-go/v2/function"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func MonadSequenceSegment[HKTB, HKTRB any](
|
||||||
|
fof func(HKTB) HKTRB,
|
||||||
|
empty HKTRB,
|
||||||
|
concat func(HKTRB, HKTRB) HKTRB,
|
||||||
|
fbs []HKTB,
|
||||||
|
start, end int,
|
||||||
|
) HKTRB {
|
||||||
|
|
||||||
|
switch end - start {
|
||||||
|
case 0:
|
||||||
|
return empty
|
||||||
|
case 1:
|
||||||
|
return fof(fbs[start])
|
||||||
|
default:
|
||||||
|
mid := (start + end) / 2
|
||||||
|
return concat(
|
||||||
|
MonadSequenceSegment(fof, empty, concat, fbs, start, mid),
|
||||||
|
MonadSequenceSegment(fof, empty, concat, fbs, mid, end),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SequenceSegment[HKTB, HKTRB any](
|
||||||
|
fof func(HKTB) HKTRB,
|
||||||
|
empty HKTRB,
|
||||||
|
concat func(HKTRB, HKTRB) HKTRB,
|
||||||
|
) func([]HKTB) HKTRB {
|
||||||
|
|
||||||
|
concat_f := func(left, right func([]HKTB) HKTRB) func([]HKTB) HKTRB {
|
||||||
|
return func(fbs []HKTB) HKTRB {
|
||||||
|
return concat(left(fbs), right(fbs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
empty_f := F.Constant1[[]HKTB](empty)
|
||||||
|
at := func(idx int) func([]HKTB) HKTRB {
|
||||||
|
return func(fbs []HKTB) HKTRB {
|
||||||
|
return fof(fbs[idx])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var divide func(start, end int) func([]HKTB) HKTRB
|
||||||
|
divide = func(start, end int) func([]HKTB) HKTRB {
|
||||||
|
switch end - start {
|
||||||
|
case 0:
|
||||||
|
return empty_f
|
||||||
|
case 1:
|
||||||
|
return at(start)
|
||||||
|
default:
|
||||||
|
mid := (start + end) / 2
|
||||||
|
left := divide(start, mid)
|
||||||
|
right := divide(mid, end)
|
||||||
|
|
||||||
|
return concat_f(left, right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO this could be cached by length
|
||||||
|
get_divide := func(len int) func([]HKTB) HKTRB {
|
||||||
|
return divide(0, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(fbs []HKTB) HKTRB {
|
||||||
|
return get_divide(len(fbs))(fbs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
We need to pass the members of the applicative explicitly, because golang does neither support higher kinded types nor template methods on structs or interfaces
|
We need to pass the members of the applicative explicitly, because golang does neither support higher kinded types nor template methods on structs or interfaces
|
||||||
@@ -79,6 +145,34 @@ func TraverseWithIndex[GA ~[]A, GB ~[]B, A, B, HKTB, HKTAB, HKTRB any](
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
We need to pass the members of the applicative explicitly, because golang does neither support higher kinded types nor template methods on structs or interfaces
|
||||||
|
|
||||||
|
HKTRB = HKT<GB>
|
||||||
|
HKTB = HKT<B>
|
||||||
|
HKTAB = HKT<func(A)B>
|
||||||
|
*/
|
||||||
|
func MonadSequence[GA ~[]HKTA, HKTA, HKTRA any](
|
||||||
|
fof func(HKTA) HKTRA,
|
||||||
|
empty HKTRA,
|
||||||
|
concat func(HKTRA, HKTRA) HKTRA,
|
||||||
|
|
||||||
|
ta GA) HKTRA {
|
||||||
|
return MonadSequenceSegment(fof, empty, concat, ta, 0, len(ta))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sequence[GA ~[]HKTA, HKTA, HKTRA any](
|
||||||
|
fof func(HKTA) HKTRA,
|
||||||
|
empty HKTRA,
|
||||||
|
concat func(HKTRA, HKTRA) HKTRA,
|
||||||
|
) func(GA) HKTRA {
|
||||||
|
|
||||||
|
return func(ma GA) HKTRA {
|
||||||
|
return MonadSequence(fof, empty, concat, ma)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func MonadTraverseReduce[GA ~[]A, GB, A, B, HKTB, HKTAB, HKTRB any](
|
func MonadTraverseReduce[GA ~[]A, GB, A, B, HKTB, HKTAB, HKTRB any](
|
||||||
fof func(GB) HKTRB,
|
fof func(GB) HKTRB,
|
||||||
fmap func(func(GB) func(B) GB) func(HKTRB) HKTAB,
|
fmap func(func(GB) func(B) GB) func(HKTRB) HKTAB,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package iter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/v2/function"
|
F "github.com/IBM/fp-go/v2/function"
|
||||||
|
M "github.com/IBM/fp-go/v2/monoid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MonadReduceWithIndex[GA ~func(yield func(A) bool), A, B any](fa GA, f func(int, B, A) B, initial B) B {
|
func MonadReduceWithIndex[GA ~func(yield func(A) bool), A, B any](fa GA, f func(int, B, A) B, initial B) B {
|
||||||
@@ -59,3 +60,41 @@ func Prepend[GA ~func(yield func(A) bool), A any](head A) func(GA) GA {
|
|||||||
func Empty[GA ~func(yield func(A) bool), A any]() GA {
|
func Empty[GA ~func(yield func(A) bool), A any]() GA {
|
||||||
return func(_ func(A) bool) {}
|
return func(_ func(A) bool) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ToArray[GA ~func(yield func(A) bool), GB ~[]A, A any](fa GA) GB {
|
||||||
|
bs := make(GB, 0)
|
||||||
|
for a := range fa {
|
||||||
|
bs = append(bs, a)
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadMapToArray[GA ~func(yield func(A) bool), GB ~[]B, A, B any](fa GA, f func(A) B) GB {
|
||||||
|
bs := make(GB, 0)
|
||||||
|
for a := range fa {
|
||||||
|
bs = append(bs, f(a))
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func MapToArray[GA ~func(yield func(A) bool), GB ~[]B, A, B any](f func(A) B) func(GA) GB {
|
||||||
|
return F.Bind2nd(MonadMapToArray[GA, GB], f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadMapToArrayWithIndex[GA ~func(yield func(A) bool), GB ~[]B, A, B any](fa GA, f func(int, A) B) GB {
|
||||||
|
bs := make(GB, 0)
|
||||||
|
var i int
|
||||||
|
for a := range fa {
|
||||||
|
bs = append(bs, f(i, a))
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
|
func MapToArrayWithIndex[GA ~func(yield func(A) bool), GB ~[]B, A, B any](f func(int, A) B) func(GA) GB {
|
||||||
|
return F.Bind2nd(MonadMapToArrayWithIndex[GA, GB], f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Monoid[GA ~func(yield func(A) bool), A any]() M.Monoid[GA] {
|
||||||
|
return M.MakeMonoid(Concat[GA], Empty[GA]())
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ package iter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/v2/function"
|
F "github.com/IBM/fp-go/v2/function"
|
||||||
|
INTA "github.com/IBM/fp-go/v2/internal/array"
|
||||||
|
M "github.com/IBM/fp-go/v2/monoid"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -27,14 +29,65 @@ HKTRB = HKT<GB>
|
|||||||
HKTB = HKT<B>
|
HKTB = HKT<B>
|
||||||
HKTAB = HKT<func(A)B>
|
HKTAB = HKT<func(A)B>
|
||||||
*/
|
*/
|
||||||
func MonadTraverse[GA ~func(yield func(A) bool), GB ~func(yield func(B) bool), A, B, HKTB, HKTAB, HKTRB any](
|
func MonadTraverse[GA ~func(yield func(A) bool), GB ~func(yield func(B) bool), A, B, HKT_B, HKT_GB_GB, HKT_GB any](
|
||||||
fof func(GB) HKTRB,
|
fmap_b func(HKT_B, func(B) GB) HKT_GB,
|
||||||
fmap func(func(GB) func(B) GB) func(HKTRB) HKTAB,
|
|
||||||
fap func(HKTB) func(HKTAB) HKTRB,
|
fof_gb func(GB) HKT_GB,
|
||||||
|
fmap_gb func(HKT_GB, func(GB) func(GB) GB) HKT_GB_GB,
|
||||||
|
fap_gb func(HKT_GB_GB, HKT_GB) HKT_GB,
|
||||||
|
|
||||||
ta GA,
|
ta GA,
|
||||||
f func(A) HKTB) HKTRB {
|
f func(A) HKT_B) HKT_GB {
|
||||||
return MonadTraverseReduce(fof, fmap, fap, ta, f, MonadAppend[GB, B], Empty[GB]())
|
|
||||||
|
fof := F.Bind2nd(fmap_b, Of[GB])
|
||||||
|
|
||||||
|
empty := fof_gb(Empty[GB]())
|
||||||
|
|
||||||
|
cb := F.Curry2(Concat[GB])
|
||||||
|
concat_gb := F.Bind2nd(fmap_gb, cb)
|
||||||
|
concat := func(first HKT_GB, second HKT_GB) HKT_GB {
|
||||||
|
return fap_gb(concat_gb(first), second)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert to an array
|
||||||
|
hktb := MonadMapToArray[GA, []HKT_B](ta, f)
|
||||||
|
return INTA.MonadSequenceSegment(fof, empty, concat, hktb, 0, len(hktb))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Traverse[GA ~func(yield func(A) bool), GB ~func(yield func(B) bool), A, B, HKT_B, HKT_GB_GB, HKT_GB any](
|
||||||
|
fmap_b func(func(B) GB) func(HKT_B) HKT_GB,
|
||||||
|
|
||||||
|
fof_gb func(GB) HKT_GB,
|
||||||
|
fmap_gb func(func(GB) func(GB) GB) func(HKT_GB) HKT_GB_GB,
|
||||||
|
fap_gb func(HKT_GB_GB, HKT_GB) HKT_GB,
|
||||||
|
|
||||||
|
f func(A) HKT_B) func(GA) HKT_GB {
|
||||||
|
|
||||||
|
fof := fmap_b(Of[GB])
|
||||||
|
empty := fof_gb(Empty[GB]())
|
||||||
|
cb := F.Curry2(Concat[GB])
|
||||||
|
concat_gb := fmap_gb(cb)
|
||||||
|
|
||||||
|
concat := func(first, second HKT_GB) HKT_GB {
|
||||||
|
return fap_gb(concat_gb(first), second)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(ma GA) HKT_GB {
|
||||||
|
// return INTA.SequenceSegment(fof, empty, concat)(MapToArray[GA, []HKT_B](f)(ma))
|
||||||
|
hktb := MonadMapToArray[GA, []HKT_B](ma, f)
|
||||||
|
return INTA.MonadSequenceSegment(fof, empty, concat, hktb, 0, len(hktb))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadSequence[GA ~func(yield func(HKTA) bool), HKTA, HKTRA any](
|
||||||
|
fof func(HKTA) HKTRA,
|
||||||
|
m M.Monoid[HKTRA],
|
||||||
|
|
||||||
|
ta GA) HKTRA {
|
||||||
|
|
||||||
|
// convert to an array
|
||||||
|
hktb := ToArray[GA, []HKTA](ta)
|
||||||
|
return INTA.MonadSequenceSegment(fof, m.Empty(), m.Concat, hktb, 0, len(hktb))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -45,37 +98,35 @@ HKTRB = HKT<GB>
|
|||||||
HKTB = HKT<B>
|
HKTB = HKT<B>
|
||||||
HKTAB = HKT<func(A)B>
|
HKTAB = HKT<func(A)B>
|
||||||
*/
|
*/
|
||||||
func MonadTraverseWithIndex[GA ~func(yield func(A) bool), GB ~func(yield func(B) bool), A, B, HKTB, HKTAB, HKTRB any](
|
func MonadTraverseWithIndex[GA ~func(yield func(A) bool), A, HKTB, HKTRB any](
|
||||||
fof func(GB) HKTRB,
|
fof func(HKTB) HKTRB,
|
||||||
fmap func(func(GB) func(B) GB) func(HKTRB) HKTAB,
|
m M.Monoid[HKTRB],
|
||||||
fap func(HKTB) func(HKTAB) HKTRB,
|
|
||||||
|
|
||||||
ta GA,
|
ta GA,
|
||||||
f func(int, A) HKTB) HKTRB {
|
f func(int, A) HKTB) HKTRB {
|
||||||
return MonadTraverseReduceWithIndex(fof, fmap, fap, ta, f, MonadAppend[GB, B], Empty[GB]())
|
|
||||||
|
// convert to an array
|
||||||
|
hktb := MonadMapToArrayWithIndex[GA, []HKTB](ta, f)
|
||||||
|
return INTA.MonadSequenceSegment(fof, m.Empty(), m.Concat, hktb, 0, len(hktb))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Traverse[GA ~func(yield func(A) bool), GB ~func(yield func(B) bool), A, B, HKTB, HKTAB, HKTRB any](
|
func Sequence[GA ~func(yield func(HKTA) bool), HKTA, HKTRA any](
|
||||||
fof func(GB) HKTRB,
|
fof func(HKTA) HKTRA,
|
||||||
fmap func(func(GB) func(B) GB) func(HKTRB) HKTAB,
|
m M.Monoid[HKTRA]) func(GA) HKTRA {
|
||||||
fap func(HKTB) func(HKTAB) HKTRB,
|
|
||||||
|
|
||||||
f func(A) HKTB) func(GA) HKTRB {
|
return func(ma GA) HKTRA {
|
||||||
|
return MonadSequence(fof, m, ma)
|
||||||
return func(ma GA) HKTRB {
|
|
||||||
return MonadTraverse(fof, fmap, fap, ma, f)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TraverseWithIndex[GA ~func(yield func(A) bool), GB ~func(yield func(B) bool), A, B, HKTB, HKTAB, HKTRB any](
|
func TraverseWithIndex[GA ~func(yield func(A) bool), A, HKTB, HKTRB any](
|
||||||
fof func(GB) HKTRB,
|
fof func(HKTB) HKTRB,
|
||||||
fmap func(func(GB) func(B) GB) func(HKTRB) HKTAB,
|
m M.Monoid[HKTRB],
|
||||||
fap func(HKTB) func(HKTAB) HKTRB,
|
|
||||||
|
|
||||||
f func(int, A) HKTB) func(GA) HKTRB {
|
f func(int, A) HKTB) func(GA) HKTRB {
|
||||||
|
|
||||||
return func(ma GA) HKTRB {
|
return func(ma GA) HKTRB {
|
||||||
return MonadTraverseWithIndex(fof, fmap, fap, ma, f)
|
return MonadTraverseWithIndex(fof, m, ma, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,9 +63,11 @@ func TraverseArray[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
|||||||
|
|
||||||
func TraverseIter[A, B any](f Kleisli[A, B]) Kleisli[Seq[A], Seq[B]] {
|
func TraverseIter[A, B any](f Kleisli[A, B]) Kleisli[Seq[A], Seq[B]] {
|
||||||
return INTI.Traverse[Seq[A]](
|
return INTI.Traverse[Seq[A]](
|
||||||
|
Map[B],
|
||||||
|
|
||||||
Of[Seq[B]],
|
Of[Seq[B]],
|
||||||
Map[Seq[B], func(B) Seq[B]],
|
Map[Seq[B]],
|
||||||
Ap[Seq[B], B],
|
MonadAp[Seq[B]],
|
||||||
|
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -885,3 +885,13 @@ func MonadZip[A, B any](fb Seq[B], fa Seq[A]) Seq2[A, B] {
|
|||||||
func Zip[A, B any](fa Seq[A]) func(Seq[B]) Seq2[A, B] {
|
func Zip[A, B any](fa Seq[A]) func(Seq[B]) Seq2[A, B] {
|
||||||
return F.Bind2nd(MonadZip[A, B], fa)
|
return F.Bind2nd(MonadZip[A, B], fa)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func MonadMapToArray[A, B any](fa Seq[A], f func(A) B) []B {
|
||||||
|
return G.MonadMapToArray[Seq[A], []B](fa, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func MapToArray[A, B any](f func(A) B) func(Seq[A]) []B {
|
||||||
|
return G.MapToArray[Seq[A], []B](f)
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,5 +33,5 @@ import (
|
|||||||
//
|
//
|
||||||
//go:inline
|
//go:inline
|
||||||
func Monoid[T any]() M.Monoid[Seq[T]] {
|
func Monoid[T any]() M.Monoid[Seq[T]] {
|
||||||
return M.MakeMonoid(G.Concat[Seq[T]], Empty[T]())
|
return G.Monoid[Seq[T]]()
|
||||||
}
|
}
|
||||||
@@ -42,6 +42,8 @@ func ApplySemigroup[A any](s S.Semigroup[A]) S.Semigroup[Option[A]] {
|
|||||||
// optMonoid := ApplicativeMonoid(intMonoid)
|
// optMonoid := ApplicativeMonoid(intMonoid)
|
||||||
// result := optMonoid.Concat(Some(2), Some(3)) // Some(5)
|
// result := optMonoid.Concat(Some(2), Some(3)) // Some(5)
|
||||||
// result := optMonoid.Empty() // Some(0)
|
// result := optMonoid.Empty() // Some(0)
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
func ApplicativeMonoid[A any](m M.Monoid[A]) M.Monoid[Option[A]] {
|
func ApplicativeMonoid[A any](m M.Monoid[A]) M.Monoid[Option[A]] {
|
||||||
return M.ApplicativeMonoid(Of[A], MonadMap[A, func(A) A], MonadAp[A, A], m)
|
return M.ApplicativeMonoid(Of[A], MonadMap[A, func(A) A], MonadAp[A, A], m)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,11 +55,22 @@ import (
|
|||||||
// result := TraverseIter(parse)(invalidStrings)
|
// result := TraverseIter(parse)(invalidStrings)
|
||||||
// // result is None because "invalid" cannot be parsed
|
// // result is None because "invalid" cannot be parsed
|
||||||
func TraverseIter[A, B any](f Kleisli[A, B]) Kleisli[Seq[A], Seq[B]] {
|
func TraverseIter[A, B any](f Kleisli[A, B]) Kleisli[Seq[A], Seq[B]] {
|
||||||
|
|
||||||
return INTI.Traverse[Seq[A]](
|
return INTI.Traverse[Seq[A]](
|
||||||
|
Map[B],
|
||||||
|
|
||||||
Of[Seq[B]],
|
Of[Seq[B]],
|
||||||
Map[Seq[B], func(B) Seq[B]],
|
Map[Seq[B]],
|
||||||
Ap[Seq[B]],
|
MonadAp[Seq[B]],
|
||||||
|
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SequenceIter[A any](as Seq[Option[A]]) Option[Seq[A]] {
|
||||||
|
return INTI.MonadSequence(
|
||||||
|
Map(INTI.Of[Seq[A]]),
|
||||||
|
ApplicativeMonoid(INTI.Monoid[Seq[A]]()),
|
||||||
|
as,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ package reader
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IBM/fp-go/v2/function"
|
"github.com/IBM/fp-go/v2/function"
|
||||||
"github.com/IBM/fp-go/v2/internal/array"
|
G "github.com/IBM/fp-go/v2/reader/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MonadTraverseArray transforms each element of an array using a function that returns a Reader,
|
// MonadTraverseArray transforms each element of an array using a function that returns a Reader,
|
||||||
@@ -38,13 +38,7 @@ import (
|
|||||||
// r := reader.MonadTraverseArray(numbers, addPrefix)
|
// r := reader.MonadTraverseArray(numbers, addPrefix)
|
||||||
// result := r(Config{Prefix: "num"}) // ["num1", "num2", "num3"]
|
// result := r(Config{Prefix: "num"}) // ["num1", "num2", "num3"]
|
||||||
func MonadTraverseArray[R, A, B any](ma []A, f Kleisli[R, A, B]) Reader[R, []B] {
|
func MonadTraverseArray[R, A, B any](ma []A, f Kleisli[R, A, B]) Reader[R, []B] {
|
||||||
return array.MonadTraverse(
|
return G.MonadTraverseArray[Reader[R, B], Reader[R, []B], []A](ma, f)
|
||||||
Of[R, []B],
|
|
||||||
Map[R, []B, func(B) []B],
|
|
||||||
Ap[[]B, R, B],
|
|
||||||
ma,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TraverseArray transforms each element of an array using a function that returns a Reader,
|
// TraverseArray transforms each element of an array using a function that returns a Reader,
|
||||||
@@ -63,12 +57,7 @@ func MonadTraverseArray[R, A, B any](ma []A, f Kleisli[R, A, B]) Reader[R, []B]
|
|||||||
// r := transform([]int{1, 2, 3})
|
// r := transform([]int{1, 2, 3})
|
||||||
// result := r(Config{Multiplier: 10}) // [10, 20, 30]
|
// result := r(Config{Multiplier: 10}) // [10, 20, 30]
|
||||||
func TraverseArray[R, A, B any](f Kleisli[R, A, B]) func([]A) Reader[R, []B] {
|
func TraverseArray[R, A, B any](f Kleisli[R, A, B]) func([]A) Reader[R, []B] {
|
||||||
return array.Traverse[[]A](
|
return G.TraverseArray[Reader[R, B], Reader[R, []B], []A](f)
|
||||||
Of[R, []B],
|
|
||||||
Map[R, []B, func(B) []B],
|
|
||||||
Ap[[]B, R, B],
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TraverseArrayWithIndex transforms each element of an array using a function that takes
|
// TraverseArrayWithIndex transforms each element of an array using a function that takes
|
||||||
@@ -89,12 +78,7 @@ func TraverseArray[R, A, B any](f Kleisli[R, A, B]) func([]A) Reader[R, []B] {
|
|||||||
// r := transform([]string{"a", "b", "c"})
|
// r := transform([]string{"a", "b", "c"})
|
||||||
// result := r(Config{Prefix: "item"}) // ["item[0]:a", "item[1]:b", "item[2]:c"]
|
// result := r(Config{Prefix: "item"}) // ["item[0]:a", "item[1]:b", "item[2]:c"]
|
||||||
func TraverseArrayWithIndex[R, A, B any](f func(int, A) Reader[R, B]) func([]A) Reader[R, []B] {
|
func TraverseArrayWithIndex[R, A, B any](f func(int, A) Reader[R, B]) func([]A) Reader[R, []B] {
|
||||||
return array.TraverseWithIndex[[]A](
|
return G.TraverseArrayWithIndex[Reader[R, B], Reader[R, []B], []A](f)
|
||||||
Of[R, []B],
|
|
||||||
Map[R, []B, func(B) []B],
|
|
||||||
Ap[[]B, R, B],
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SequenceArray converts an array of Readers into a single Reader containing an array.
|
// SequenceArray converts an array of Readers into a single Reader containing an array.
|
||||||
|
|||||||
15
v2/reader/generic/monoid.go
Normal file
15
v2/reader/generic/monoid.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package generic
|
||||||
|
|
||||||
|
import (
|
||||||
|
M "github.com/IBM/fp-go/v2/monoid"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func ApplicativeMonoid[GA ~func(R) A, R, A any](m M.Monoid[A]) M.Monoid[GA] {
|
||||||
|
return M.ApplicativeMonoid(
|
||||||
|
Of[GA, R, A],
|
||||||
|
MonadMap[GA, func(R) func(A) A],
|
||||||
|
MonadAp[GA, GA, func(R) func(A) A],
|
||||||
|
m,
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user