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:
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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]
|
||||
)
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)())
|
||||
}
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -56,3 +56,5 @@ func TestApS(t *testing.T) {
|
||||
|
||||
assert.Equal(t, res(context.Background())(), result.Of("John Doe"))
|
||||
}
|
||||
|
||||
// Made with Bob
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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] {
|
||||
|
||||
Reference in New Issue
Block a user