1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-11-23 22:14:53 +02:00

fix: add bind variations

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
Dr. Carsten Leue
2025-11-11 12:42:14 +01:00
parent 600521b220
commit 1af6501cd8
11 changed files with 1165 additions and 77 deletions

View File

@@ -18,9 +18,16 @@ package readerioresult
import (
"context"
F "github.com/IBM/fp-go/v2/function"
"github.com/IBM/fp-go/v2/internal/apply"
"github.com/IBM/fp-go/v2/io"
"github.com/IBM/fp-go/v2/ioeither"
"github.com/IBM/fp-go/v2/ioresult"
L "github.com/IBM/fp-go/v2/optics/lens"
"github.com/IBM/fp-go/v2/reader"
"github.com/IBM/fp-go/v2/readerio"
RIOR "github.com/IBM/fp-go/v2/readerioresult"
"github.com/IBM/fp-go/v2/result"
)
// Do creates an empty context of type [S] to be used with the [Bind] operation.
@@ -320,3 +327,346 @@ func LetToL[S, T any](
) Operator[S, S] {
return RIOR.LetToL[context.Context](lens, b)
}
// BindIOEitherK is a variant of Bind that works with IOEither computations.
// It lifts an IOEither Kleisli arrow into the ReaderIOResult context (with context.Context as environment).
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: An IOEither Kleisli arrow (S1 -> IOEither[error, T])
func BindIOEitherK[S1, S2, T any](
setter func(T) func(S1) S2,
f ioresult.Kleisli[S1, T],
) Operator[S1, S2] {
return Bind(setter, F.Flow2(f, FromIOEither[T]))
}
// BindIOResultK is a variant of Bind that works with IOResult computations.
// This is an alias for BindIOEitherK for consistency with the Result naming convention.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: An IOResult Kleisli arrow (S1 -> IOResult[T])
func BindIOResultK[S1, S2, T any](
setter func(T) func(S1) S2,
f ioresult.Kleisli[S1, T],
) Operator[S1, S2] {
return Bind(setter, F.Flow2(f, FromIOResult[T]))
}
// BindIOK is a variant of Bind that works with IO computations.
// It lifts an IO Kleisli arrow into the ReaderIOResult context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: An IO Kleisli arrow (S1 -> IO[T])
func BindIOK[S1, S2, T any](
setter func(T) func(S1) S2,
f io.Kleisli[S1, T],
) Operator[S1, S2] {
return Bind(setter, F.Flow2(f, FromIO[T]))
}
// BindReaderK is a variant of Bind that works with Reader computations.
// It lifts a Reader Kleisli arrow (with context.Context) into the ReaderIOResult context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: A Reader Kleisli arrow (S1 -> Reader[context.Context, T])
func BindReaderK[S1, S2, T any](
setter func(T) func(S1) S2,
f reader.Kleisli[context.Context, S1, T],
) Operator[S1, S2] {
return Bind(setter, F.Flow2(f, FromReader[T]))
}
// BindReaderIOK is a variant of Bind that works with ReaderIO computations.
// It lifts a ReaderIO Kleisli arrow (with context.Context) into the ReaderIOResult context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: A ReaderIO Kleisli arrow (S1 -> ReaderIO[context.Context, T])
func BindReaderIOK[S1, S2, T any](
setter func(T) func(S1) S2,
f readerio.Kleisli[context.Context, S1, T],
) Operator[S1, S2] {
return Bind(setter, F.Flow2(f, FromReaderIO[T]))
}
// BindEitherK is a variant of Bind that works with Either (Result) computations.
// It lifts an Either Kleisli arrow into the ReaderIOResult context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: An Either Kleisli arrow (S1 -> Either[error, T])
func BindEitherK[S1, S2, T any](
setter func(T) func(S1) S2,
f result.Kleisli[S1, T],
) Operator[S1, S2] {
return Bind(setter, F.Flow2(f, FromEither[T]))
}
// BindResultK is a variant of Bind that works with Result computations.
// This is an alias for BindEitherK for consistency with the Result naming convention.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: A Result Kleisli arrow (S1 -> Result[T])
func BindResultK[S1, S2, T any](
setter func(T) func(S1) S2,
f result.Kleisli[S1, T],
) Operator[S1, S2] {
return Bind(setter, F.Flow2(f, FromResult[T]))
}
// BindIOEitherKL is a lens-based variant of BindIOEitherK.
// It combines a lens with an IOEither Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: An IOEither Kleisli arrow (T -> IOEither[error, T])
func BindIOEitherKL[S, T any](
lens L.Lens[S, T],
f ioresult.Kleisli[T, T],
) Operator[S, S] {
return BindL(lens, F.Flow2(f, FromIOEither[T]))
}
// BindIOResultKL is a lens-based variant of BindIOResultK.
// This is an alias for BindIOEitherKL for consistency with the Result naming convention.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: An IOResult Kleisli arrow (T -> IOResult[T])
func BindIOResultKL[S, T any](
lens L.Lens[S, T],
f ioresult.Kleisli[T, T],
) Operator[S, S] {
return BindL(lens, F.Flow2(f, FromIOEither[T]))
}
// BindIOKL is a lens-based variant of BindIOK.
// It combines a lens with an IO Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: An IO Kleisli arrow (T -> IO[T])
func BindIOKL[S, T any](
lens L.Lens[S, T],
f io.Kleisli[T, T],
) Operator[S, S] {
return BindL(lens, F.Flow2(f, FromIO[T]))
}
// BindReaderKL is a lens-based variant of BindReaderK.
// It combines a lens with a Reader Kleisli arrow (with context.Context), focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: A Reader Kleisli arrow (T -> Reader[context.Context, T])
func BindReaderKL[S, T any](
lens L.Lens[S, T],
f reader.Kleisli[context.Context, T, T],
) Operator[S, S] {
return BindL(lens, F.Flow2(f, FromReader[T]))
}
// BindReaderIOKL is a lens-based variant of BindReaderIOK.
// It combines a lens with a ReaderIO Kleisli arrow (with context.Context), focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: A ReaderIO Kleisli arrow (T -> ReaderIO[context.Context, T])
func BindReaderIOKL[S, T any](
lens L.Lens[S, T],
f readerio.Kleisli[context.Context, T, T],
) Operator[S, S] {
return BindL(lens, F.Flow2(f, FromReaderIO[T]))
}
// ApIOEitherS is an applicative variant that works with IOEither values.
// Unlike BindIOEitherK, this uses applicative composition (ApS) instead of monadic
// composition (Bind), allowing independent computations to be combined.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An IOEither value
func ApIOEitherS[S1, S2, T any](
setter func(T) func(S1) S2,
fa IOResult[T],
) Operator[S1, S2] {
return F.Bind2nd(F.Flow2[ReaderIOResult[S1], ioresult.Operator[S1, S2]], ioeither.ApS(setter, fa))
}
// ApIOResultS is an applicative variant that works with IOResult values.
// This is an alias for ApIOEitherS for consistency with the Result naming convention.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An IOResult value
func ApIOResultS[S1, S2, T any](
setter func(T) func(S1) S2,
fa IOResult[T],
) Operator[S1, S2] {
return F.Bind2nd(F.Flow2[ReaderIOResult[S1], ioresult.Operator[S1, S2]], ioeither.ApS(setter, fa))
}
// ApIOS is an applicative variant that works with IO values.
// It lifts an IO value into the ReaderIOResult context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An IO value
func ApIOS[S1, S2, T any](
setter func(T) func(S1) S2,
fa IO[T],
) Operator[S1, S2] {
return ApS(setter, FromIO(fa))
}
// ApReaderS is an applicative variant that works with Reader values.
// It lifts a Reader value (with context.Context) into the ReaderIOResult context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: A Reader value
func ApReaderS[S1, S2, T any](
setter func(T) func(S1) S2,
fa Reader[context.Context, T],
) Operator[S1, S2] {
return ApS(setter, FromReader[T](fa))
}
// ApReaderIOS is an applicative variant that works with ReaderIO values.
// It lifts a ReaderIO value (with context.Context) into the ReaderIOResult context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: A ReaderIO value
func ApReaderIOS[S1, S2, T any](
setter func(T) func(S1) S2,
fa ReaderIO[T],
) Operator[S1, S2] {
return ApS(setter, FromReaderIO[T](fa))
}
// ApEitherS is an applicative variant that works with Either (Result) values.
// It lifts an Either value into the ReaderIOResult context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An Either value
func ApEitherS[S1, S2, T any](
setter func(T) func(S1) S2,
fa Result[T],
) Operator[S1, S2] {
return ApS(setter, FromEither[T](fa))
}
// ApResultS is an applicative variant that works with Result values.
// This is an alias for ApEitherS for consistency with the Result naming convention.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: A Result value
func ApResultS[S1, S2, T any](
setter func(T) func(S1) S2,
fa Result[T],
) Operator[S1, S2] {
return ApS(setter, FromResult[T](fa))
}
// ApIOEitherSL is a lens-based variant of ApIOEitherS.
// It combines a lens with an IOEither value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An IOEither value
func ApIOEitherSL[S, T any](
lens L.Lens[S, T],
fa IOResult[T],
) Operator[S, S] {
return F.Bind2nd(F.Flow2[ReaderIOResult[S], ioresult.Operator[S, S]], ioresult.ApSL(lens, fa))
}
// ApIOResultSL is a lens-based variant of ApIOResultS.
// This is an alias for ApIOEitherSL for consistency with the Result naming convention.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An IOResult value
func ApIOResultSL[S, T any](
lens L.Lens[S, T],
fa IOResult[T],
) Operator[S, S] {
return F.Bind2nd(F.Flow2[ReaderIOResult[S], ioresult.Operator[S, S]], ioresult.ApSL(lens, fa))
}
// ApIOSL is a lens-based variant of ApIOS.
// It combines a lens with an IO value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An IO value
func ApIOSL[S, T any](
lens L.Lens[S, T],
fa IO[T],
) Operator[S, S] {
return ApSL(lens, FromIO(fa))
}
// ApReaderSL is a lens-based variant of ApReaderS.
// It combines a lens with a Reader value (with context.Context) using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: A Reader value
func ApReaderSL[S, T any](
lens L.Lens[S, T],
fa Reader[context.Context, T],
) Operator[S, S] {
return ApSL(lens, FromReader[T](fa))
}
// ApReaderIOSL is a lens-based variant of ApReaderIOS.
// It combines a lens with a ReaderIO value (with context.Context) using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: A ReaderIO value
func ApReaderIOSL[S, T any](
lens L.Lens[S, T],
fa ReaderIO[T],
) Operator[S, S] {
return ApSL(lens, FromReaderIO[T](fa))
}
// ApEitherSL is a lens-based variant of ApEitherS.
// It combines a lens with an Either value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An Either value
func ApEitherSL[S, T any](
lens L.Lens[S, T],
fa Result[T],
) Operator[S, S] {
return ApSL(lens, FromEither[T](fa))
}
// ApResultSL is a lens-based variant of ApResultS.
// This is an alias for ApEitherSL for consistency with the Result naming convention.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: A Result value
func ApResultSL[S, T any](
lens L.Lens[S, T],
fa Result[T],
) Operator[S, S] {
return ApSL(lens, FromResult[T](fa))
}

