mirror of
https://github.com/IBM/fp-go.git
synced 2025-12-09 23:11:40 +02:00
Compare commits
4 Commits
cleue-add-
...
cleue-supp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28b8598f37 | ||
|
|
8bb006c741 | ||
|
|
b6efa35b03 | ||
|
|
35848900c0 |
32
array/generic/uniq.go
Normal file
32
array/generic/uniq.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package generic
|
||||
|
||||
import F "github.com/IBM/fp-go/function"
|
||||
|
||||
// StrictUniq converts an array of arbitrary items into an array or unique items
|
||||
// where uniqueness is determined by the built-in uniqueness constraint
|
||||
func StrictUniq[AS ~[]A, A comparable](as AS) AS {
|
||||
return Uniq[AS](F.Identity[A])(as)
|
||||
}
|
||||
|
||||
// uniquePredUnsafe returns a predicate on a map for uniqueness
|
||||
func uniquePredUnsafe[PRED ~func(A) K, A any, K comparable](f PRED) func(int, A) bool {
|
||||
lookup := make(map[K]bool)
|
||||
return func(_ int, a A) bool {
|
||||
k := f(a)
|
||||
_, has := lookup[k]
|
||||
if has {
|
||||
return false
|
||||
}
|
||||
lookup[k] = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Uniq converts an array of arbitrary items into an array or unique items
|
||||
// where uniqueness is determined based on a key extractor function
|
||||
func Uniq[AS ~[]A, PRED ~func(A) K, A any, K comparable](f PRED) func(as AS) AS {
|
||||
return func(as AS) AS {
|
||||
// we need to create a new predicate for each iteration
|
||||
return filterWithIndex(as, uniquePredUnsafe(f))
|
||||
}
|
||||
}
|
||||
17
array/uniq.go
Normal file
17
array/uniq.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package array
|
||||
|
||||
import (
|
||||
G "github.com/IBM/fp-go/array/generic"
|
||||
)
|
||||
|
||||
// StrictUniq converts an array of arbitrary items into an array or unique items
|
||||
// where uniqueness is determined by the built-in uniqueness constraint
|
||||
func StrictUniq[A comparable](as []A) []A {
|
||||
return G.StrictUniq[[]A](as)
|
||||
}
|
||||
|
||||
// Uniq converts an array of arbitrary items into an array or unique items
|
||||
// where uniqueness is determined based on a key extractor function
|
||||
func Uniq[A any, K comparable](f func(A) K) func(as []A) []A {
|
||||
return G.Uniq[[]A](f)
|
||||
}
|
||||
14
array/uniq_test.go
Normal file
14
array/uniq_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package array
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUniq(t *testing.T) {
|
||||
data := From(1, 2, 3, 2, 4, 1)
|
||||
|
||||
uniq := StrictUniq(data)
|
||||
assert.Equal(t, From(1, 2, 3, 4), uniq)
|
||||
}
|
||||
@@ -61,14 +61,14 @@ func SequenceArray[E, A any](ma []Either[E, A]) Either[E, []A] {
|
||||
return SequenceArrayG[[]A](ma)
|
||||
}
|
||||
|
||||
// CompactArrayG discards the none values and keeps the some values
|
||||
// CompactArrayG discards the none values and keeps the right values
|
||||
func CompactArrayG[A1 ~[]Either[E, A], A2 ~[]A, E, A any](fa A1) A2 {
|
||||
return RA.Reduce(fa, func(out A2, value Either[E, A]) A2 {
|
||||
return MonadFold(value, F.Constant1[E](out), F.Bind1st(RA.Append[A2, A], out))
|
||||
}, make(A2, len(fa)))
|
||||
}, make(A2, 0, len(fa)))
|
||||
}
|
||||
|
||||
// CompactArray discards the none values and keeps the some values
|
||||
// CompactArray discards the none values and keeps the right values
|
||||
func CompactArray[E, A any](fa []Either[E, A]) []A {
|
||||
return CompactArrayG[[]Either[E, A], []A](fa)
|
||||
}
|
||||
|
||||
18
either/array_test.go
Normal file
18
either/array_test.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package either
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCompactArray(t *testing.T) {
|
||||
ar := []Either[string, string]{
|
||||
Of[string]("ok"),
|
||||
Left[string]("err"),
|
||||
Of[string]("ok"),
|
||||
}
|
||||
|
||||
res := CompactArray(ar)
|
||||
assert.Equal(t, 2, len(res))
|
||||
}
|
||||
@@ -89,7 +89,7 @@ func MonadChainFirst[E, A, B any](ma Either[E, A], f func(a A) Either[E, B]) Eit
|
||||
})
|
||||
}
|
||||
|
||||
func MonadChainTo[E, A, B any](ma Either[E, A], mb Either[E, B]) Either[E, B] {
|
||||
func MonadChainTo[A, E, B any](ma Either[E, A], mb Either[E, B]) Either[E, B] {
|
||||
return mb
|
||||
}
|
||||
|
||||
@@ -104,8 +104,8 @@ func ChainOptionK[A, B, E any](onNone func() E) func(func(A) O.Option[B]) func(E
|
||||
}
|
||||
}
|
||||
|
||||
func ChainTo[E, A, B any](mb Either[E, B]) func(Either[E, A]) Either[E, B] {
|
||||
return F.Bind2nd(MonadChainTo[E, A, B], mb)
|
||||
func ChainTo[A, E, B any](mb Either[E, B]) func(Either[E, A]) Either[E, B] {
|
||||
return F.Bind2nd(MonadChainTo[A, E, B], mb)
|
||||
}
|
||||
|
||||
func Chain[E, A, B any](f func(a A) Either[E, B]) func(Either[E, A]) Either[E, B] {
|
||||
|
||||
@@ -41,7 +41,7 @@ func Logger[E, A any](loggers ...*log.Logger) func(string) func(Either[E, A]) Ei
|
||||
return func(ma Either[E, A]) Either[E, A] {
|
||||
return F.Pipe1(
|
||||
delegate(ma),
|
||||
ChainTo[E, A](ma),
|
||||
ChainTo[A](ma),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,16 @@ func MonadChain[A, B, HKTFA, HKTFB any](
|
||||
return fchain(ma, O.Fold(F.Nullary2(O.None[B], fof), f))
|
||||
}
|
||||
|
||||
func Chain[A, B, HKTFA, HKTFB any](
|
||||
fchain func(HKTFA, func(O.Option[A]) HKTFB) HKTFB,
|
||||
fof func(O.Option[B]) HKTFB,
|
||||
f func(A) HKTFB) func(ma HKTFA) HKTFB {
|
||||
// dispatch to the even more generic implementation
|
||||
return func(ma HKTFA) HKTFB {
|
||||
return MonadChain(fchain, fof, ma, f)
|
||||
}
|
||||
}
|
||||
|
||||
func MonadAp[A, B, HKTFAB, HKTFGAB, HKTFA, HKTFB any](
|
||||
fap func(HKTFGAB, HKTFA) HKTFB,
|
||||
fmap func(HKTFAB, func(O.Option[func(A) B]) func(O.Option[A]) O.Option[B]) HKTFGAB,
|
||||
|
||||
@@ -197,12 +197,12 @@ func GetOrElse[E, A any](onLeft func(E) I.IO[A]) func(IOEither[E, A]) I.IO[A] {
|
||||
}
|
||||
|
||||
// MonadChainTo composes to the second monad ignoring the return value of the first
|
||||
func MonadChainTo[E, A, B any](fa IOEither[E, A], fb IOEither[E, B]) IOEither[E, B] {
|
||||
func MonadChainTo[A, E, B any](fa IOEither[E, A], fb IOEither[E, B]) IOEither[E, B] {
|
||||
return G.MonadChainTo(fa, fb)
|
||||
}
|
||||
|
||||
// ChainTo composes to the second [IOEither] monad ignoring the return value of the first
|
||||
func ChainTo[E, A, B any](fb IOEither[E, B]) func(IOEither[E, A]) IOEither[E, B] {
|
||||
func ChainTo[A, E, B any](fb IOEither[E, B]) func(IOEither[E, A]) IOEither[E, B] {
|
||||
return G.ChainTo[IOEither[E, A]](fb)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
ET "github.com/IBM/fp-go/either"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
C "github.com/IBM/fp-go/internal/chain"
|
||||
FI "github.com/IBM/fp-go/internal/fromio"
|
||||
"github.com/IBM/fp-go/internal/optiont"
|
||||
IO "github.com/IBM/fp-go/io/generic"
|
||||
@@ -76,8 +77,48 @@ func MonadChain[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](fa GA,
|
||||
return optiont.MonadChain(IO.MonadChain[GA, GB, O.Option[A], O.Option[B]], IO.MonadOf[GB, O.Option[B]], fa, f)
|
||||
}
|
||||
|
||||
// MonadChainFirst runs the monad returned by the function but returns the result of the original monad
|
||||
func MonadChainFirst[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](ma GA, f func(A) GB) GA {
|
||||
return C.MonadChainFirst(
|
||||
MonadChain[GA, GA, A, A],
|
||||
MonadMap[GB, GA, B, A],
|
||||
ma,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// ChainFirst runs the monad returned by the function but returns the result of the original monad
|
||||
func ChainFirst[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) GB) func(GA) GA {
|
||||
return C.ChainFirst(
|
||||
MonadChain[GA, GA, A, A],
|
||||
MonadMap[GB, GA, B, A],
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// MonadChainFirstIOK runs the monad returned by the function but returns the result of the original monad
|
||||
func MonadChainFirstIOK[GA ~func() O.Option[A], GIOB ~func() B, A, B any](first GA, f func(A) GIOB) GA {
|
||||
return FI.MonadChainFirstIOK(
|
||||
MonadChain[GA, GA, A, A],
|
||||
MonadMap[func() O.Option[B], GA, B, A],
|
||||
FromIO[func() O.Option[B], GIOB, B],
|
||||
first,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// ChainFirstIOK runs the monad returned by the function but returns the result of the original monad
|
||||
func ChainFirstIOK[GA ~func() O.Option[A], GIOB ~func() B, A, B any](f func(A) GIOB) func(GA) GA {
|
||||
return FI.ChainFirstIOK(
|
||||
MonadChain[GA, GA, A, A],
|
||||
MonadMap[func() O.Option[B], GA, B, A],
|
||||
FromIO[func() O.Option[B], GIOB, B],
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func Chain[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) GB) func(GA) GB {
|
||||
return F.Bind2nd(MonadChain[GA, GB, A, B], f)
|
||||
return optiont.Chain(IO.MonadChain[GA, GB, O.Option[A], O.Option[B]], IO.MonadOf[GB, O.Option[B]], f)
|
||||
}
|
||||
|
||||
func MonadChainOptionK[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](ma GA, f func(A) O.Option[B]) GB {
|
||||
|
||||
@@ -18,6 +18,7 @@ package iooption
|
||||
import (
|
||||
ET "github.com/IBM/fp-go/either"
|
||||
I "github.com/IBM/fp-go/io"
|
||||
IO "github.com/IBM/fp-go/io"
|
||||
G "github.com/IBM/fp-go/iooption/generic"
|
||||
L "github.com/IBM/fp-go/lazy"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
@@ -143,3 +144,23 @@ func MonadAlt[A any](first IOOption[A], second L.Lazy[IOOption[A]]) IOOption[A]
|
||||
func Alt[A any](second L.Lazy[IOOption[A]]) func(IOOption[A]) IOOption[A] {
|
||||
return G.Alt(second)
|
||||
}
|
||||
|
||||
// MonadChainFirst runs the monad returned by the function but returns the result of the original monad
|
||||
func MonadChainFirst[A, B any](ma IOOption[A], f func(A) IOOption[B]) IOOption[A] {
|
||||
return G.MonadChainFirst[IOOption[A], IOOption[B]](ma, f)
|
||||
}
|
||||
|
||||
// ChainFirst runs the monad returned by the function but returns the result of the original monad
|
||||
func ChainFirst[A, B any](f func(A) IOOption[B]) func(IOOption[A]) IOOption[A] {
|
||||
return G.ChainFirst[IOOption[A], IOOption[B]](f)
|
||||
}
|
||||
|
||||
// MonadChainFirstIOK runs the monad returned by the function but returns the result of the original monad
|
||||
func MonadChainFirstIOK[A, B any](first IOOption[A], f func(A) IO.IO[B]) IOOption[A] {
|
||||
return G.MonadChainFirstIOK[IOOption[A], IO.IO[B]](first, f)
|
||||
}
|
||||
|
||||
// ChainFirstIOK runs the monad returned by the function but returns the result of the original monad
|
||||
func ChainFirstIOK[A, B any](f func(A) IO.IO[B]) func(IOOption[A]) IOOption[A] {
|
||||
return G.ChainFirstIOK[IOOption[A], IO.IO[B]](f)
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@ import (
|
||||
G "github.com/IBM/fp-go/iterator/stateless/generic"
|
||||
)
|
||||
|
||||
// StrictUniq converts an [Iterator] or arbitrary items into an [Iterator] or unique items
|
||||
// StrictUniq converts an [Iterator] of arbitrary items into an [Iterator] or unique items
|
||||
// where uniqueness is determined by the built-in uniqueness constraint
|
||||
func StrictUniq[A comparable](as Iterator[A]) Iterator[A] {
|
||||
return G.StrictUniq[Iterator[A]](as)
|
||||
}
|
||||
|
||||
// Uniq converts an [Iterator] or arbitrary items into an [Iterator] or unique items
|
||||
// Uniq converts an [Iterator] of arbitrary items into an [Iterator] or unique items
|
||||
// where uniqueness is determined based on a key extractor function
|
||||
func Uniq[A any, K comparable](f func(A) K) func(as Iterator[A]) Iterator[A] {
|
||||
return G.Uniq[Iterator[A], K](f)
|
||||
|
||||
@@ -65,7 +65,7 @@ func SequenceArray[A any](ma []Option[A]) Option[[]A] {
|
||||
func CompactArrayG[A1 ~[]Option[A], A2 ~[]A, A any](fa A1) A2 {
|
||||
return RA.Reduce(fa, func(out A2, value Option[A]) A2 {
|
||||
return MonadFold(value, F.Constant(out), F.Bind1st(RA.Append[A2, A], out))
|
||||
}, make(A2, len(fa)))
|
||||
}, make(A2, 0, len(fa)))
|
||||
}
|
||||
|
||||
// CompactArray discards the none values and keeps the some values
|
||||
|
||||
@@ -34,3 +34,14 @@ func TestSequenceArray(t *testing.T) {
|
||||
|
||||
assert.Equal(t, res, Of([]int{1, 2}))
|
||||
}
|
||||
|
||||
func TestCompactArray(t *testing.T) {
|
||||
ar := []Option[string]{
|
||||
Of("ok"),
|
||||
None[string](),
|
||||
Of("ok"),
|
||||
}
|
||||
|
||||
res := CompactArray(ar)
|
||||
assert.Equal(t, 2, len(res))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user