mirror of
https://github.com/IBM/fp-go.git
synced 2025-11-25 22:21:49 +02:00
fix: ChainReaderK
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
@@ -365,13 +365,13 @@ func Asks[R, A any](r Reader[R, A]) ReaderResult[R, A] {
|
|||||||
//
|
//
|
||||||
// parseUser := func(data string) result.Result[User] { ... }
|
// parseUser := func(data string) result.Result[User] { ... }
|
||||||
// result := readerresult.MonadChainEitherK(getUserDataRR, parseUser)
|
// result := readerresult.MonadChainEitherK(getUserDataRR, parseUser)
|
||||||
func MonadChainEitherK[R, A, B any](ma ReaderResult[R, A], f result.Kleisli[A, B]) ReaderResult[R, B] {
|
func MonadChainEitherK[R, A, B any](ma ReaderResult[R, A], f RES.Kleisli[A, B]) ReaderResult[R, B] {
|
||||||
return func(r R) (B, error) {
|
return func(r R) (B, error) {
|
||||||
a, err := ma(r)
|
a, err := ma(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result.Left[B](err)
|
return result.Left[B](err)
|
||||||
}
|
}
|
||||||
return f(a)
|
return RES.Unwrap(f(a))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,10 +384,40 @@ func MonadChainEitherK[R, A, B any](ma ReaderResult[R, A], f result.Kleisli[A, B
|
|||||||
// result := F.Pipe1(getUserDataRR, readerresult.ChainEitherK[Config](parseUser))
|
// result := F.Pipe1(getUserDataRR, readerresult.ChainEitherK[Config](parseUser))
|
||||||
//
|
//
|
||||||
//go:inline
|
//go:inline
|
||||||
func ChainEitherK[R, A, B any](f result.Kleisli[A, B]) Operator[R, A, B] {
|
func ChainEitherK[R, A, B any](f RES.Kleisli[A, B]) Operator[R, A, B] {
|
||||||
return function.Bind2nd(MonadChainEitherK[R, A, B], f)
|
return function.Bind2nd(MonadChainEitherK[R, A, B], f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MonadChainReaderK chains a ReaderResult with a function that returns a plain Result.
|
||||||
|
// This is useful for integrating functions that don't need environment access.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// parseUser := func(data string) result.Result[User] { ... }
|
||||||
|
// result := readerresult.MonadChainReaderK(getUserDataRR, parseUser)
|
||||||
|
func MonadChainReaderK[R, A, B any](ma ReaderResult[R, A], f result.Kleisli[A, B]) ReaderResult[R, B] {
|
||||||
|
return func(r R) (B, error) {
|
||||||
|
a, err := ma(r)
|
||||||
|
if err != nil {
|
||||||
|
return result.Left[B](err)
|
||||||
|
}
|
||||||
|
return f(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainReaderK is the curried version of MonadChainEitherK.
|
||||||
|
// It lifts a Result-returning function into a ReaderResult operator.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// parseUser := func(data string) result.Result[User] { ... }
|
||||||
|
// result := F.Pipe1(getUserDataRR, readerresult.ChainReaderK[Config](parseUser))
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
|
func ChainReaderK[R, A, B any](f result.Kleisli[A, B]) Operator[R, A, B] {
|
||||||
|
return function.Bind2nd(MonadChainReaderK[R, A, B], f)
|
||||||
|
}
|
||||||
|
|
||||||
// ChainOptionK chains with a function that returns an Option, converting None to an error.
|
// ChainOptionK chains with a function that returns an Option, converting None to an error.
|
||||||
// This is useful for integrating functions that return optional values.
|
// This is useful for integrating functions that return optional values.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
"github.com/IBM/fp-go/v2/internal/utils"
|
"github.com/IBM/fp-go/v2/internal/utils"
|
||||||
"github.com/IBM/fp-go/v2/reader"
|
"github.com/IBM/fp-go/v2/reader"
|
||||||
"github.com/IBM/fp-go/v2/result"
|
"github.com/IBM/fp-go/v2/result"
|
||||||
|
RES "github.com/IBM/fp-go/v2/result"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -271,7 +272,7 @@ func TestAsks(t *testing.T) {
|
|||||||
assert.Equal(t, 7, v)
|
assert.Equal(t, 7, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChainEitherK(t *testing.T) {
|
func TestChainReaderK(t *testing.T) {
|
||||||
parseInt := func(s string) (int, error) {
|
parseInt := func(s string) (int, error) {
|
||||||
if s == "42" {
|
if s == "42" {
|
||||||
return 42, nil
|
return 42, nil
|
||||||
@@ -279,6 +280,24 @@ func TestChainEitherK(t *testing.T) {
|
|||||||
return 0, errors.New("parse error")
|
return 0, errors.New("parse error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chain := ChainReaderK[MyContext](parseInt)
|
||||||
|
|
||||||
|
v, err := F.Pipe1(Of[MyContext]("42"), chain)(defaultContext)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 42, v)
|
||||||
|
|
||||||
|
_, err = F.Pipe1(Of[MyContext]("invalid"), chain)(defaultContext)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChainEitherK(t *testing.T) {
|
||||||
|
parseInt := func(s string) RES.Result[int] {
|
||||||
|
if s == "42" {
|
||||||
|
return RES.Of(42)
|
||||||
|
}
|
||||||
|
return RES.Left[int](errors.New("parse error"))
|
||||||
|
}
|
||||||
|
|
||||||
chain := ChainEitherK[MyContext](parseInt)
|
chain := ChainEitherK[MyContext](parseInt)
|
||||||
|
|
||||||
v, err := F.Pipe1(Of[MyContext]("42"), chain)(defaultContext)
|
v, err := F.Pipe1(Of[MyContext]("42"), chain)(defaultContext)
|
||||||
|
|||||||
Reference in New Issue
Block a user