mirror of
https://github.com/IBM/fp-go.git
synced 2025-06-23 00:27:49 +02:00
fix: implement FilterChain
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
@ -108,10 +108,16 @@ func MonadFilterMap[A, B any](fa []A, f func(a A) O.Option[B]) []B {
|
|||||||
return G.MonadFilterMap[[]A, []B](fa, f)
|
return G.MonadFilterMap[[]A, []B](fa, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterChain maps an array with an iterating function that returns an [O.Option] and it keeps only the Some values discarding the Nones.
|
||||||
func FilterMap[A, B any](f func(a A) O.Option[B]) func([]A) []B {
|
func FilterMap[A, B any](f func(a A) O.Option[B]) func([]A) []B {
|
||||||
return G.FilterMap[[]A, []B](f)
|
return G.FilterMap[[]A, []B](f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterChain maps an array with an iterating function that returns an [O.Option] of an array. It keeps only the Some values discarding the Nones and then flattens the result.
|
||||||
|
func FilterChain[A, B any](f func(A) O.Option[[]B]) func([]A) []B {
|
||||||
|
return G.FilterChain[[]A](f)
|
||||||
|
}
|
||||||
|
|
||||||
func FilterMapRef[A, B any](pred func(a *A) bool, f func(a *A) B) func([]A) []B {
|
func FilterMapRef[A, B any](pred func(a *A) bool, f func(a *A) B) func([]A) []B {
|
||||||
return func(fa []A) []B {
|
return func(fa []A) []B {
|
||||||
return filterMapRef(fa, pred, f)
|
return filterMapRef(fa, pred, f)
|
||||||
@ -237,7 +243,7 @@ func Intercalate[A any](m M.Monoid[A]) func(A) func([]A) A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Flatten[A any](mma [][]A) []A {
|
func Flatten[A any](mma [][]A) []A {
|
||||||
return MonadChain(mma, F.Identity[[]A])
|
return G.Flatten(mma)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Slice[A any](low, high int) func(as []A) []A {
|
func Slice[A any](low, high int) func(as []A) []A {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package array
|
package array
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -142,3 +143,33 @@ func TestPartition(t *testing.T) {
|
|||||||
assert.Equal(t, T.MakeTuple2(Empty[int](), Empty[int]()), Partition(pred)(Empty[int]()))
|
assert.Equal(t, T.MakeTuple2(Empty[int](), Empty[int]()), Partition(pred)(Empty[int]()))
|
||||||
assert.Equal(t, T.MakeTuple2(From(1), From(3)), Partition(pred)(From(1, 3)))
|
assert.Equal(t, T.MakeTuple2(From(1), From(3)), Partition(pred)(From(1, 3)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFilterChain(t *testing.T) {
|
||||||
|
src := From(1, 2, 3)
|
||||||
|
|
||||||
|
f := func(i int) O.Option[[]string] {
|
||||||
|
if i%2 != 0 {
|
||||||
|
return O.Of(From(fmt.Sprintf("a%d", i), fmt.Sprintf("b%d", i)))
|
||||||
|
}
|
||||||
|
return O.None[[]string]()
|
||||||
|
}
|
||||||
|
|
||||||
|
res := FilterChain(f)(src)
|
||||||
|
|
||||||
|
assert.Equal(t, From("a1", "b1", "a3", "b3"), res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterMap(t *testing.T) {
|
||||||
|
src := From(1, 2, 3)
|
||||||
|
|
||||||
|
f := func(i int) O.Option[string] {
|
||||||
|
if i%2 != 0 {
|
||||||
|
return O.Of(fmt.Sprintf("a%d", i))
|
||||||
|
}
|
||||||
|
return O.None[string]()
|
||||||
|
}
|
||||||
|
|
||||||
|
res := FilterMap(f)(src)
|
||||||
|
|
||||||
|
assert.Equal(t, From("a1", "a3"), res)
|
||||||
|
}
|
||||||
|
@ -118,6 +118,17 @@ func MonadFilterMap[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(a A) O.Option[B])
|
|||||||
return filterMap[GA, GB](fa, f)
|
return filterMap[GA, GB](fa, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FilterChain[GA ~[]A, GB ~[]B, A, B any](f func(a A) O.Option[GB]) func(GA) GB {
|
||||||
|
return F.Flow2(
|
||||||
|
FilterMap[GA, []GB](f),
|
||||||
|
Flatten[[]GB],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Flatten[GAA ~[]GA, GA ~[]A, A any](mma GAA) GA {
|
||||||
|
return MonadChain(mma, F.Identity[GA])
|
||||||
|
}
|
||||||
|
|
||||||
func FilterMap[GA ~[]A, GB ~[]B, A, B any](f func(a A) O.Option[B]) func(GA) GB {
|
func FilterMap[GA ~[]A, GB ~[]B, A, B any](f func(a A) O.Option[B]) func(GA) GB {
|
||||||
return F.Bind2nd(MonadFilterMap[GA, GB, A, B], f)
|
return F.Bind2nd(MonadFilterMap[GA, GB, A, B], f)
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,12 @@ import (
|
|||||||
S "github.com/IBM/fp-go/semigroup"
|
S "github.com/IBM/fp-go/semigroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
func concat[A any](first, second func(A) A) func(A) A {
|
|
||||||
return F.Flow2(first, second)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Semigroup for the Endomorphism where the `concat` operation is the usual function composition.
|
// Semigroup for the Endomorphism where the `concat` operation is the usual function composition.
|
||||||
func Semigroup[A any]() S.Semigroup[func(A) A] {
|
func Semigroup[A any]() S.Semigroup[func(A) A] {
|
||||||
return S.MakeSemigroup(concat[A])
|
return S.MakeSemigroup(F.Flow2[func(A) A, func(A) A])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Monoid for the Endomorphism where the `concat` operation is the usual function composition.
|
// Monoid for the Endomorphism where the `concat` operation is the usual function composition.
|
||||||
func Monoid[A any]() M.Monoid[func(A) A] {
|
func Monoid[A any]() M.Monoid[func(A) A] {
|
||||||
return M.MakeMonoid(concat[A], F.Identity[A])
|
return M.MakeMonoid(F.Flow2[func(A) A, func(A) A], F.Identity[A])
|
||||||
}
|
}
|
||||||
|
@ -219,3 +219,10 @@ func Ap[GUV ~func() O.Option[T.Tuple2[GUV, func(U) V]], GV ~func() O.Option[T.Tu
|
|||||||
func MonadAp[GUV ~func() O.Option[T.Tuple2[GUV, func(U) V]], GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](fab GUV, ma GU) GV {
|
func MonadAp[GUV ~func() O.Option[T.Tuple2[GUV, func(U) V]], GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](fab GUV, ma GU) GV {
|
||||||
return Ap[GUV, GV, GU](ma)(fab)
|
return Ap[GUV, GV, GU](ma)(fab)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FilterChain[GVV ~func() O.Option[T.Tuple2[GVV, GV]], GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) O.Option[GV], U, V any](f FCT) func(ma GU) GV {
|
||||||
|
return F.Flow2(
|
||||||
|
FilterMap[GVV, GU](f),
|
||||||
|
Flatten[GVV],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -118,3 +118,8 @@ func Repeat[U any](n int, a U) Iterator[U] {
|
|||||||
func Count(start int) Iterator[int] {
|
func Count(start int) Iterator[int] {
|
||||||
return G.Count[Iterator[int]](start)
|
return G.Count[Iterator[int]](start)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterChain filters and transforms the content of an iterator
|
||||||
|
func FilterChain[U, V any](f func(U) O.Option[Iterator[V]]) func(ma Iterator[U]) Iterator[V] {
|
||||||
|
return G.FilterChain[Iterator[Iterator[V]], Iterator[V], Iterator[U]](f)
|
||||||
|
}
|
||||||
|
17
record/doc.go
Normal file
17
record/doc.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) 2023 IBM Corp.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package record contains monadic operations for maps as well as a rich set of utility functions
|
||||||
|
package record
|
@ -16,6 +16,7 @@
|
|||||||
package generic
|
package generic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
M "github.com/IBM/fp-go/monoid"
|
M "github.com/IBM/fp-go/monoid"
|
||||||
S "github.com/IBM/fp-go/semigroup"
|
S "github.com/IBM/fp-go/semigroup"
|
||||||
)
|
)
|
||||||
@ -26,3 +27,17 @@ func UnionMonoid[N ~map[K]V, K comparable, V any](s S.Semigroup[V]) M.Monoid[N]
|
|||||||
Empty[N](),
|
Empty[N](),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UnionLastMonoid[N ~map[K]V, K comparable, V any]() M.Monoid[N] {
|
||||||
|
return M.MakeMonoid(
|
||||||
|
unionLast[N],
|
||||||
|
Empty[N](),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnionFirstMonoid[N ~map[K]V, K comparable, V any]() M.Monoid[N] {
|
||||||
|
return M.MakeMonoid(
|
||||||
|
F.Swap(unionLast[N]),
|
||||||
|
Empty[N](),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
G "github.com/IBM/fp-go/internal/record"
|
G "github.com/IBM/fp-go/internal/record"
|
||||||
Mg "github.com/IBM/fp-go/magma"
|
Mg "github.com/IBM/fp-go/magma"
|
||||||
|
Mo "github.com/IBM/fp-go/monoid"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
T "github.com/IBM/fp-go/tuple"
|
||||||
)
|
)
|
||||||
@ -82,6 +83,34 @@ func MonadMap[M ~map[K]V, N ~map[K]R, K comparable, V, R any](r M, f func(V) R)
|
|||||||
return MonadMapWithIndex[M, N](r, F.Ignore1of2[K](f))
|
return MonadMapWithIndex[M, N](r, F.Ignore1of2[K](f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MonadChainWithIndex[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N], r M, f func(K, V1) N) N {
|
||||||
|
return G.ReduceWithIndex(r, func(k K, dst N, b V1) N {
|
||||||
|
return m.Concat(dst, f(k, b))
|
||||||
|
}, m.Empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadChain[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N], r M, f func(V1) N) N {
|
||||||
|
return G.Reduce(r, func(dst N, b V1) N {
|
||||||
|
return m.Concat(dst, f(b))
|
||||||
|
}, m.Empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChainWithIndex[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N]) func(func(K, V1) N) func(M) N {
|
||||||
|
return func(f func(K, V1) N) func(M) N {
|
||||||
|
return func(ma M) N {
|
||||||
|
return MonadChainWithIndex(m, ma, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chain[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N]) func(func(V1) N) func(M) N {
|
||||||
|
return func(f func(V1) N) func(M) N {
|
||||||
|
return func(ma M) N {
|
||||||
|
return MonadChain(m, ma, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func MonadMapWithIndex[M ~map[K]V, N ~map[K]R, K comparable, V, R any](r M, f func(K, V) R) N {
|
func MonadMapWithIndex[M ~map[K]V, N ~map[K]R, K comparable, V, R any](r M, f func(K, V) R) N {
|
||||||
return G.ReduceWithIndex(r, func(k K, dst N, v V) N {
|
return G.ReduceWithIndex(r, func(k K, dst N, v V) N {
|
||||||
return upsertAtReadWrite(dst, k, f(k, v))
|
return upsertAtReadWrite(dst, k, f(k, v))
|
||||||
@ -114,15 +143,14 @@ func MapRefWithIndex[M ~map[K]V, N ~map[K]R, K comparable, V, R any](f func(K, *
|
|||||||
return F.Bind2nd(MonadMapRefWithIndex[M, N, K, V, R], f)
|
return F.Bind2nd(MonadMapRefWithIndex[M, N, K, V, R], f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookup[M ~map[K]V, K comparable, V any](r M, k K) O.Option[V] {
|
|
||||||
if val, ok := r[k]; ok {
|
|
||||||
return O.Some(val)
|
|
||||||
}
|
|
||||||
return O.None[V]()
|
|
||||||
}
|
|
||||||
|
|
||||||
func Lookup[M ~map[K]V, K comparable, V any](k K) func(M) O.Option[V] {
|
func Lookup[M ~map[K]V, K comparable, V any](k K) func(M) O.Option[V] {
|
||||||
return F.Bind2nd(lookup[M, K, V], k)
|
n := O.None[V]()
|
||||||
|
return func(m M) O.Option[V] {
|
||||||
|
if val, ok := m[k]; ok {
|
||||||
|
return O.Some(val)
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Has[M ~map[K]V, K comparable, V any](k K, r M) bool {
|
func Has[M ~map[K]V, K comparable, V any](k K, r M) bool {
|
||||||
@ -161,6 +189,31 @@ func union[M ~map[K]V, K comparable, V any](m Mg.Magma[V], left M, right M) M {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unionLast[M ~map[K]V, K comparable, V any](left M, right M) M {
|
||||||
|
lenLeft := len(left)
|
||||||
|
|
||||||
|
if lenLeft == 0 {
|
||||||
|
return right
|
||||||
|
}
|
||||||
|
|
||||||
|
lenRight := len(right)
|
||||||
|
if lenRight == 0 {
|
||||||
|
return left
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make(M, lenLeft+lenRight)
|
||||||
|
|
||||||
|
for k, v := range left {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range right {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func Union[M ~map[K]V, K comparable, V any](m Mg.Magma[V]) func(M) func(M) M {
|
func Union[M ~map[K]V, K comparable, V any](m Mg.Magma[V]) func(M) func(M) M {
|
||||||
return func(right M) func(M) M {
|
return func(right M) func(M) M {
|
||||||
return func(left M) M {
|
return func(left M) M {
|
||||||
@ -169,6 +222,22 @@ func Union[M ~map[K]V, K comparable, V any](m Mg.Magma[V]) func(M) func(M) M {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UnionLast[M ~map[K]V, K comparable, V any](right M) func(M) M {
|
||||||
|
return func(left M) M {
|
||||||
|
return unionLast(left, right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Merge[M ~map[K]V, K comparable, V any](right M) func(M) M {
|
||||||
|
return UnionLast(right)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnionFirst[M ~map[K]V, K comparable, V any](right M) func(M) M {
|
||||||
|
return func(left M) M {
|
||||||
|
return unionLast(right, left)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Empty[M ~map[K]V, K comparable, V any]() M {
|
func Empty[M ~map[K]V, K comparable, V any]() M {
|
||||||
return make(M)
|
return make(M)
|
||||||
}
|
}
|
||||||
@ -269,6 +338,33 @@ func FilterMap[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](f func(V1) O.
|
|||||||
return F.Bind2nd(filterMapWithIndex[M, N, K, V1, V2], F.Ignore1of2[K](f))
|
return F.Bind2nd(filterMapWithIndex[M, N, K, V1, V2], F.Ignore1of2[K](f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flatten converts a nested map into a regular map
|
||||||
|
func Flatten[M ~map[K]N, N ~map[K]V, K comparable, V any](m Mo.Monoid[N]) func(M) N {
|
||||||
|
return Chain[M, N](m)(F.Identity[N])
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterChainWithIndex creates a new map with only the elements for which the transformation function creates a Some
|
||||||
|
func FilterChainWithIndex[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N]) func(func(K, V1) O.Option[N]) func(M) N {
|
||||||
|
flatten := Flatten[map[K]N, N](m)
|
||||||
|
return func(f func(K, V1) O.Option[N]) func(M) N {
|
||||||
|
return F.Flow2(
|
||||||
|
FilterMapWithIndex[M, map[K]N](f),
|
||||||
|
flatten,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterChain creates a new map with only the elements for which the transformation function creates a Some
|
||||||
|
func FilterChain[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N]) func(func(V1) O.Option[N]) func(M) N {
|
||||||
|
flatten := Flatten[map[K]N, N](m)
|
||||||
|
return func(f func(V1) O.Option[N]) func(M) N {
|
||||||
|
return F.Flow2(
|
||||||
|
FilterMap[M, map[K]N](f),
|
||||||
|
flatten,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IsNil checks if the map is set to nil
|
// IsNil checks if the map is set to nil
|
||||||
func IsNil[M ~map[K]V, K comparable, V any](m M) bool {
|
func IsNil[M ~map[K]V, K comparable, V any](m M) bool {
|
||||||
return m == nil
|
return m == nil
|
||||||
|
@ -20,8 +20,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func UnionSemigroup[N ~map[K]V, K comparable, V any](s S.Semigroup[V]) S.Semigroup[N] {
|
func UnionSemigroup[N ~map[K]V, K comparable, V any](s S.Semigroup[V]) S.Semigroup[N] {
|
||||||
union := Union[N, K, V](s)
|
|
||||||
return S.MakeSemigroup(func(first N, second N) N {
|
return S.MakeSemigroup(func(first N, second N) N {
|
||||||
return union(second)(first)
|
return union(s, first, second)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnionLastSemigroup[N ~map[K]V, K comparable, V any]() S.Semigroup[N] {
|
||||||
|
return S.MakeSemigroup(func(first N, second N) N {
|
||||||
|
return unionLast(first, second)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnionFirstSemigroup[N ~map[K]V, K comparable, V any]() S.Semigroup[N] {
|
||||||
|
return S.MakeSemigroup(func(first N, second N) N {
|
||||||
|
return unionLast(second, first)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,22 @@ import (
|
|||||||
S "github.com/IBM/fp-go/semigroup"
|
S "github.com/IBM/fp-go/semigroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// UnionMonoid computes the union of two maps of the same type
|
||||||
func UnionMonoid[K comparable, V any](s S.Semigroup[V]) M.Monoid[map[K]V] {
|
func UnionMonoid[K comparable, V any](s S.Semigroup[V]) M.Monoid[map[K]V] {
|
||||||
return G.UnionMonoid[map[K]V](s)
|
return G.UnionMonoid[map[K]V](s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnionLastMonoid computes the union of two maps of the same type giving the last map precedence
|
||||||
|
func UnionLastMonoid[K comparable, V any]() M.Monoid[map[K]V] {
|
||||||
|
return G.UnionLastMonoid[map[K]V]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnionFirstMonoid computes the union of two maps of the same type giving the first map precedence
|
||||||
|
func UnionFirstMonoid[K comparable, V any]() M.Monoid[map[K]V] {
|
||||||
|
return G.UnionFirstMonoid[map[K]V]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeMonoid computes the union of two maps of the same type giving the last map precedence
|
||||||
|
func MergeMonoid[K comparable, V any]() M.Monoid[map[K]V] {
|
||||||
|
return G.UnionLastMonoid[map[K]V]()
|
||||||
|
}
|
||||||
|
@ -17,27 +17,33 @@ package record
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
Mg "github.com/IBM/fp-go/magma"
|
Mg "github.com/IBM/fp-go/magma"
|
||||||
|
Mo "github.com/IBM/fp-go/monoid"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
G "github.com/IBM/fp-go/record/generic"
|
G "github.com/IBM/fp-go/record/generic"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
T "github.com/IBM/fp-go/tuple"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// IsEmpty tests if a map is empty
|
||||||
func IsEmpty[K comparable, V any](r map[K]V) bool {
|
func IsEmpty[K comparable, V any](r map[K]V) bool {
|
||||||
return G.IsEmpty(r)
|
return G.IsEmpty(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsNonEmpty tests if a map is not empty
|
||||||
func IsNonEmpty[K comparable, V any](r map[K]V) bool {
|
func IsNonEmpty[K comparable, V any](r map[K]V) bool {
|
||||||
return G.IsNonEmpty(r)
|
return G.IsNonEmpty(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keys returns the key in a map
|
||||||
func Keys[K comparable, V any](r map[K]V) []K {
|
func Keys[K comparable, V any](r map[K]V) []K {
|
||||||
return G.Keys[map[K]V, []K](r)
|
return G.Keys[map[K]V, []K](r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Values returns the values in a map
|
||||||
func Values[K comparable, V any](r map[K]V) []V {
|
func Values[K comparable, V any](r map[K]V) []V {
|
||||||
return G.Values[map[K]V, []V](r)
|
return G.Values[map[K]V, []V](r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Collect applies a collector function to the key value pairs in a map and returns the result as an array
|
||||||
func Collect[K comparable, V, R any](f func(K, V) R) func(map[K]V) []R {
|
func Collect[K comparable, V, R any](f func(K, V) R) func(map[K]V) []R {
|
||||||
return G.Collect[map[K]V, []R](f)
|
return G.Collect[map[K]V, []R](f)
|
||||||
}
|
}
|
||||||
@ -90,10 +96,12 @@ func MapRefWithIndex[K comparable, V, R any](f func(K, *V) R) func(map[K]V) map[
|
|||||||
return G.MapRefWithIndex[map[K]V, map[K]R](f)
|
return G.MapRefWithIndex[map[K]V, map[K]R](f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lookup returns the entry for a key in a map if it exists
|
||||||
func Lookup[K comparable, V any](k K) func(map[K]V) O.Option[V] {
|
func Lookup[K comparable, V any](k K) func(map[K]V) O.Option[V] {
|
||||||
return G.Lookup[map[K]V](k)
|
return G.Lookup[map[K]V](k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Has tests if a key is contained in a map
|
||||||
func Has[K comparable, V any](k K, r map[K]V) bool {
|
func Has[K comparable, V any](k K, r map[K]V) bool {
|
||||||
return G.Has(k, r)
|
return G.Has(k, r)
|
||||||
}
|
}
|
||||||
@ -102,10 +110,17 @@ func Union[K comparable, V any](m Mg.Magma[V]) func(map[K]V) func(map[K]V) map[K
|
|||||||
return G.Union[map[K]V](m)
|
return G.Union[map[K]V](m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge combines two maps giving the values in the right one precedence. Also refer to [MergeMonoid]
|
||||||
|
func Merge[K comparable, V any](right map[K]V) func(map[K]V) map[K]V {
|
||||||
|
return G.Merge[map[K]V](right)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty creates an empty map
|
||||||
func Empty[K comparable, V any]() map[K]V {
|
func Empty[K comparable, V any]() map[K]V {
|
||||||
return G.Empty[map[K]V]()
|
return G.Empty[map[K]V]()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Size returns the number of elements in a map
|
||||||
func Size[K comparable, V any](r map[K]V) int {
|
func Size[K comparable, V any](r map[K]V) int {
|
||||||
return G.Size(r)
|
return G.Size(r)
|
||||||
}
|
}
|
||||||
@ -130,6 +145,7 @@ func DeleteAt[K comparable, V any](k K) func(map[K]V) map[K]V {
|
|||||||
return G.DeleteAt[map[K]V](k)
|
return G.DeleteAt[map[K]V](k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Singleton creates a new map with a single entry
|
||||||
func Singleton[K comparable, V any](k K, v V) map[K]V {
|
func Singleton[K comparable, V any](k K, v V) map[K]V {
|
||||||
return G.Singleton[map[K]V](k, v)
|
return G.Singleton[map[K]V](k, v)
|
||||||
}
|
}
|
||||||
@ -168,3 +184,34 @@ func IsNonNil[K comparable, V any](m map[K]V) bool {
|
|||||||
func ConstNil[K comparable, V any]() map[K]V {
|
func ConstNil[K comparable, V any]() map[K]V {
|
||||||
return (map[K]V)(nil)
|
return (map[K]V)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MonadChainWithIndex[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2], r map[K]V1, f func(K, V1) map[K]V2) map[K]V2 {
|
||||||
|
return G.MonadChainWithIndex(m, r, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadChain[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2], r map[K]V1, f func(V1) map[K]V2) map[K]V2 {
|
||||||
|
return G.MonadChain(m, r, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChainWithIndex[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2]) func(func(K, V1) map[K]V2) func(map[K]V1) map[K]V2 {
|
||||||
|
return G.ChainWithIndex[map[K]V1](m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chain[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2]) func(func(V1) map[K]V2) func(map[K]V1) map[K]V2 {
|
||||||
|
return G.Chain[map[K]V1](m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flatten converts a nested map into a regular map
|
||||||
|
func Flatten[K comparable, V any](m Mo.Monoid[map[K]V]) func(map[K]map[K]V) map[K]V {
|
||||||
|
return G.Flatten[map[K]map[K]V](m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterChainWithIndex creates a new map with only the elements for which the transformation function creates a Some
|
||||||
|
func FilterChainWithIndex[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2]) func(func(K, V1) O.Option[map[K]V2]) func(map[K]V1) map[K]V2 {
|
||||||
|
return G.FilterChainWithIndex[map[K]V1](m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterChain creates a new map with only the elements for which the transformation function creates a Some
|
||||||
|
func FilterChain[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2]) func(func(V1) O.Option[map[K]V2]) func(map[K]V1) map[K]V2 {
|
||||||
|
return G.FilterChain[map[K]V1](m)
|
||||||
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package record
|
package record
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -71,3 +72,30 @@ func TestLookup(t *testing.T) {
|
|||||||
assert.Equal(t, O.Some("a"), Lookup[string, string]("a")(data))
|
assert.Equal(t, O.Some("a"), Lookup[string, string]("a")(data))
|
||||||
assert.Equal(t, O.None[string](), Lookup[string, string]("a1")(data))
|
assert.Equal(t, O.None[string](), Lookup[string, string]("a1")(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFilterChain(t *testing.T) {
|
||||||
|
src := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
f := func(k string, value int) O.Option[map[string]string] {
|
||||||
|
if value%2 != 0 {
|
||||||
|
return O.Of(map[string]string{
|
||||||
|
k: fmt.Sprintf("%s%d", k, value),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return O.None[map[string]string]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// monoid
|
||||||
|
monoid := MergeMonoid[string, string]()
|
||||||
|
|
||||||
|
res := FilterChainWithIndex[int](monoid)(f)(src)
|
||||||
|
|
||||||
|
assert.Equal(t, map[string]string{
|
||||||
|
"a": "a1",
|
||||||
|
"c": "c3",
|
||||||
|
}, res)
|
||||||
|
}
|
||||||
|
@ -22,3 +22,11 @@ import (
|
|||||||
func UnionSemigroup[K comparable, V any](s S.Semigroup[V]) S.Semigroup[map[K]V] {
|
func UnionSemigroup[K comparable, V any](s S.Semigroup[V]) S.Semigroup[map[K]V] {
|
||||||
return G.UnionSemigroup[map[K]V](s)
|
return G.UnionSemigroup[map[K]V](s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UnionLastSemigroup[K comparable, V any]() S.Semigroup[map[K]V] {
|
||||||
|
return G.UnionLastSemigroup[map[K]V]()
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnionFirstSemigroup[K comparable, V any]() S.Semigroup[map[K]V] {
|
||||||
|
return G.UnionFirstSemigroup[map[K]V]()
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user