View File

@@ -438,6 +438,11 @@ func FromIOEither[A any](t IOResult[A]) ReaderIOResult[A] {
return RIOR.FromIOEither[context.Context](t)
}
//go:inline
func FromIOResult[A any](t IOResult[A]) ReaderIOResult[A] {
return RIOR.FromIOResult[context.Context](t)
}
// FromIO converts an [IO] into a [ReaderIOResult].
// The IO computation always succeeds, so it's wrapped in Right.
//
@@ -451,6 +456,16 @@ func FromIO[A any](t IO[A]) ReaderIOResult[A] {
return RIOR.FromIO[context.Context](t)
}
//go:inline
func FromReader[A any](t Reader[context.Context, A]) ReaderIOResult[A] {
return RIOR.FromReader[context.Context](t)
}
//go:inline
func FromReaderIO[A any](t ReaderIO[A]) ReaderIOResult[A] {
return RIOR.FromReaderIO[context.Context](t)
}
// FromLazy converts a [Lazy] computation into a [ReaderIOResult].
// The Lazy computation always succeeds, so it's wrapped in Right.
// This is an alias for [FromIO] since Lazy and IO have the same structure.

View File

@@ -25,5 +25,6 @@ type (
Reader[R, A any] = reader.Reader[R, A]
ReaderIO[R, A any] = Reader[R, IO[A]]
Operator[R, A, B any] = Reader[ReaderIO[R, A], ReaderIO[R, B]]
Kleisli[R, A, B any] = Reader[A, ReaderIO[R, B]]
Operator[R, A, B any] = Kleisli[R, ReaderIO[R, A], B]
)

