mirror of
https://github.com/IBM/fp-go.git
synced 2026-01-21 01:07:29 +02:00
Compare commits
3 Commits
v1.0.24
...
cleue-impl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f04344cda | ||
|
|
cf1c886f48 | ||
|
|
3e0eb99b88 |
@@ -44,3 +44,15 @@ func SequenceArrayG[GA ~[]A, GOA ~[]Either[E, A], E, A any](ma GOA) Either[E, GA
|
||||
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
|
||||
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)))
|
||||
}
|
||||
|
||||
// CompactArray discards the none values and keeps the some values
|
||||
func CompactArray[E, A any](fa []Either[E, A]) []A {
|
||||
return CompactArrayG[[]Either[E, A], []A](fa)
|
||||
}
|
||||
|
||||
@@ -91,11 +91,11 @@ func MonadChainTo[E, A, B any](ma Either[E, A], mb Either[E, B]) Either[E, B] {
|
||||
return mb
|
||||
}
|
||||
|
||||
func MonadChainOptionK[E, A, B any](onNone func() E, ma Either[E, A], f func(A) O.Option[B]) Either[E, B] {
|
||||
func MonadChainOptionK[A, B, E any](onNone func() E, ma Either[E, A], f func(A) O.Option[B]) Either[E, B] {
|
||||
return MonadChain(ma, F.Flow2(f, FromOption[E, B](onNone)))
|
||||
}
|
||||
|
||||
func ChainOptionK[E, A, B any](onNone func() E) func(func(A) O.Option[B]) func(Either[E, A]) Either[E, B] {
|
||||
func ChainOptionK[A, B, E any](onNone func() E) func(func(A) O.Option[B]) func(Either[E, A]) Either[E, B] {
|
||||
from := FromOption[E, B](onNone)
|
||||
return func(f func(A) O.Option[B]) func(Either[E, A]) Either[E, B] {
|
||||
return Chain(F.Flow2(f, from))
|
||||
|
||||
@@ -100,7 +100,7 @@ func TestChainFirst(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestChainOptionK(t *testing.T) {
|
||||
f := ChainOptionK[string, int, int](F.Constant("a"))(func(n int) O.Option[int] {
|
||||
f := ChainOptionK[int, int](F.Constant("a"))(func(n int) O.Option[int] {
|
||||
if n > 0 {
|
||||
return O.Some(n)
|
||||
}
|
||||
|
||||
@@ -43,3 +43,24 @@ func SequenceRecordG[GA ~map[K]A, GOA ~map[K]Either[E, A], K comparable, E, A an
|
||||
func SequenceRecord[K comparable, E, A any](ma map[K]Either[E, A]) Either[E, map[K]A] {
|
||||
return SequenceRecordG[map[K]A](ma)
|
||||
}
|
||||
|
||||
func upsertAtReadWrite[M ~map[K]V, K comparable, V any](r M, k K, v V) M {
|
||||
r[k] = v
|
||||
return r
|
||||
}
|
||||
|
||||
// CompactRecordG discards the noe values and keeps the some values
|
||||
func CompactRecordG[M1 ~map[K]Either[E, A], M2 ~map[K]A, K comparable, E, A any](m M1) M2 {
|
||||
out := make(M2)
|
||||
onLeft := F.Constant1[E](out)
|
||||
return RR.ReduceWithIndex(m, func(key K, _ M2, value Either[E, A]) M2 {
|
||||
return MonadFold(value, onLeft, func(v A) M2 {
|
||||
return upsertAtReadWrite(out, key, v)
|
||||
})
|
||||
}, out)
|
||||
}
|
||||
|
||||
// CompactRecord discards all none values and keeps the somes
|
||||
func CompactRecord[K comparable, E, A any](m map[K]Either[E, A]) map[K]A {
|
||||
return CompactRecordG[map[K]Either[E, A], map[K]A](m)
|
||||
}
|
||||
|
||||
37
either/record_test.go
Normal file
37
either/record_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// 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 either
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCompactRecord(t *testing.T) {
|
||||
// make the map
|
||||
m := make(map[string]Either[string, int])
|
||||
m["foo"] = Left[int]("error")
|
||||
m["bar"] = Right[string](1)
|
||||
// compact it
|
||||
m1 := CompactRecord(m)
|
||||
// check expected
|
||||
exp := map[string]int{
|
||||
"bar": 1,
|
||||
}
|
||||
|
||||
assert.Equal(t, exp, m1)
|
||||
}
|
||||
@@ -44,3 +44,15 @@ func SequenceArrayG[GA ~[]A, GOA ~[]Option[A], A any](ma GOA) Option[GA] {
|
||||
func SequenceArray[A any](ma []Option[A]) Option[[]A] {
|
||||
return SequenceArrayG[[]A](ma)
|
||||
}
|
||||
|
||||
// CompactArrayG discards the none values and keeps the some values
|
||||
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)))
|
||||
}
|
||||
|
||||
// CompactArray discards the none values and keeps the some values
|
||||
func CompactArray[A any](fa []Option[A]) []A {
|
||||
return CompactArrayG[[]Option[A], []A](fa)
|
||||
}
|
||||
|
||||
@@ -44,3 +44,21 @@ func SequenceRecordG[GA ~map[K]A, GOA ~map[K]Option[A], K comparable, A any](ma
|
||||
func SequenceRecord[K comparable, A any](ma map[K]Option[A]) Option[map[K]A] {
|
||||
return SequenceRecordG[map[K]A](ma)
|
||||
}
|
||||
|
||||
func upsertAtReadWrite[M ~map[K]V, K comparable, V any](r M, k K, v V) M {
|
||||
r[k] = v
|
||||
return r
|
||||
}
|
||||
|
||||
// CompactRecordG discards the noe values and keeps the some values
|
||||
func CompactRecordG[M1 ~map[K]Option[A], M2 ~map[K]A, K comparable, A any](m M1) M2 {
|
||||
bnd := F.Bind12of3(upsertAtReadWrite[M2])
|
||||
return RR.ReduceWithIndex(m, func(key K, m M2, value Option[A]) M2 {
|
||||
return MonadFold(value, F.Constant(m), bnd(m, key))
|
||||
}, make(M2))
|
||||
}
|
||||
|
||||
// CompactRecord discards the noe values and keeps the some values
|
||||
func CompactRecord[K comparable, A any](m map[K]Option[A]) map[K]A {
|
||||
return CompactRecordG[map[K]Option[A], map[K]A](m)
|
||||
}
|
||||
|
||||
@@ -30,3 +30,18 @@ func TestSequenceRecord(t *testing.T) {
|
||||
"b": Of("B"),
|
||||
}))
|
||||
}
|
||||
|
||||
func TestCompactRecord(t *testing.T) {
|
||||
// make the map
|
||||
m := make(map[string]Option[int])
|
||||
m["foo"] = None[int]()
|
||||
m["bar"] = Some(1)
|
||||
// compact it
|
||||
m1 := CompactRecord(m)
|
||||
// check expected
|
||||
exp := map[string]int{
|
||||
"bar": 1,
|
||||
}
|
||||
|
||||
assert.Equal(t, exp, m1)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
// AssertLaws asserts the apply monad laws for the `Either` monad
|
||||
// AssertLaws asserts the apply monad laws for the [Option] monad
|
||||
func AssertLaws[A, B, C any](t *testing.T,
|
||||
eqa EQ.Eq[A],
|
||||
eqb EQ.Eq[B],
|
||||
|
||||
@@ -32,7 +32,7 @@ func FromEither[E, L, A any](e ET.Either[L, A]) ReaderEither[E, L, A] {
|
||||
return G.FromEither[ReaderEither[E, L, A]](e)
|
||||
}
|
||||
|
||||
func RightReader[E, L, A any](r R.Reader[E, A]) ReaderEither[E, L, A] {
|
||||
func RightReader[L, E, A any](r R.Reader[E, A]) ReaderEither[E, L, A] {
|
||||
return G.RightReader[R.Reader[E, A], ReaderEither[E, L, A]](r)
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ func MonadAp[E, L, A, B any](fab ReaderEither[E, L, func(A) B], fa ReaderEither[
|
||||
return G.MonadAp[ReaderEither[E, L, A], ReaderEither[E, L, B], ReaderEither[E, L, func(A) B]](fab, fa)
|
||||
}
|
||||
|
||||
func Ap[E, L, A, B any](fa ReaderEither[E, L, A]) func(ReaderEither[E, L, func(A) B]) ReaderEither[E, L, B] {
|
||||
func Ap[B, E, L, A any](fa ReaderEither[E, L, A]) func(ReaderEither[E, L, func(A) B]) ReaderEither[E, L, B] {
|
||||
return G.Ap[ReaderEither[E, L, A], ReaderEither[E, L, B], ReaderEither[E, L, func(A) B]](fa)
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ func OrElse[E, L1, A, L2 any](onLeft func(L1) ReaderEither[E, L2, A]) func(Reade
|
||||
return G.OrElse[ReaderEither[E, L1, A]](onLeft)
|
||||
}
|
||||
|
||||
func OrLeft[L1, E, L2, A any](onLeft func(L1) R.Reader[E, L2]) func(ReaderEither[E, L1, A]) ReaderEither[E, L2, A] {
|
||||
func OrLeft[A, L1, E, L2 any](onLeft func(L1) R.Reader[E, L2]) func(ReaderEither[E, L1, A]) ReaderEither[E, L2, A] {
|
||||
return G.OrLeft[ReaderEither[E, L1, A], ReaderEither[E, L2, A]](onLeft)
|
||||
}
|
||||
|
||||
@@ -104,19 +104,19 @@ func Ask[E, L any]() ReaderEither[E, L, E] {
|
||||
return G.Ask[ReaderEither[E, L, E]]()
|
||||
}
|
||||
|
||||
func Asks[E, L, A any](r R.Reader[E, A]) ReaderEither[E, L, A] {
|
||||
func Asks[L, E, A any](r R.Reader[E, A]) ReaderEither[E, L, A] {
|
||||
return G.Asks[R.Reader[E, A], ReaderEither[E, L, A]](r)
|
||||
}
|
||||
|
||||
func MonadChainEitherK[E, L, A, B any](ma ReaderEither[E, L, A], f func(A) ET.Either[L, B]) ReaderEither[E, L, B] {
|
||||
func MonadChainEitherK[A, B, L, E any](ma ReaderEither[E, L, A], f func(A) ET.Either[L, B]) ReaderEither[E, L, B] {
|
||||
return G.MonadChainEitherK[ReaderEither[E, L, A], ReaderEither[E, L, B]](ma, f)
|
||||
}
|
||||
|
||||
func ChainEitherK[E, L, A, B any](f func(A) ET.Either[L, B]) func(ma ReaderEither[E, L, A]) ReaderEither[E, L, B] {
|
||||
func ChainEitherK[A, B, L, E any](f func(A) ET.Either[L, B]) func(ma ReaderEither[E, L, A]) ReaderEither[E, L, B] {
|
||||
return G.ChainEitherK[ReaderEither[E, L, A], ReaderEither[E, L, B]](f)
|
||||
}
|
||||
|
||||
func ChainOptionK[E, L, A, B any](onNone func() L) func(func(A) O.Option[B]) func(ReaderEither[E, L, A]) ReaderEither[E, L, B] {
|
||||
func ChainOptionK[E, A, B, L any](onNone func() L) func(func(A) O.Option[B]) func(ReaderEither[E, L, A]) ReaderEither[E, L, B] {
|
||||
return G.ChainOptionK[ReaderEither[E, L, A], ReaderEither[E, L, B]](onNone)
|
||||
}
|
||||
|
||||
@@ -135,11 +135,11 @@ func BiMap[E, E1, E2, A, B any](f func(E1) E2, g func(A) B) func(ReaderEither[E,
|
||||
|
||||
// Local changes the value of the local context during the execution of the action `ma` (similar to `Contravariant`'s
|
||||
// `contramap`).
|
||||
func Local[R2, R1, E, A any](f func(R2) R1) func(ReaderEither[R1, E, A]) ReaderEither[R2, E, A] {
|
||||
func Local[E, A, R2, R1 any](f func(R2) R1) func(ReaderEither[R1, E, A]) ReaderEither[R2, E, A] {
|
||||
return G.Local[ReaderEither[R1, E, A], ReaderEither[R2, E, A]](f)
|
||||
}
|
||||
|
||||
// Read applies a context to a reader to obtain its value
|
||||
func Read[E, E1, A any](e E) func(ReaderEither[E, E1, A]) ET.Either[E1, A] {
|
||||
func Read[E1, A, E any](e E) func(ReaderEither[E, E1, A]) ET.Either[E1, A] {
|
||||
return G.Read[ReaderEither[E, E1, A]](e)
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestMap(t *testing.T) {
|
||||
func TestAp(t *testing.T) {
|
||||
g := F.Pipe1(
|
||||
Of[MyContext, error](utils.Double),
|
||||
Ap[MyContext, error, int, int](Of[MyContext, error](1)),
|
||||
Ap[int](Of[MyContext, error](1)),
|
||||
)
|
||||
assert.Equal(t, ET.Of[error](2), g(defaultContext))
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ func MonadChainReaderK[R, E, A, B any](ma ReaderIOEither[R, E, A], f func(A) RD.
|
||||
return G.MonadChainReaderK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](ma, f)
|
||||
}
|
||||
|
||||
func ChainReaderK[R, E, A, B any](f func(A) RD.Reader[R, B]) func(ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
func ChainReaderK[E, R, A, B any](f func(A) RD.Reader[R, B]) func(ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.ChainReaderK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](f)
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func ChainFirstIOK[R, E, A, B any](f func(A) io.IO[B]) func(ma ReaderIOEither[R,
|
||||
return G.ChainFirstIOK[ReaderIOEither[R, E, A]](f)
|
||||
}
|
||||
|
||||
func ChainOptionK[R, E, A, B any](onNone func() E) func(func(A) O.Option[B]) func(ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
func ChainOptionK[R, A, B, E any](onNone func() E) func(func(A) O.Option[B]) func(ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.ChainOptionK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](onNone)
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ func Left[R, A, E any](e E) ReaderIOEither[R, E, A] {
|
||||
return G.Left[ReaderIOEither[R, E, A]](e)
|
||||
}
|
||||
|
||||
func ThrowError[R, E, A any](e E) ReaderIOEither[R, E, A] {
|
||||
func ThrowError[R, A, E any](e E) ReaderIOEither[R, E, A] {
|
||||
return G.ThrowError[ReaderIOEither[R, E, A]](e)
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ func FromEither[R, E, A any](t ET.Either[E, A]) ReaderIOEither[R, E, A] {
|
||||
return G.FromEither[ReaderIOEither[R, E, A]](t)
|
||||
}
|
||||
|
||||
func RightReader[R, E, A any](ma RD.Reader[R, A]) ReaderIOEither[R, E, A] {
|
||||
func RightReader[E, R, A any](ma RD.Reader[R, A]) ReaderIOEither[R, E, A] {
|
||||
return G.RightReader[RD.Reader[R, A], ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ func LeftReader[A, R, E any](ma RD.Reader[R, E]) ReaderIOEither[R, E, A] {
|
||||
return G.LeftReader[RD.Reader[R, E], ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
func FromReader[R, E, A any](ma RD.Reader[R, A]) ReaderIOEither[R, E, A] {
|
||||
func FromReader[E, R, A any](ma RD.Reader[R, A]) ReaderIOEither[R, E, A] {
|
||||
return G.FromReader[RD.Reader[R, A], ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
@@ -202,11 +202,11 @@ func Ask[R, E any]() ReaderIOEither[R, E, R] {
|
||||
return G.Ask[ReaderIOEither[R, E, R]]()
|
||||
}
|
||||
|
||||
func Asks[R, E, A any](r RD.Reader[R, A]) ReaderIOEither[R, E, A] {
|
||||
func Asks[E, R, A any](r RD.Reader[R, A]) ReaderIOEither[R, E, A] {
|
||||
return G.Asks[RD.Reader[R, A], ReaderIOEither[R, E, A]](r)
|
||||
}
|
||||
|
||||
func FromOption[R, E, A any](onNone func() E) func(O.Option[A]) ReaderIOEither[R, E, A] {
|
||||
func FromOption[R, A, E any](onNone func() E) func(O.Option[A]) ReaderIOEither[R, E, A] {
|
||||
return G.FromOption[ReaderIOEither[R, E, A]](onNone)
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ func OrElse[R, E1, A, E2 any](onLeft func(E1) ReaderIOEither[R, E2, A]) func(Rea
|
||||
return G.OrElse[ReaderIOEither[R, E1, A]](onLeft)
|
||||
}
|
||||
|
||||
func OrLeft[E1, R, E2, A any](onLeft func(E1) RIO.ReaderIO[R, E2]) func(ReaderIOEither[R, E1, A]) ReaderIOEither[R, E2, A] {
|
||||
func OrLeft[A, E1, R, E2 any](onLeft func(E1) RIO.ReaderIO[R, E2]) func(ReaderIOEither[R, E1, A]) ReaderIOEither[R, E2, A] {
|
||||
return G.OrLeft[ReaderIOEither[R, E1, A], RIO.ReaderIO[R, E2], ReaderIOEither[R, E2, A]](onLeft)
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestMap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOrLeft(t *testing.T) {
|
||||
f := OrLeft[string, context.Context, string, int](func(s string) RIO.ReaderIO[context.Context, string] {
|
||||
f := OrLeft[int](func(s string) RIO.ReaderIO[context.Context, string] {
|
||||
return RIO.Of[context.Context](s + "!")
|
||||
})
|
||||
|
||||
@@ -70,7 +70,7 @@ func TestChainReaderK(t *testing.T) {
|
||||
|
||||
g := F.Pipe1(
|
||||
Of[context.Context, error](1),
|
||||
ChainReaderK[context.Context, error](func(v int) R.Reader[context.Context, string] {
|
||||
ChainReaderK[error](func(v int) R.Reader[context.Context, string] {
|
||||
return R.Of[context.Context](fmt.Sprintf("%d", v))
|
||||
}),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user