View File

@@ -16,9 +16,13 @@
package readerioeither
import (
"github.com/IBM/fp-go/v2/either"
F "github.com/IBM/fp-go/v2/function"
IOE "github.com/IBM/fp-go/v2/ioeither"
"github.com/IBM/fp-go/v2/io"
"github.com/IBM/fp-go/v2/ioeither"
L "github.com/IBM/fp-go/v2/optics/lens"
"github.com/IBM/fp-go/v2/reader"
"github.com/IBM/fp-go/v2/readerio"
G "github.com/IBM/fp-go/v2/readerioeither/generic"
)
@@ -102,7 +106,7 @@ func Let[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
f func(S1) T,
) Operator[R, E, S1, S2] {
return G.Let[ReaderIOEither[R, E, S1], ReaderIOEither[R, E, S2], IOE.IOEither[E, S1], IOE.IOEither[E, S2], R, E, S1, S2, T](setter, f)
return G.Let[ReaderIOEither[R, E, S1], ReaderIOEither[R, E, S2], ioeither.IOEither[E, S1], ioeither.IOEither[E, S2], R, E, S1, S2, T](setter, f)
}
// LetTo attaches the a value to a context [S1] to produce a context [S2]
@@ -112,7 +116,7 @@ func LetTo[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
b T,
) Operator[R, E, S1, S2] {
return G.LetTo[ReaderIOEither[R, E, S1], ReaderIOEither[R, E, S2], IOE.IOEither[E, S1], IOE.IOEither[E, S2], R, E, S1, S2, T](setter, b)
return G.LetTo[ReaderIOEither[R, E, S1], ReaderIOEither[R, E, S2], ioeither.IOEither[E, S1], ioeither.IOEither[E, S2], R, E, S1, S2, T](setter, b)
}
// BindTo initializes a new state [S1] from a value [T]
@@ -121,7 +125,7 @@ func LetTo[R, E, S1, S2, T any](
func BindTo[R, E, S1, T any](
setter func(T) S1,
) Operator[R, E, T, S1] {
return G.BindTo[ReaderIOEither[R, E, S1], ReaderIOEither[R, E, T], IOE.IOEither[E, S1], IOE.IOEither[E, T], R, E, S1, T](setter)
return G.BindTo[ReaderIOEither[R, E, S1], ReaderIOEither[R, E, T], ioeither.IOEither[E, S1], ioeither.IOEither[E, T], R, E, S1, T](setter)
}
// ApS attaches a value to a context [S1] to produce a context [S2] by considering
@@ -171,7 +175,7 @@ func ApS[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
fa ReaderIOEither[R, E, T],
) Operator[R, E, S1, S2] {
return G.ApS[ReaderIOEither[R, E, func(T) S2], ReaderIOEither[R, E, S1], ReaderIOEither[R, E, S2], ReaderIOEither[R, E, T], IOE.IOEither[E, func(T) S2], IOE.IOEither[E, S1], IOE.IOEither[E, S2], IOE.IOEither[E, T], R, E, S1, S2, T](setter, fa)
return G.ApS[ReaderIOEither[R, E, func(T) S2], ReaderIOEither[R, E, S1], ReaderIOEither[R, E, S2], ReaderIOEither[R, E, T], ioeither.IOEither[E, func(T) S2], ioeither.IOEither[E, S1], ioeither.IOEither[E, S2], ioeither.IOEither[E, T], R, E, S1, S2, T](setter, fa)
}
// ApSL attaches a value to a context using a lens-based setter.
@@ -322,3 +326,259 @@ func LetToL[R, E, S, T any](
) Operator[R, E, S, S] {
return LetTo[R, E, S, S, T](lens.Set, b)
}
// BindIOEitherK is a variant of Bind that works with IOEither computations.
// It lifts an IOEither Kleisli arrow into the ReaderIOEither context, allowing you to
// compose IOEither operations within a do-notation chain.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: An IOEither Kleisli arrow (S1 -> IOEither[E, T])
//
// Returns:
// - An Operator that can be used in a do-notation chain
func BindIOEitherK[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
f ioeither.Kleisli[E, S1, T],
) Operator[R, E, S1, S2] {
return Bind(setter, F.Flow2(f, FromIOEither[R, E, T]))
}
// BindIOK is a variant of Bind that works with IO computations.
// It lifts an IO Kleisli arrow into the ReaderIOEither context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: An IO Kleisli arrow (S1 -> IO[T])
func BindIOK[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
f io.Kleisli[S1, T],
) Operator[R, E, S1, S2] {
return Bind(setter, F.Flow2(f, FromIO[R, E, T]))
}
// BindReaderK is a variant of Bind that works with Reader computations.
// It lifts a Reader Kleisli arrow into the ReaderIOEither context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: A Reader Kleisli arrow (S1 -> Reader[R, T])
func BindReaderK[E, R, S1, S2, T any](
setter func(T) func(S1) S2,
f reader.Kleisli[R, S1, T],
) Operator[R, E, S1, S2] {
return Bind(setter, F.Flow2(f, FromReader[E, R, T]))
}
// BindReaderIOK is a variant of Bind that works with ReaderIO computations.
// It lifts a ReaderIO Kleisli arrow into the ReaderIOEither context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: A ReaderIO Kleisli arrow (S1 -> ReaderIO[R, T])
func BindReaderIOK[E, R, S1, S2, T any](
setter func(T) func(S1) S2,
f readerio.Kleisli[R, S1, T],
) Operator[R, E, S1, S2] {
return Bind(setter, F.Flow2(f, FromReaderIO[E, R, T]))
}
// BindEitherK is a variant of Bind that works with Either computations.
// It lifts an Either Kleisli arrow into the ReaderIOEither context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: An Either Kleisli arrow (S1 -> Either[E, T])
func BindEitherK[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
f either.Kleisli[E, S1, T],
) Operator[R, E, S1, S2] {
return Bind(setter, F.Flow2(f, FromEither[R, E, T]))
}
// BindIOEitherKL is a lens-based variant of BindIOEitherK.
// It combines a lens with an IOEither Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: An IOEither Kleisli arrow (T -> IOEither[E, T])
func BindIOEitherKL[R, E, S, T any](
lens L.Lens[S, T],
f ioeither.Kleisli[E, T, T],
) Operator[R, E, S, S] {
return BindL(lens, F.Flow2(f, FromIOEither[R, E, T]))
}
// BindIOKL is a lens-based variant of BindIOK.
// It combines a lens with an IO Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: An IO Kleisli arrow (T -> IO[T])
func BindIOKL[R, E, S, T any](
lens L.Lens[S, T],
f io.Kleisli[T, T],
) Operator[R, E, S, S] {
return BindL(lens, F.Flow2(f, FromIO[R, E, T]))
}
// BindReaderKL is a lens-based variant of BindReaderK.
// It combines a lens with a Reader Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: A Reader Kleisli arrow (T -> Reader[R, T])
func BindReaderKL[E, R, S, T any](
lens L.Lens[S, T],
f reader.Kleisli[R, T, T],
) Operator[R, E, S, S] {
return BindL(lens, F.Flow2(f, FromReader[E, R, T]))
}
// BindReaderIOKL is a lens-based variant of BindReaderIOK.
// It combines a lens with a ReaderIO Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: A ReaderIO Kleisli arrow (T -> ReaderIO[R, T])
func BindReaderIOKL[E, R, S, T any](
lens L.Lens[S, T],
f readerio.Kleisli[R, T, T],
) Operator[R, E, S, S] {
return BindL(lens, F.Flow2(f, FromReaderIO[E, R, T]))
}
// ApIOEitherS is an applicative variant that works with IOEither values.
// Unlike BindIOEitherK, this uses applicative composition (ApS) instead of monadic
// composition (Bind), allowing independent computations to be combined.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An IOEither value
func ApIOEitherS[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
fa IOEither[E, T],
) Operator[R, E, S1, S2] {
return F.Bind2nd(F.Flow2[ReaderIOEither[R, E, S1], ioeither.Operator[E, S1, S2]], ioeither.ApS(setter, fa))
}
// ApIOS is an applicative variant that works with IO values.
// It lifts an IO value into the ReaderIOEither context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An IO value
func ApIOS[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
fa IO[T],
) Operator[R, E, S1, S2] {
return ApS(setter, FromIO[R, E](fa))
}
// ApReaderS is an applicative variant that works with Reader values.
// It lifts a Reader value into the ReaderIOEither context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: A Reader value
func ApReaderS[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
fa Reader[R, T],
) Operator[R, E, S1, S2] {
return ApS(setter, FromReader[E, R, T](fa))
}
// ApReaderIOS is an applicative variant that works with ReaderIO values.
// It lifts a ReaderIO value into the ReaderIOEither context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: A ReaderIO value
func ApReaderIOS[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
fa ReaderIO[R, T],
) Operator[R, E, S1, S2] {
return ApS(setter, FromReaderIO[E, R, T](fa))
}
// ApEitherS is an applicative variant that works with Either values.
// It lifts an Either value into the ReaderIOEither context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An Either value
func ApEitherS[R, E, S1, S2, T any](
setter func(T) func(S1) S2,
fa Either[E, T],
) Operator[R, E, S1, S2] {
return ApS(setter, FromEither[R, E, T](fa))
}
// ApIOEitherSL is a lens-based variant of ApIOEitherS.
// It combines a lens with an IOEither value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An IOEither value
func ApIOEitherSL[R, E, S, T any](
lens L.Lens[S, T],
fa IOEither[E, T],
) Operator[R, E, S, S] {
return F.Bind2nd(F.Flow2[ReaderIOEither[R, E, S], ioeither.Operator[E, S, S]], ioeither.ApSL(lens, fa))
}
// ApIOSL is a lens-based variant of ApIOS.
// It combines a lens with an IO value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An IO value
func ApIOSL[R, E, S, T any](
lens L.Lens[S, T],
fa IO[T],
) Operator[R, E, S, S] {
return ApSL(lens, FromIO[R, E](fa))
}
// ApReaderSL is a lens-based variant of ApReaderS.
// It combines a lens with a Reader value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: A Reader value
func ApReaderSL[R, E, S, T any](
lens L.Lens[S, T],
fa Reader[R, T],
) Operator[R, E, S, S] {
return ApSL(lens, FromReader[E, R, T](fa))
}
// ApReaderIOSL is a lens-based variant of ApReaderIOS.
// It combines a lens with a ReaderIO value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: A ReaderIO value
func ApReaderIOSL[R, E, S, T any](
lens L.Lens[S, T],
fa ReaderIO[R, T],
) Operator[R, E, S, S] {
return ApSL(lens, FromReaderIO[E, R, T](fa))
}
// ApEitherSL is a lens-based variant of ApEitherS.
// It combines a lens with an Either value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An Either value
func ApEitherSL[R, E, S, T any](
lens L.Lens[S, T],
fa Either[E, T],
) Operator[R, E, S, S] {
return ApSL(lens, FromEither[R, E, T](fa))
}

View File

@@ -34,26 +34,14 @@ import (
"github.com/IBM/fp-go/v2/readerio"
)
// MonadFromReaderIO creates a ReaderIOEither from a value and a function that produces a ReaderIO.
// The ReaderIO result is lifted into the Right side of the Either.
func MonadFromReaderIO[R, E, A any](a A, f func(A) ReaderIO[R, A]) ReaderIOEither[R, E, A] {
return function.Pipe2(
a,
f,
RightReaderIO[R, E, A],
)
}
// FromReaderIO creates a function that lifts a ReaderIO-producing function into ReaderIOEither.
// The ReaderIO result is placed in the Right side of the Either.
func FromReaderIO[R, E, A any](f func(A) ReaderIO[R, A]) func(A) ReaderIOEither[R, E, A] {
return function.Bind2nd(MonadFromReaderIO[R, E, A], f)
func FromReaderIO[E, R, A any](ma ReaderIO[R, A]) ReaderIOEither[R, E, A] {
return RightReaderIO[E](ma)
}
// RightReaderIO lifts a ReaderIO into a ReaderIOEither, placing the result in the Right side.
//
//go:inline
func RightReaderIO[R, E, A any](ma ReaderIO[R, A]) ReaderIOEither[R, E, A] {
func RightReaderIO[E, R, A any](ma ReaderIO[R, A]) ReaderIOEither[R, E, A] {
return eithert.RightF(
readerio.MonadMap[R, A, either.Either[E, A]],
ma,

View File

@@ -611,35 +611,12 @@ func TestLocal(t *testing.T) {
assert.Equal(t, E.Right[error](40), result(ctx2)())
}
func TestMonadFromReaderIO(t *testing.T) {
ctx := testContext{value: 10}
result := MonadFromReaderIO[testContext, error](
5,
func(x int) RIO.ReaderIO[testContext, int] {
return func(c testContext) io.IO[int] {
return func() int { return x + c.value }
}
},
)
assert.Equal(t, E.Right[error](15), result(ctx)())
}
func TestFromReaderIO(t *testing.T) {
ctx := testContext{value: 10}
result := FromReaderIO[testContext, error](func(x int) RIO.ReaderIO[testContext, int] {
return func(c testContext) io.IO[int] {
return func() int { return x + c.value }
}
})(5)
assert.Equal(t, E.Right[error](15), result(ctx)())
}
func TestRightReaderIO(t *testing.T) {
ctx := testContext{value: 10}
rio := func(c testContext) io.IO[int] {
return func() int { return c.value * 2 }
}
result := RightReaderIO[testContext, error](rio)
result := RightReaderIO[error, testContext](rio)
assert.Equal(t, E.Right[error](20), result(ctx)())
}

View File

@@ -17,6 +17,7 @@ package readerioeither
import (
"github.com/IBM/fp-go/v2/either"
"github.com/IBM/fp-go/v2/io"
"github.com/IBM/fp-go/v2/ioeither"
"github.com/IBM/fp-go/v2/reader"
"github.com/IBM/fp-go/v2/readerio"
@@ -31,6 +32,8 @@ type (
// and produces a value of type A. It's useful for dependency injection patterns.
Reader[R, A any] = reader.Reader[R, A]
IO[T any] = io.IO[T]
// ReaderIO represents a computation that depends on some context R and performs
// side effects to produce a value of type A.
ReaderIO[R, A any] = readerio.ReaderIO[R, A]

View File

@@ -16,8 +16,15 @@
package readerioresult
import (
F "github.com/IBM/fp-go/v2/function"
"github.com/IBM/fp-go/v2/io"
"github.com/IBM/fp-go/v2/ioeither"
"github.com/IBM/fp-go/v2/ioresult"
L "github.com/IBM/fp-go/v2/optics/lens"
"github.com/IBM/fp-go/v2/reader"
"github.com/IBM/fp-go/v2/readerio"
RIOE "github.com/IBM/fp-go/v2/readerioeither"
"github.com/IBM/fp-go/v2/result"
)
// Do creates an empty context of type [S] to be used with the [Bind] operation.
@@ -320,3 +327,517 @@ func LetToL[R, S, T any](
) Operator[R, S, S] {
return RIOE.LetToL[R, error](lens, b)
}
// BindIOEitherK is a variant of Bind that works with IOEither computations.
// It lifts an IOEither Kleisli arrow into the ReaderIOResult context, allowing you to
// compose IOEither operations within a do-notation chain.
//
// This is useful when you have an existing IOEither computation that doesn't need
// access to the Reader environment, and you want to integrate it into a ReaderIOResult pipeline.
//
// Parameters:
// - setter: A function that takes the result T and returns a function to update the state from S1 to S2
// - f: An IOEither Kleisli arrow that takes S1 and returns IOEither[error, T]
//
// Returns:
// - An Operator that can be used in a do-notation chain
//
// Example:
//
// type State struct {
// UserID int
// Data []byte
// }
//
// // An IOEither operation that reads a file
// readFile := func(s State) ioeither.IOEither[error, []byte] {
// return ioeither.TryCatch(func() ([]byte, error) {
// return os.ReadFile(fmt.Sprintf("user_%d.json", s.UserID))
// })
// }
//
// result := F.Pipe2(
// readerioresult.Do[Env, error](State{UserID: 123}),
// readerioresult.BindIOEitherK(
// func(data []byte) func(State) State {
// return func(s State) State { s.Data = data; return s }
// },
// readFile,
// ),
// )
func BindIOEitherK[R, S1, S2, T any](
setter func(T) func(S1) S2,
f ioresult.Kleisli[S1, T],
) Operator[R, S1, S2] {
return Bind(setter, F.Flow2(f, FromIOEither[R, T]))
}
func BindIOResultK[R, S1, S2, T any](
setter func(T) func(S1) S2,
f ioresult.Kleisli[S1, T],
) Operator[R, S1, S2] {
return Bind(setter, F.Flow2(f, FromIOResult[R, T]))
}
// BindIOK is a variant of Bind that works with IO computations.
// It lifts an IO Kleisli arrow into the ReaderIOResult context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: An IO Kleisli arrow (S1 -> IO[T])
//
// Example:
//
// getCurrentTime := func(s State) io.IO[time.Time] {
// return func() time.Time { return time.Now() }
// }
func BindIOK[R, S1, S2, T any](
setter func(T) func(S1) S2,
f io.Kleisli[S1, T],
) Operator[R, S1, S2] {
return Bind(setter, F.Flow2(f, FromIO[R, T]))
}
// BindReaderK is a variant of Bind that works with Reader computations.
// It lifts a Reader Kleisli arrow into the ReaderIOResult context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: A Reader Kleisli arrow (S1 -> Reader[R, T])
//
// Example:
//
// getConfig := func(s State) reader.Reader[Env, string] {
// return func(env Env) string { return env.ConfigValue }
// }
func BindReaderK[R, S1, S2, T any](
setter func(T) func(S1) S2,
f reader.Kleisli[R, S1, T],
) Operator[R, S1, S2] {
return Bind(setter, F.Flow2(f, FromReader[R, T]))
}
// BindReaderIOK is a variant of Bind that works with ReaderIO computations.
// It lifts a ReaderIO Kleisli arrow into the ReaderIOResult context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: A ReaderIO Kleisli arrow (S1 -> ReaderIO[R, T])
//
// Example:
//
// logState := func(s State) readerio.ReaderIO[Env, string] {
// return func(env Env) io.IO[string] {
// return func() string {
// env.Logger.Println(s)
// return "logged"
// }
// }
// }
func BindReaderIOK[R, S1, S2, T any](
setter func(T) func(S1) S2,
f readerio.Kleisli[R, S1, T],
) Operator[R, S1, S2] {
return Bind(setter, F.Flow2(f, FromReaderIO[R, T]))
}
// BindEitherK is a variant of Bind that works with Either (Result) computations.
// It lifts an Either Kleisli arrow into the ReaderIOResult context.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - f: An Either Kleisli arrow (S1 -> Either[error, T])
//
// Example:
//
// parseValue := func(s State) result.Result[int] {
// return result.TryCatch(func() (int, error) {
// return strconv.Atoi(s.StringValue)
// })
// }
func BindEitherK[R, S1, S2, T any](
setter func(T) func(S1) S2,
f result.Kleisli[S1, T],
) Operator[R, S1, S2] {
return Bind(setter, F.Flow2(f, FromEither[R, T]))
}
func BindResultK[R, S1, S2, T any](
setter func(T) func(S1) S2,
f result.Kleisli[S1, T],
) Operator[R, S1, S2] {
return Bind(setter, F.Flow2(f, FromResult[R, T]))
}
// BindIOEitherKL is a lens-based variant of BindIOEitherK.
// It combines a lens with an IOEither Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: An IOEither Kleisli arrow (T -> IOEither[error, T])
//
// Example:
//
// userLens := lens.MakeLens(
// func(s State) User { return s.User },
// func(s State, u User) State { s.User = u; return s },
// )
// updateUser := func(u User) ioeither.IOEither[error, User] {
// return ioeither.TryCatch(func() (User, error) {
// return saveUser(u)
// })
// }
// result := F.Pipe2(
// readerioresult.Do[Env](State{}),
// readerioresult.BindIOEitherKL(userLens, updateUser),
// )
func BindIOEitherKL[R, S, T any](
lens L.Lens[S, T],
f ioresult.Kleisli[T, T],
) Operator[R, S, S] {
return BindL(lens, F.Flow2(f, FromIOEither[R, T]))
}
// BindIOResultKL is a lens-based variant of BindIOResultK.
// It combines a lens with an IOResult Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: An IOResult Kleisli arrow (T -> IOResult[T])
func BindIOResultKL[R, S, T any](
lens L.Lens[S, T],
f ioresult.Kleisli[T, T],
) Operator[R, S, S] {
return BindL(lens, F.Flow2(f, FromIOEither[R, T]))
}
// BindIOKL is a lens-based variant of BindIOK.
// It combines a lens with an IO Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: An IO Kleisli arrow (T -> IO[T])
//
// Example:
//
// timestampLens := lens.MakeLens(
// func(s State) time.Time { return s.Timestamp },
// func(s State, t time.Time) State { s.Timestamp = t; return s },
// )
// updateTimestamp := func(t time.Time) io.IO[time.Time] {
// return func() time.Time { return time.Now() }
// }
func BindIOKL[R, S, T any](
lens L.Lens[S, T],
f io.Kleisli[T, T],
) Operator[R, S, S] {
return BindL(lens, F.Flow2(f, FromIO[R, T]))
}
// BindReaderKL is a lens-based variant of BindReaderK.
// It combines a lens with a Reader Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: A Reader Kleisli arrow (T -> Reader[R, T])
//
// Example:
//
// configLens := lens.MakeLens(
// func(s State) string { return s.Config },
// func(s State, c string) State { s.Config = c; return s },
// )
// getConfigFromEnv := func(c string) reader.Reader[Env, string] {
// return func(env Env) string { return env.ConfigValue }
// }
func BindReaderKL[R, S, T any](
lens L.Lens[S, T],
f reader.Kleisli[R, T, T],
) Operator[R, S, S] {
return BindL(lens, F.Flow2(f, FromReader[R, T]))
}
// BindReaderIOKL is a lens-based variant of BindReaderIOK.
// It combines a lens with a ReaderIO Kleisli arrow, focusing on a specific field
// within the state structure.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - f: A ReaderIO Kleisli arrow (T -> ReaderIO[R, T])
//
// Example:
//
// logLens := lens.MakeLens(
// func(s State) string { return s.LogMessage },
// func(s State, l string) State { s.LogMessage = l; return s },
// )
// logMessage := func(msg string) readerio.ReaderIO[Env, string] {
// return func(env Env) io.IO[string] {
// return func() string {
// env.Logger.Println(msg)
// return "logged: " + msg
// }
// }
// }
func BindReaderIOKL[R, S, T any](
lens L.Lens[S, T],
f readerio.Kleisli[R, T, T],
) Operator[R, S, S] {
return BindL(lens, F.Flow2(f, FromReaderIO[R, T]))
}
// ApIOEitherS is an applicative variant that works with IOEither values.
// Unlike BindIOEitherK, this uses applicative composition (ApS) instead of monadic
// composition (Bind), allowing independent computations to be combined.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An IOEither value (not a Kleisli arrow)
//
// Example:
//
// readConfig := ioeither.TryCatch(func() (Config, error) {
// return loadConfig()
// })
func ApIOEitherS[R, S1, S2, T any](
setter func(T) func(S1) S2,
fa IOResult[T],
) Operator[R, S1, S2] {
return F.Bind2nd(F.Flow2[ReaderIOResult[R, S1], ioresult.Operator[S1, S2]], ioeither.ApS(setter, fa))
}
// ApIOResultS is an applicative variant that works with IOResult values.
// This is an alias for ApIOEitherS for consistency with the Result naming convention.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An IOResult value
func ApIOResultS[R, S1, S2, T any](
setter func(T) func(S1) S2,
fa IOResult[T],
) Operator[R, S1, S2] {
return F.Bind2nd(F.Flow2[ReaderIOResult[R, S1], ioresult.Operator[S1, S2]], ioeither.ApS(setter, fa))
}
// ApIOS is an applicative variant that works with IO values.
// It lifts an IO value into the ReaderIOResult context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An IO value
//
// Example:
//
// getCurrentTime := func() time.Time { return time.Now() }
func ApIOS[R, S1, S2, T any](
setter func(T) func(S1) S2,
fa IO[T],
) Operator[R, S1, S2] {
return ApS(setter, FromIO[R](fa))
}
// ApReaderS is an applicative variant that works with Reader values.
// It lifts a Reader value into the ReaderIOResult context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: A Reader value
//
// Example:
//
// getEnvConfig := func(env Env) string { return env.ConfigValue }
func ApReaderS[R, S1, S2, T any](
setter func(T) func(S1) S2,
fa Reader[R, T],
) Operator[R, S1, S2] {
return ApS(setter, FromReader[R, T](fa))
}
// ApReaderIOS is an applicative variant that works with ReaderIO values.
// It lifts a ReaderIO value into the ReaderIOResult context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: A ReaderIO value
func ApReaderIOS[R, S1, S2, T any](
setter func(T) func(S1) S2,
fa ReaderIO[R, T],
) Operator[R, S1, S2] {
return ApS(setter, FromReaderIO[R, T](fa))
}
// ApEitherS is an applicative variant that works with Either (Result) values.
// It lifts an Either value into the ReaderIOResult context using applicative composition.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: An Either value
//
// Example:
//
// parseResult := result.TryCatch(func() (int, error) {
// return strconv.Atoi("123")
// })
func ApEitherS[R, S1, S2, T any](
setter func(T) func(S1) S2,
fa Result[T],
) Operator[R, S1, S2] {
return ApS(setter, FromEither[R, T](fa))
}
// ApResultS is an applicative variant that works with Result values.
// This is an alias for ApEitherS for consistency with the Result naming convention.
//
// Parameters:
// - setter: Updates state from S1 to S2 using result T
// - fa: A Result value
func ApResultS[R, S1, S2, T any](
setter func(T) func(S1) S2,
fa Result[T],
) Operator[R, S1, S2] {
return ApS(setter, FromResult[R, T](fa))
}
// ApIOEitherSL is a lens-based variant of ApIOEitherS.
// It combines a lens with an IOEither value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An IOEither value
//
// Example:
//
// userLens := lens.MakeLens(
// func(s State) User { return s.User },
// func(s State, u User) State { s.User = u; return s },
// )
// loadUser := ioeither.TryCatch(func() (User, error) {
// return fetchUser()
// })
func ApIOEitherSL[R, S, T any](
lens L.Lens[S, T],
fa IOResult[T],
) Operator[R, S, S] {
return F.Bind2nd(F.Flow2[ReaderIOResult[R, S], ioresult.Operator[S, S]], ioresult.ApSL(lens, fa))
}
// ApIOResultSL is a lens-based variant of ApIOResultS.
// This is an alias for ApIOEitherSL for consistency with the Result naming convention.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An IOResult value
func ApIOResultSL[R, S, T any](
lens L.Lens[S, T],
fa IOResult[T],
) Operator[R, S, S] {
return F.Bind2nd(F.Flow2[ReaderIOResult[R, S], ioresult.Operator[S, S]], ioresult.ApSL(lens, fa))
}
// ApIOSL is a lens-based variant of ApIOS.
// It combines a lens with an IO value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An IO value
//
// Example:
//
// timestampLens := lens.MakeLens(
// func(s State) time.Time { return s.Timestamp },
// func(s State, t time.Time) State { s.Timestamp = t; return s },
// )
// getCurrentTime := func() time.Time { return time.Now() }
func ApIOSL[R, S, T any](
lens L.Lens[S, T],
fa IO[T],
) Operator[R, S, S] {
return ApSL(lens, FromIO[R](fa))
}
// ApReaderSL is a lens-based variant of ApReaderS.
// It combines a lens with a Reader value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: A Reader value
//
// Example:
//
// configLens := lens.MakeLens(
// func(s State) string { return s.Config },
// func(s State, c string) State { s.Config = c; return s },
// )
// getConfig := func(env Env) string { return env.ConfigValue }
func ApReaderSL[R, S, T any](
lens L.Lens[S, T],
fa Reader[R, T],
) Operator[R, S, S] {
return ApSL(lens, FromReader[R, T](fa))
}
// ApReaderIOSL is a lens-based variant of ApReaderIOS.
// It combines a lens with a ReaderIO value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: A ReaderIO value
//
// Example:
//
// logLens := lens.MakeLens(
// func(s State) string { return s.LogMessage },
// func(s State, l string) State { s.LogMessage = l; return s },
// )
// logWithEnv := func(env Env) io.IO[string] {
// return func() string {
// env.Logger.Println("Processing")
// return "logged"
// }
// }
func ApReaderIOSL[R, S, T any](
lens L.Lens[S, T],
fa ReaderIO[R, T],
) Operator[R, S, S] {
return ApSL(lens, FromReaderIO[R, T](fa))
}
// ApEitherSL is a lens-based variant of ApEitherS.
// It combines a lens with an Either value using applicative composition.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: An Either value
//
// Example:
//
// valueLens := lens.MakeLens(
// func(s State) int { return s.Value },
// func(s State, v int) State { s.Value = v; return s },
// )
// parseValue := result.TryCatch(func() (int, error) {
// return strconv.Atoi("123")
// })
func ApEitherSL[R, S, T any](
lens L.Lens[S, T],
fa Result[T],
) Operator[R, S, S] {
return ApSL(lens, FromEither[R, T](fa))
}
// ApResultSL is a lens-based variant of ApResultS.
// This is an alias for ApEitherSL for consistency with the Result naming convention.
//
// Parameters:
// - lens: A lens focusing on field T within state S
// - fa: A Result value
func ApResultSL[R, S, T any](
lens L.Lens[S, T],
fa Result[T],
) Operator[R, S, S] {
return ApSL(lens, FromResult[R, T](fa))
}

View File

@@ -56,3 +56,5 @@ func TestApS(t *testing.T) {
assert.Equal(t, res(context.Background())(), result.Of("John Doe"))
}
// Made with Bob

View File

@@ -20,23 +20,17 @@ import (
RIOE "github.com/IBM/fp-go/v2/readerioeither"
)
// MonadFromReaderIO creates a ReaderIOResult from a value and a function that produces a ReaderIO.
// The ReaderIO result is lifted into the Right side of the Either.
func MonadFromReaderIO[R, A any](a A, f func(A) ReaderIO[R, A]) ReaderIOResult[R, A] {
return RIOE.MonadFromReaderIO[R, error](a, f)
}
// FromReaderIO creates a function that lifts a ReaderIO-producing function into ReaderIOResult.
// The ReaderIO result is placed in the Right side of the Either.
func FromReaderIO[R, A any](f func(A) ReaderIO[R, A]) Kleisli[R, A, A] {
return RIOE.FromReaderIO[R, error](f)
func FromReaderIO[R, A any](ma ReaderIO[R, A]) ReaderIOResult[R, A] {
return RIOE.FromReaderIO[error, R](ma)
}
// RightReaderIO lifts a ReaderIO into a ReaderIOResult, placing the result in the Right side.
//
//go:inline
func RightReaderIO[R, A any](ma ReaderIO[R, A]) ReaderIOResult[R, A] {
return RIOE.RightReaderIO[R, error](ma)
return RIOE.RightReaderIO[error, R](ma)
}
// LeftReaderIO lifts a ReaderIO into a ReaderIOResult, placing the result in the Left (error) side.

View File

@@ -573,29 +573,6 @@ func TestLocal(t *testing.T) {
assert.Equal(t, result.Of(40), res(ctx2)())
}
func TestMonadFromReaderIO(t *testing.T) {
ctx := testContext{value: 10}
res := MonadFromReaderIO(
5,
func(x int) RIO.ReaderIO[testContext, int] {
return func(c testContext) IO[int] {
return func() int { return x + c.value }
}
},
)
assert.Equal(t, result.Of(15), res(ctx)())
}
func TestFromReaderIO(t *testing.T) {
ctx := testContext{value: 10}
res := FromReaderIO(func(x int) RIO.ReaderIO[testContext, int] {
return func(c testContext) IO[int] {
return func() int { return x + c.value }
}
})(5)
assert.Equal(t, result.Of(15), res(ctx)())
}
func TestRightReaderIO(t *testing.T) {
ctx := testContext{value: 10}
rio := func(c testContext) IO[int] {