Documentation
¶
Overview ¶
Package readerreaderioeither provides a functional programming abstraction that combines four powerful concepts: Reader, Reader, IO, and Either monads in a nested structure.
Type Parameter Ordering Convention ¶
This package follows a consistent convention for ordering type parameters in function signatures. The general rule is: R -> C -> E -> T (outer context, inner context, error, type), where:
- R: The outer Reader context/environment type
- C: The inner Reader context/environment type (for the ReaderIOEither)
- E: The Either error type
- T: The value type(s) (A, B, etc.)
However, when some type parameters can be automatically inferred by the Go compiler from function arguments, the convention is modified to minimize explicit type annotations:
Rule: Undetectable types come first, followed by detectable types, while preserving the relative order within each group (R -> C -> E -> T).
Examples:
All types detectable from first argument: MonadMap[R, C, E, A, B](fa ReaderReaderIOEither[R, C, E, A], f func(A) B) - R, C, E, A are detectable from fa - B is detectable from f - Order: R, C, E, A, B (standard order, all detectable)
Some types undetectable: FromReader[C, E, R, A](ma Reader[R, A]) ReaderReaderIOEither[R, C, E, A] - R, A are detectable from ma - C, E are undetectable (not in any argument) - Order: C, E, R, A (C, E first as undetectable, then R, A in standard order)
Multiple undetectable types: Local[C, E, A, R1, R2](f func(R2) R1) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A] - C, E, A are undetectable - R1, R2 are detectable from f - Order: C, E, A, R1, R2 (undetectable first, then detectable)
Functions returning Kleisli arrows: ChainReaderOptionK[R, C, A, B, E](onNone Lazy[E]) func(readeroption.Kleisli[R, A, B]) Operator[R, C, E, A, B] - Canonical order would be R, C, E, A, B - E is detectable from onNone parameter - R, C, A, B are not detectable (they're in the Kleisli argument type) - Order: R, C, A, B, E (undetectable R, C, A, B first, then detectable E)
This convention allows for more ergonomic function calls:
// Without convention - need to specify all types: result := FromReader[OuterCtx, InnerCtx, error, User](readerFunc) // With convention - only specify undetectable types: result := FromReader[InnerCtx, error](readerFunc) // R and A inferred from readerFunc
The reasoning behind this approach is to reduce the number of explicit type parameters that developers need to specify when calling functions, improving code readability and reducing verbosity while maintaining type safety.
Additional examples demonstrating the convention:
FromReaderOption[R, C, A, E](onNone Lazy[E]) Kleisli[R, C, E, ReaderOption[R, A], A] - Canonical order would be R, C, E, A - E is detectable from onNone parameter - R, C, A are not detectable (they're in the return type's Kleisli) - Order: R, C, A, E (undetectable R, C, A first, then detectable E)
MapLeft[R, C, A, E1, E2](f func(E1) E2) func(ReaderReaderIOEither[R, C, E1, A]) ReaderReaderIOEither[R, C, E2, A] - Canonical order would be R, C, E1, E2, A - E1, E2 are detectable from f parameter - R, C, A are not detectable (they're in the return type) - Order: R, C, A, E1, E2 (undetectable R, C, A first, then detectable E1, E2)
Additional special cases:
- Ap[B, R, C, E, A]: B is undetectable (in function return type), so B comes first
- ChainOptionK[R, C, A, B, E]: R, C, A, B are undetectable, E is detectable from onNone
- FromReaderIO[C, E, R, A]: C, E are undetectable, R, A are detectable from ReaderIO[R, A]
All functions in this package follow this convention consistently.
Fantasy Land Specification ¶
This is a monad transformer combining:
- Reader monad: https://github.com/fantasyland/fantasy-land
- Reader monad (nested): https://github.com/fantasyland/fantasy-land
- IO monad: https://github.com/fantasyland/fantasy-land
- Either monad: https://github.com/fantasyland/fantasy-land#either
Implemented Fantasy Land algebras:
- Functor: https://github.com/fantasyland/fantasy-land#functor
- Bifunctor: https://github.com/fantasyland/fantasy-land#bifunctor
- Apply: https://github.com/fantasyland/fantasy-land#apply
- Applicative: https://github.com/fantasyland/fantasy-land#applicative
- Chain: https://github.com/fantasyland/fantasy-land#chain
- Monad: https://github.com/fantasyland/fantasy-land#monad
- Alt: https://github.com/fantasyland/fantasy-land#alt
ReaderReaderIOEither ¶
ReaderReaderIOEither[R, C, E, A] represents a computation that:
- Depends on an outer context/environment of type R (outer Reader)
- Returns a computation that depends on an inner context/environment of type C (inner Reader)
- Performs side effects (IO)
- Can fail with an error of type E or succeed with a value of type A (Either)
This is particularly useful for:
- Multi-level dependency injection patterns
- Layered architectures with different context requirements at each layer
- Composing operations that need access to multiple levels of configuration or context
- Building reusable components that can be configured at different stages
Core Operations ¶
Construction:
- Of/Right: Create a successful computation
- Left: Create a failed computation
- FromEither: Lift an Either into ReaderReaderIOEither
- FromIO: Lift an IO into ReaderReaderIOEither
- FromReader: Lift a Reader into ReaderReaderIOEither
- FromReaderIO: Lift a ReaderIO into ReaderReaderIOEither
- FromIOEither: Lift an IOEither into ReaderReaderIOEither
- FromReaderEither: Lift a ReaderEither into ReaderReaderIOEither
- FromReaderIOEither: Lift a ReaderIOEither into ReaderReaderIOEither
- FromReaderOption: Lift a ReaderOption into ReaderReaderIOEither
Transformation:
- Map: Transform the success value
- MapLeft: Transform the error value
- Chain/Bind: Sequence dependent computations
- Flatten: Flatten nested ReaderReaderIOEither
Combination:
- Ap: Apply a function in a context to a value in a context
- ApSeq: Sequential application
- ApPar: Parallel application
Error Handling:
- Alt: Choose the first successful computation
Context Access:
- Ask: Get the current outer context
- Asks: Get a value derived from the outer context
- Local: Run a computation with a modified outer context
- Read: Execute with a specific outer context
Kleisli Composition:
- ChainEitherK: Chain with Either-returning functions
- ChainReaderK: Chain with Reader-returning functions
- ChainReaderIOK: Chain with ReaderIO-returning functions
- ChainReaderEitherK: Chain with ReaderEither-returning functions
- ChainReaderOptionK: Chain with ReaderOption-returning functions
- ChainIOEitherK: Chain with IOEither-returning functions
- ChainIOK: Chain with IO-returning functions
- ChainOptionK: Chain with Option-returning functions
First/Tap Operations (execute for side effects, return original value):
- ChainFirst/Tap: Execute a computation but return the original value
- ChainFirstEitherK/TapEitherK: Tap with Either-returning functions
- ChainFirstReaderK/TapReaderK: Tap with Reader-returning functions
- ChainFirstReaderIOK/TapReaderIOK: Tap with ReaderIO-returning functions
- ChainFirstReaderEitherK/TapReaderEitherK: Tap with ReaderEither-returning functions
- ChainFirstReaderOptionK/TapReaderOptionK: Tap with ReaderOption-returning functions
- ChainFirstIOK/TapIOK: Tap with IO-returning functions
Example Usage ¶
type OuterConfig struct {
DatabaseURL string
LogLevel string
}
type InnerConfig struct {
APIKey string
Timeout time.Duration
}
// A computation that depends on both OuterConfig and InnerConfig
func fetchUser(id int) readerreaderioeither.ReaderReaderIOEither[OuterConfig, InnerConfig, error, User] {
return func(outerCfg OuterConfig) readerioeither.ReaderIOEither[InnerConfig, error, User] {
// Use outerCfg.DatabaseURL and outerCfg.LogLevel
return func(innerCfg InnerConfig) ioeither.IOEither[error, User] {
// Use innerCfg.APIKey and innerCfg.Timeout to fetch user
return func() either.Either[error, User] {
// Perform the actual IO operation
// Return either.Right(user) or either.Left(err)
}
}
}
}
// Compose operations
result := function.Pipe2(
fetchUser(123),
readerreaderioeither.Map[OuterConfig, InnerConfig, error](func(u User) string { return u.Name }),
readerreaderioeither.Chain[OuterConfig, InnerConfig, error](func(name string) readerreaderioeither.ReaderReaderIOEither[OuterConfig, InnerConfig, error, string] {
return readerreaderioeither.Of[OuterConfig, InnerConfig, error]("Hello, " + name)
}),
)
// Execute with both configs
outerConfig := OuterConfig{DatabaseURL: "postgres://...", LogLevel: "info"}
innerConfig := InnerConfig{APIKey: "secret", Timeout: 30 * time.Second}
outcome := result(outerConfig)(innerConfig)() // Returns either.Either[error, string]
Copyright (c) 2025 IBM Corp. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Index ¶
- func ChainFirstReaderOptionK[R, C, A, B, E any](onNone Lazy[E]) func(readeroption.Kleisli[R, A, B]) Operator[R, C, E, A, A]
- func ChainLeft[R, C, EA, EB, A any](f Kleisli[R, C, EB, EA, A]) func(ReaderReaderIOEither[R, C, EA, A]) ReaderReaderIOEither[R, C, EB, A]
- func ChainOptionK[R, C, A, B, E any](onNone Lazy[E]) func(option.Kleisli[A, B]) Operator[R, C, E, A, B]
- func ChainReaderOptionK[R, C, A, B, E any](onNone Lazy[E]) func(readeroption.Kleisli[R, A, B]) Operator[R, C, E, A, B]
- func FromOption[R, C, A, E any](onNone Lazy[E]) func(Option[A]) ReaderReaderIOEither[R, C, E, A]
- func FromPredicate[R, C, E, A any](pred func(A) bool, onFalse func(A) E) func(A) ReaderReaderIOEither[R, C, E, A]
- func Local[C, E, A, R1, R2 any](f func(R2) R1) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
- func MapLeft[R, C, A, E1, E2 any](f func(E1) E2) func(ReaderReaderIOEither[R, C, E1, A]) ReaderReaderIOEither[R, C, E2, A]
- func Read[C, E, A, R any](r R) func(ReaderReaderIOEither[R, C, E, A]) ReaderIOEither[C, E, A]
- func ReadIO[C, E, A, R any](rio IO[R]) func(ReaderReaderIOEither[R, C, E, A]) ReaderIOEither[C, E, A]
- func ReadIOEither[A, R, C, E any](rio IOEither[E, R]) func(ReaderReaderIOEither[R, C, E, A]) ReaderIOEither[C, E, A]
- func TapReaderOptionK[R, C, A, B, E any](onNone Lazy[E]) func(readeroption.Kleisli[R, A, B]) Operator[R, C, E, A, A]
- func Traverse[R2, R1, C, E, A, B any](f Kleisli[R1, C, E, A, B]) func(ReaderReaderIOEither[R2, C, E, A]) Kleisli[R2, C, E, R1, B]
- func TraverseReader[R2, R1, C, E, A, B any](f reader.Kleisli[R1, A, B]) func(ReaderReaderIOEither[R2, C, E, A]) Kleisli[R2, C, E, R1, B]
- type Either
- type IO
- type IOEither
- type Kleisli
- func FromReaderOption[R, C, A, E any](onNone Lazy[E]) Kleisli[R, C, E, ReaderOption[R, A], A]
- func Sequence[R1, R2, C, E, A any](ma ReaderReaderIOEither[R2, C, E, ReaderReaderIOEither[R1, C, E, A]]) Kleisli[R2, C, E, R1, A]
- func SequenceReader[R1, R2, C, E, A any](ma ReaderReaderIOEither[R2, C, E, Reader[R1, A]]) Kleisli[R2, C, E, R1, A]
- func SequenceReaderIO[R1, R2, C, E, A any](ma ReaderReaderIOEither[R2, C, E, ReaderIO[R1, A]]) Kleisli[R2, C, E, R1, A]
- type Lazy
- type Lens
- type Monoid
- func AltMonoid[R, C, E, A any](zero Lazy[ReaderReaderIOEither[R, C, E, A]]) Monoid[R, C, E, A]
- func AlternativeMonoid[R, C, E, A any](m monoid.Monoid[A]) Monoid[R, C, E, A]
- func ApplicativeMonoid[R, C, E, A any](m monoid.Monoid[A]) Monoid[R, C, E, A]
- func ApplicativeMonoidPar[R, C, E, A any](m monoid.Monoid[A]) Monoid[R, C, E, A]
- func ApplicativeMonoidSeq[R, C, E, A any](m monoid.Monoid[A]) Monoid[R, C, E, A]
- type Operator
- func After[R, C, E, A any](timestamp time.Time) Operator[R, C, E, A, A]
- func Alt[R, C, E, A any](second Lazy[ReaderReaderIOEither[R, C, E, A]]) Operator[R, C, E, A, A]
- func Ap[B, R, C, E, A any](fa ReaderReaderIOEither[R, C, E, A]) Operator[R, C, E, func(A) B, B]
- func ApEitherS[R, C, E, S1, S2, T any](setter func(T) func(S1) S2, fa Either[E, T]) Operator[R, C, E, S1, S2]
- func ApEitherSL[R, C, E, S, T any](lens Lens[S, T], fa Either[E, T]) Operator[R, C, E, S, S]
- func ApIOEitherS[R, C, E, S1, S2, T any](setter func(T) func(S1) S2, fa IOEither[E, T]) Operator[R, C, E, S1, S2]
- func ApIOEitherSL[R, C, E, S, T any](lens Lens[S, T], fa IOEither[E, T]) Operator[R, C, E, S, S]
- func ApIOS[R, C, E, S1, S2, T any](setter func(T) func(S1) S2, fa IO[T]) Operator[R, C, E, S1, S2]
- func ApIOSL[R, C, E, S, T any](lens Lens[S, T], fa IO[T]) Operator[R, C, E, S, S]
- func ApReaderIOS[C, E, R, S1, S2, T any](setter func(T) func(S1) S2, fa ReaderIO[R, T]) Operator[R, C, E, S1, S2]
- func ApReaderIOSL[C, E, R, S, T any](lens Lens[S, T], fa ReaderIO[R, T]) Operator[R, C, E, S, S]
- func ApReaderS[C, E, R, S1, S2, T any](setter func(T) func(S1) S2, fa Reader[R, T]) Operator[R, C, E, S1, S2]
- func ApReaderSL[C, E, R, S, T any](lens Lens[S, T], fa Reader[R, T]) Operator[R, C, E, S, S]
- func ApS[R, C, E, S1, S2, T any](setter func(T) func(S1) S2, fa ReaderReaderIOEither[R, C, E, T]) Operator[R, C, E, S1, S2]
- func ApSL[R, C, E, S, T any](lens Lens[S, T], fa ReaderReaderIOEither[R, C, E, T]) Operator[R, C, E, S, S]
- func Bind[R, C, E, S1, S2, T any](setter func(T) func(S1) S2, f func(S1) ReaderReaderIOEither[R, C, E, T]) Operator[R, C, E, S1, S2]
- func BindEitherK[R, C, E, S1, S2, T any](setter func(T) func(S1) S2, f either.Kleisli[E, S1, T]) Operator[R, C, E, S1, S2]
- func BindIOEitherK[R, C, E, S1, S2, T any](setter func(T) func(S1) S2, f ioeither.Kleisli[E, S1, T]) Operator[R, C, E, S1, S2]
- func BindIOEitherKL[R, C, E, S, T any](lens Lens[S, T], f ioeither.Kleisli[E, T, T]) Operator[R, C, E, S, S]
- func BindIOK[R, C, E, S1, S2, T any](setter func(T) func(S1) S2, f io.Kleisli[S1, T]) Operator[R, C, E, S1, S2]
- func BindIOKL[R, C, E, S, T any](lens Lens[S, T], f io.Kleisli[T, T]) Operator[R, C, E, S, S]
- func BindL[R, C, E, S, T any](lens Lens[S, T], f func(T) ReaderReaderIOEither[R, C, E, T]) Operator[R, C, E, S, S]
- func BindReaderIOK[C, E, R, S1, S2, T any](setter func(T) func(S1) S2, f readerio.Kleisli[R, S1, T]) Operator[R, C, E, S1, S2]
- func BindReaderIOKL[C, E, R, S, T any](lens Lens[S, T], f readerio.Kleisli[R, T, T]) Operator[R, C, E, S, S]
- func BindReaderK[C, E, R, S1, S2, T any](setter func(T) func(S1) S2, f reader.Kleisli[R, S1, T]) Operator[R, C, E, S1, S2]
- func BindReaderKL[C, E, R, S, T any](lens Lens[S, T], f reader.Kleisli[R, T, T]) Operator[R, C, E, S, S]
- func BindTo[R, C, E, S1, T any](setter func(T) S1) Operator[R, C, E, T, S1]
- func Chain[R, C, E, A, B any](f Kleisli[R, C, E, A, B]) Operator[R, C, E, A, B]
- func ChainEitherK[R, C, E, A, B any](f either.Kleisli[E, A, B]) Operator[R, C, E, A, B]
- func ChainFirst[R, C, E, A, B any](f Kleisli[R, C, E, A, B]) Operator[R, C, E, A, A]
- func ChainFirstEitherK[R, C, E, A, B any](f either.Kleisli[E, A, B]) Operator[R, C, E, A, A]
- func ChainFirstIOK[R, C, E, A, B any](f io.Kleisli[A, B]) Operator[R, C, E, A, A]
- func ChainFirstReaderEitherK[C, E, R, A, B any](f RE.Kleisli[R, E, A, B]) Operator[R, C, E, A, A]
- func ChainFirstReaderIOK[C, E, R, A, B any](f readerio.Kleisli[R, A, B]) Operator[R, C, E, A, A]
- func ChainFirstReaderK[C, E, R, A, B any](f reader.Kleisli[R, A, B]) Operator[R, C, E, A, A]
- func ChainIOEitherK[R, C, E, A, B any](f IOE.Kleisli[E, A, B]) Operator[R, C, E, A, B]
- func ChainIOK[R, C, E, A, B any](f io.Kleisli[A, B]) Operator[R, C, E, A, B]
- func ChainReaderEitherK[C, E, R, A, B any](f RE.Kleisli[R, E, A, B]) Operator[R, C, E, A, B]
- func ChainReaderIOK[C, E, R, A, B any](f readerio.Kleisli[R, A, B]) Operator[R, C, E, A, B]
- func ChainReaderK[C, E, R, A, B any](f reader.Kleisli[R, A, B]) Operator[R, C, E, A, B]
- func Delay[R, C, E, A any](delay time.Duration) Operator[R, C, E, A, A]
- func Flap[R, C, E, B, A any](a A) Operator[R, C, E, func(A) B, B]
- func Let[R, C, E, S1, S2, T any](setter func(T) func(S1) S2, f func(S1) T) Operator[R, C, E, S1, S2]
- func LetL[R, C, E, S, T any](lens Lens[S, T], f func(T) T) Operator[R, C, E, S, S]
- func LetTo[R, C, E, S1, S2, T any](setter func(T) func(S1) S2, b T) Operator[R, C, E, S1, S2]
- func LetToL[R, C, E, S, T any](lens Lens[S, T], b T) Operator[R, C, E, S, S]
- func Map[R, C, E, A, B any](f func(A) B) Operator[R, C, E, A, B]
- func MapTo[R, C, E, A, B any](b B) Operator[R, C, E, A, B]
- func Tap[R, C, E, A, B any](f Kleisli[R, C, E, A, B]) Operator[R, C, E, A, A]
- func TapEitherK[R, C, E, A, B any](f either.Kleisli[E, A, B]) Operator[R, C, E, A, A]
- func TapIOK[R, C, E, A, B any](f io.Kleisli[A, B]) Operator[R, C, E, A, A]
- func TapReaderEitherK[C, E, R, A, B any](f RE.Kleisli[R, E, A, B]) Operator[R, C, E, A, A]
- func TapReaderIOK[C, E, R, A, B any](f readerio.Kleisli[R, A, B]) Operator[R, C, E, A, A]
- func TapReaderK[C, E, R, A, B any](f reader.Kleisli[R, A, B]) Operator[R, C, E, A, A]
- type Option
- type Predicate
- type Reader
- type ReaderEither
- type ReaderIO
- type ReaderIOEither
- type ReaderOption
- type ReaderReaderIOEither
- func Ask[R, C, E any]() ReaderReaderIOEither[R, C, E, R]
- func Asks[C, E, R, A any](r Reader[R, A]) ReaderReaderIOEither[R, C, E, A]
- func Bracket[R, C, E, A, B, ANY any](acquire ReaderReaderIOEither[R, C, E, A], ...) ReaderReaderIOEither[R, C, E, B]
- func Do[R, C, E, S any](empty S) ReaderReaderIOEither[R, C, E, S]
- func Flatten[R, C, E, A any](mma ReaderReaderIOEither[R, C, E, ReaderReaderIOEither[R, C, E, A]]) ReaderReaderIOEither[R, C, E, A]
- func FromEither[R, C, E, A any](t Either[E, A]) ReaderReaderIOEither[R, C, E, A]
- func FromIO[R, C, E, A any](ma IO[A]) ReaderReaderIOEither[R, C, E, A]
- func FromIOEither[R, C, E, A any](ma IOEither[E, A]) ReaderReaderIOEither[R, C, E, A]
- func FromReader[C, E, R, A any](ma Reader[R, A]) ReaderReaderIOEither[R, C, E, A]
- func FromReaderEither[R, C, E, A any](ma RE.ReaderEither[R, E, A]) ReaderReaderIOEither[R, C, E, A]
- func FromReaderIO[C, E, R, A any](ma ReaderIO[R, A]) ReaderReaderIOEither[R, C, E, A]
- func FromReaderIOEither[C, E, R, A any](ma ReaderIOEither[R, E, A]) ReaderReaderIOEither[R, C, E, A]
- func Left[R, C, A, E any](e E) ReaderReaderIOEither[R, C, E, A]
- func LeftIO[R, C, A, E any](ma IO[E]) ReaderReaderIOEither[R, C, E, A]
- func LeftReader[C, A, R, E any](ma Reader[R, E]) ReaderReaderIOEither[R, C, E, A]
- func LeftReaderIO[C, A, R, E any](me ReaderIO[R, E]) ReaderReaderIOEither[R, C, E, A]
- func MonadAlt[R, C, E, A any](first ReaderReaderIOEither[R, C, E, A], ...) ReaderReaderIOEither[R, C, E, A]
- func MonadAp[R, C, E, A, B any](fab ReaderReaderIOEither[R, C, E, func(A) B], ...) ReaderReaderIOEither[R, C, E, B]
- func MonadApPar[R, C, E, A, B any](fab ReaderReaderIOEither[R, C, E, func(A) B], ...) ReaderReaderIOEither[R, C, E, B]
- func MonadApSeq[R, C, E, A, B any](fab ReaderReaderIOEither[R, C, E, func(A) B], ...) ReaderReaderIOEither[R, C, E, B]
- func MonadChain[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], f Kleisli[R, C, E, A, B]) ReaderReaderIOEither[R, C, E, B]
- func MonadChainEitherK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f either.Kleisli[E, A, B]) ReaderReaderIOEither[R, C, E, B]
- func MonadChainFirst[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], f Kleisli[R, C, E, A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadChainFirstEitherK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f either.Kleisli[E, A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadChainFirstIOK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f io.Kleisli[A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadChainFirstReaderEitherK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f RE.Kleisli[R, E, A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadChainFirstReaderIOK[C, E, R, A, B any](ma ReaderReaderIOEither[R, C, E, A], f readerio.Kleisli[R, A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadChainFirstReaderK[C, E, R, A, B any](ma ReaderReaderIOEither[R, C, E, A], f reader.Kleisli[R, A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadChainIOEitherK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f IOE.Kleisli[E, A, B]) ReaderReaderIOEither[R, C, E, B]
- func MonadChainIOK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f io.Kleisli[A, B]) ReaderReaderIOEither[R, C, E, B]
- func MonadChainLeft[R, C, EA, EB, A any](fa ReaderReaderIOEither[R, C, EA, A], f Kleisli[R, C, EB, EA, A]) ReaderReaderIOEither[R, C, EB, A]
- func MonadChainReaderEitherK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f RE.Kleisli[R, E, A, B]) ReaderReaderIOEither[R, C, E, B]
- func MonadChainReaderIOK[C, E, R, A, B any](ma ReaderReaderIOEither[R, C, E, A], f readerio.Kleisli[R, A, B]) ReaderReaderIOEither[R, C, E, B]
- func MonadChainReaderK[C, E, R, A, B any](ma ReaderReaderIOEither[R, C, E, A], f reader.Kleisli[R, A, B]) ReaderReaderIOEither[R, C, E, B]
- func MonadFlap[R, C, E, B, A any](fab ReaderReaderIOEither[R, C, E, func(A) B], a A) ReaderReaderIOEither[R, C, E, B]
- func MonadMap[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], f func(A) B) ReaderReaderIOEither[R, C, E, B]
- func MonadMapLeft[R, C, E1, E2, A any](fa ReaderReaderIOEither[R, C, E1, A], f func(E1) E2) ReaderReaderIOEither[R, C, E2, A]
- func MonadMapTo[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], b B) ReaderReaderIOEither[R, C, E, B]
- func MonadTap[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], f Kleisli[R, C, E, A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadTapEitherK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f either.Kleisli[E, A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadTapIOK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f io.Kleisli[A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadTapReaderEitherK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f RE.Kleisli[R, E, A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadTapReaderIOK[C, E, R, A, B any](ma ReaderReaderIOEither[R, C, E, A], f readerio.Kleisli[R, A, B]) ReaderReaderIOEither[R, C, E, A]
- func MonadTapReaderK[C, E, R, A, B any](ma ReaderReaderIOEither[R, C, E, A], f reader.Kleisli[R, A, B]) ReaderReaderIOEither[R, C, E, A]
- func Of[R, C, E, A any](a A) ReaderReaderIOEither[R, C, E, A]
- func Retrying[R, C, E, A any](policy retry.RetryPolicy, action Kleisli[R, C, E, retry.RetryStatus, A], ...) ReaderReaderIOEither[R, C, E, A]
- func Right[R, C, E, A any](a A) ReaderReaderIOEither[R, C, E, A]
- func RightIO[R, C, E, A any](ma IO[A]) ReaderReaderIOEither[R, C, E, A]
- func RightReader[C, E, R, A any](ma Reader[R, A]) ReaderReaderIOEither[R, C, E, A]
- func RightReaderIO[C, E, R, A any](ma ReaderIO[R, A]) ReaderReaderIOEither[R, C, E, A]
- type Trampoline
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ChainFirstReaderOptionK ¶
func ChainFirstReaderOptionK[R, C, A, B, E any](onNone Lazy[E]) func(readeroption.Kleisli[R, A, B]) Operator[R, C, E, A, A]
func ChainLeft ¶
func ChainLeft[R, C, EA, EB, A any](f Kleisli[R, C, EB, EA, A]) func(ReaderReaderIOEither[R, C, EA, A]) ReaderReaderIOEither[R, C, EB, A]
func ChainOptionK ¶
func ChainReaderOptionK ¶
func ChainReaderOptionK[R, C, A, B, E any](onNone Lazy[E]) func(readeroption.Kleisli[R, A, B]) Operator[R, C, E, A, B]
func FromOption ¶
func FromPredicate ¶
func Local ¶
func Local[C, E, A, R1, R2 any](f func(R2) R1) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
func MapLeft ¶
func MapLeft[R, C, A, E1, E2 any](f func(E1) E2) func(ReaderReaderIOEither[R, C, E1, A]) ReaderReaderIOEither[R, C, E2, A]
func Read ¶
func Read[C, E, A, R any](r R) func(ReaderReaderIOEither[R, C, E, A]) ReaderIOEither[C, E, A]
func ReadIO ¶
func ReadIO[C, E, A, R any](rio IO[R]) func(ReaderReaderIOEither[R, C, E, A]) ReaderIOEither[C, E, A]
func ReadIOEither ¶
func ReadIOEither[A, R, C, E any](rio IOEither[E, R]) func(ReaderReaderIOEither[R, C, E, A]) ReaderIOEither[C, E, A]
func TapReaderOptionK ¶
func TapReaderOptionK[R, C, A, B, E any](onNone Lazy[E]) func(readeroption.Kleisli[R, A, B]) Operator[R, C, E, A, A]
func Traverse ¶ added in v2.1.17
func Traverse[R2, R1, C, E, A, B any]( f Kleisli[R1, C, E, A, B], ) func(ReaderReaderIOEither[R2, C, E, A]) Kleisli[R2, C, E, R1, B]
Traverse transforms a ReaderReaderIOEither computation by applying a function that produces another ReaderReaderIOEither, effectively swapping the order of outer environment parameters.
This function is useful when you have a computation that depends on environment R2 and produces a value of type A, and you want to transform it using a function that takes A and produces a computation depending on environment R1. The result is a curried function that takes R1 first, then R2, and produces a ReaderIOEither[C, E, B].
Type Parameters:
- R2: The outer environment type from the original computation
- R1: The inner environment type introduced by the transformation
- C: The inner context/environment type (for the ReaderIOEither layer)
- E: The error type
- A: The input value type
- B: The output value type
Parameters:
- f: A Kleisli arrow that transforms A into a ReaderReaderIOEither[R1, C, E, B]
Returns:
- A function that takes a ReaderReaderIOEither[R2, C, E, A] and returns a Kleisli[R2, C, E, R1, B], which is func(R1) ReaderReaderIOEither[R2, C, E, B]
The function preserves error handling and IO effects while reordering the environment dependencies. This is the generalized version of Sequence that also applies a transformation function.
Example:
type UserConfig struct {
UserID int
}
type SystemConfig struct {
SystemID string
}
type Context struct {
RequestID string
}
// Original computation depending on SystemConfig
original := readerreaderioeither.Of[SystemConfig, Context, error](42)
// Transformation that introduces UserConfig dependency
transform := func(n int) readerreaderioeither.ReaderReaderIOEither[UserConfig, Context, error, string] {
return func(userCfg UserConfig) readerioeither.ReaderIOEither[Context, error, string] {
return readerioeither.Of[Context, error](fmt.Sprintf("User %d: %d", userCfg.UserID, n))
}
}
// Apply traverse to swap order and transform
traversed := Traverse[SystemConfig, UserConfig, Context, error, int, string](transform)(original)
// Provide UserConfig first, then SystemConfig
result := traversed(UserConfig{UserID: 1})(SystemConfig{SystemID: "sys1"})(Context{RequestID: "req1"})()
func TraverseReader ¶ added in v2.1.17
func TraverseReader[R2, R1, C, E, A, B any]( f reader.Kleisli[R1, A, B], ) func(ReaderReaderIOEither[R2, C, E, A]) Kleisli[R2, C, E, R1, B]
TraverseReader transforms a ReaderReaderIOEither computation by applying a Reader-based function, effectively introducing a new environment dependency.
This function takes a Reader-based transformation (Kleisli arrow) and returns a function that can transform a ReaderReaderIOEither. The result allows you to provide the Reader's environment (R1) first, which then produces a ReaderReaderIOEither that depends on environment R2.
Type Parameters:
- R2: The outer environment type from the original ReaderReaderIOEither
- R1: The inner environment type introduced by the Reader transformation
- C: The inner context/environment type (for the ReaderIOEither layer)
- E: The error type
- A: The input value type
- B: The output value type
Parameters:
- f: A Reader-based Kleisli arrow that transforms A to B using environment R1
Returns:
- A function that takes a ReaderReaderIOEither[R2, C, E, A] and returns a Kleisli[R2, C, E, R1, B], which is func(R1) ReaderReaderIOEither[R2, C, E, B]
The function preserves error handling and IO effects while adding the Reader environment dependency and reordering the environment parameters. This is useful when you want to introduce a pure (non-IO, non-error) environment dependency to an existing computation.
Example:
type SystemConfig struct {
Timeout int
}
type UserPreferences struct {
Theme string
}
type Context struct {
SessionID string
}
// Original computation depending on SystemConfig
original := readerreaderioeither.Of[SystemConfig, Context, error](100)
// Pure Reader transformation that introduces UserPreferences dependency
formatWithTheme := func(value int) reader.Reader[UserPreferences, string] {
return func(prefs UserPreferences) string {
return fmt.Sprintf("[%s theme] Value: %d", prefs.Theme, value)
}
}
// Apply traverse to introduce UserPreferences and swap order
traversed := TraverseReader[SystemConfig, UserPreferences, Context, error, int, string](formatWithTheme)(original)
// Provide UserPreferences first, then SystemConfig
result := traversed(UserPreferences{Theme: "dark"})(SystemConfig{Timeout: 30})(Context{SessionID: "sess1"})()
Types ¶
type Kleisli ¶
type Kleisli[R, C, E, A, B any] = Reader[A, ReaderReaderIOEither[R, C, E, B]]
func FromReaderOption ¶
func FromReaderOption[R, C, A, E any](onNone Lazy[E]) Kleisli[R, C, E, ReaderOption[R, A], A]
func Sequence ¶ added in v2.1.17
func Sequence[R1, R2, C, E, A any](ma ReaderReaderIOEither[R2, C, E, ReaderReaderIOEither[R1, C, E, A]]) Kleisli[R2, C, E, R1, A]
Sequence swaps the order of nested environment parameters in a ReaderReaderIOEither computation.
This function takes a ReaderReaderIOEither that produces another ReaderReaderIOEither and returns a Kleisli arrow that reverses the order of the outer environment parameters (R1 and R2). The result is a curried function that takes R1 first, then R2, and produces a ReaderIOEither[C, E, A].
Type Parameters:
- R1: The first outer environment type (becomes the outermost after sequence)
- R2: The second outer environment type (becomes inner after sequence)
- C: The inner context/environment type (for the ReaderIOEither layer)
- E: The error type
- A: The success value type
Parameters:
- ma: A ReaderReaderIOEither[R2, C, E, ReaderReaderIOEither[R1, C, E, A]]
Returns:
- A Kleisli[R2, C, E, R1, A], which is func(R1) ReaderReaderIOEither[R2, C, E, A]
The function preserves error handling and IO effects at all levels while reordering the outer environment dependencies. This is particularly useful when you need to change the order in which contexts are provided to a nested computation.
Example:
type OuterConfig struct {
DatabaseURL string
}
type InnerConfig struct {
APIKey string
}
type RequestContext struct {
UserID int
}
// Original: takes OuterConfig, returns computation that may produce
// another computation depending on InnerConfig
original := func(outer OuterConfig) readerioeither.ReaderIOEither[RequestContext, error,
readerreaderioeither.ReaderReaderIOEither[InnerConfig, RequestContext, error, string]] {
return readerioeither.Of[RequestContext, error](
readerreaderioeither.Of[InnerConfig, RequestContext, error]("result"),
)
}
// Sequence swaps InnerConfig and OuterConfig order
sequenced := Sequence(original)
// Now provide InnerConfig first, then OuterConfig
result := sequenced(InnerConfig{APIKey: "key"})(OuterConfig{DatabaseURL: "db"})(RequestContext{UserID: 1})()
func SequenceReader ¶ added in v2.1.17
func SequenceReader[R1, R2, C, E, A any](ma ReaderReaderIOEither[R2, C, E, Reader[R1, A]]) Kleisli[R2, C, E, R1, A]
SequenceReader swaps the order of environment parameters when the inner computation is a pure Reader.
This function is similar to Sequence but specialized for the case where the innermost computation is a pure Reader (without IO or error handling) rather than another ReaderReaderIOEither. It takes a ReaderReaderIOEither that produces a Reader and returns a Kleisli arrow that reverses the order of the outer environment parameters.
Type Parameters:
- R1: The first environment type (becomes outermost after sequence)
- R2: The second environment type (becomes inner after sequence)
- C: The inner context/environment type (for the ReaderIOEither layer)
- E: The error type (only present in the ReaderReaderIOEither layer)
- A: The success value type
Parameters:
- ma: A ReaderReaderIOEither[R2, C, E, Reader[R1, A]]
Returns:
- A Kleisli[R2, C, E, R1, A], which is func(R1) ReaderReaderIOEither[R2, C, E, A]
The function lifts the pure Reader computation into the ReaderIOEither context while reordering the environment dependencies.
Example:
type Config struct {
Multiplier int
}
type Database struct {
ConnectionString string
}
type Context struct {
RequestID string
}
// Original: takes Config, may produce a Reader[Database, int]
original := func(cfg Config) readerioeither.ReaderIOEither[Context, error, reader.Reader[Database, int]] {
return readerioeither.Of[Context, error](func(db Database) int {
return len(db.ConnectionString) * cfg.Multiplier
})
}
// Sequence to provide Database first, then Config
sequenced := SequenceReader(original)
result := sequenced(Database{ConnectionString: "localhost"})(Config{Multiplier: 2})(Context{RequestID: "123"})()
func SequenceReaderIO ¶ added in v2.1.17
func SequenceReaderIO[R1, R2, C, E, A any](ma ReaderReaderIOEither[R2, C, E, ReaderIO[R1, A]]) Kleisli[R2, C, E, R1, A]
SequenceReaderIO swaps the order of environment parameters when the inner computation is a ReaderIO.
This function is specialized for the case where the innermost computation is a ReaderIO (with IO effects but no error handling) rather than another ReaderReaderIOEither. It takes a ReaderReaderIOEither that produces a ReaderIO and returns a Kleisli arrow that reverses the order of the outer environment parameters.
Type Parameters:
- R1: The first environment type (becomes outermost after sequence)
- R2: The second environment type (becomes inner after sequence)
- C: The inner context/environment type (for the ReaderIOEither layer)
- E: The error type (only present in the outer ReaderReaderIOEither layer)
- A: The success value type
Parameters:
- ma: A ReaderReaderIOEither[R2, C, E, ReaderIO[R1, A]]
Returns:
- A Kleisli[R2, C, E, R1, A], which is func(R1) ReaderReaderIOEither[R2, C, E, A]
The function lifts the ReaderIO computation (which has IO effects but no error handling) into the ReaderIOEither context while reordering the environment dependencies.
Example:
type Config struct {
FilePath string
}
type Logger struct {
Level string
}
type Context struct {
TraceID string
}
// Original: takes Config, may produce a ReaderIO[Logger, string]
original := func(cfg Config) readerioeither.ReaderIOEither[Context, error, readerio.ReaderIO[Logger, string]] {
return readerioeither.Of[Context, error](func(logger Logger) io.IO[string] {
return func() string {
return fmt.Sprintf("[%s] Reading from %s", logger.Level, cfg.FilePath)
}
})
}
// Sequence to provide Logger first, then Config
sequenced := SequenceReaderIO(original)
result := sequenced(Logger{Level: "INFO"})(Config{FilePath: "/data"})(Context{TraceID: "abc"})()
type Monoid ¶
func AlternativeMonoid ¶
func ApplicativeMonoid ¶
func ApplicativeMonoidPar ¶
type Operator ¶
type Operator[R, C, E, A, B any] = Kleisli[R, C, E, ReaderReaderIOEither[R, C, E, A], B]
func Alt ¶
func Alt[R, C, E, A any](second Lazy[ReaderReaderIOEither[R, C, E, A]]) Operator[R, C, E, A, A]
func Ap ¶
func Ap[B, R, C, E, A any](fa ReaderReaderIOEither[R, C, E, A]) Operator[R, C, E, func(A) B, B]
func ApEitherS ¶
func ApEitherS[R, C, E, S1, S2, T any]( setter func(T) func(S1) S2, fa Either[E, T], ) Operator[R, C, E, S1, S2]
ApEitherS applies an Either computation and attaches its result to the context.
func ApEitherSL ¶
func ApEitherSL[R, C, E, S, T any]( lens Lens[S, T], fa Either[E, T], ) Operator[R, C, E, S, S]
ApEitherSL is a lens-based version of ApEitherS.
func ApIOEitherS ¶
func ApIOEitherS[R, C, E, S1, S2, T any]( setter func(T) func(S1) S2, fa IOEither[E, T], ) Operator[R, C, E, S1, S2]
ApIOEitherS applies an IOEither computation and attaches its result to the context.
func ApIOEitherSL ¶
func ApIOEitherSL[R, C, E, S, T any]( lens Lens[S, T], fa IOEither[E, T], ) Operator[R, C, E, S, S]
ApIOEitherSL is a lens-based version of ApIOEitherS.
func ApIOS ¶
func ApIOS[R, C, E, S1, S2, T any]( setter func(T) func(S1) S2, fa IO[T], ) Operator[R, C, E, S1, S2]
ApIOS applies an IO computation and attaches its result to the context.
func ApIOSL ¶
func ApIOSL[R, C, E, S, T any]( lens Lens[S, T], fa IO[T], ) Operator[R, C, E, S, S]
ApIOSL is a lens-based version of ApIOS.
func ApReaderIOS ¶
func ApReaderIOS[C, E, R, S1, S2, T any]( setter func(T) func(S1) S2, fa ReaderIO[R, T], ) Operator[R, C, E, S1, S2]
ApReaderIOS applies a ReaderIO computation and attaches its result to the context.
func ApReaderIOSL ¶
func ApReaderIOSL[C, E, R, S, T any]( lens Lens[S, T], fa ReaderIO[R, T], ) Operator[R, C, E, S, S]
ApReaderIOSL is a lens-based version of ApReaderIOS.
func ApReaderS ¶
func ApReaderS[C, E, R, S1, S2, T any]( setter func(T) func(S1) S2, fa Reader[R, T], ) Operator[R, C, E, S1, S2]
ApReaderS applies a Reader computation and attaches its result to the context.
func ApReaderSL ¶
func ApReaderSL[C, E, R, S, T any]( lens Lens[S, T], fa Reader[R, T], ) Operator[R, C, E, S, S]
ApReaderSL is a lens-based version of ApReaderS.
func ApS ¶
func ApS[R, C, E, S1, S2, T any]( setter func(T) func(S1) S2, fa ReaderReaderIOEither[R, C, E, T], ) Operator[R, C, E, S1, S2]
ApS applies a computation in parallel (applicative style) and attaches its result to the context. Unlike Bind, this doesn't allow the computation to depend on the current context state.
Example:
readerreaderioeither.ApS(
func(count int) func(State) State {
return func(s State) State { s.Count = count; return s }
},
getCount, // ReaderReaderIOEither[OuterEnv, InnerEnv, error, int]
)
func ApSL ¶
func ApSL[R, C, E, S, T any]( lens Lens[S, T], fa ReaderReaderIOEither[R, C, E, T], ) Operator[R, C, E, S, S]
ApSL is a lens-based version of ApS that uses a lens to focus on a specific field in the context.
func Bind ¶
func Bind[R, C, E, S1, S2, T any]( setter func(T) func(S1) S2, f func(S1) ReaderReaderIOEither[R, C, E, T], ) Operator[R, C, E, S1, S2]
Bind attaches the result of a computation to a context [S1] to produce a context [S2]. This enables sequential composition where each step can depend on the results of previous steps and access both the outer (R) and inner (C) reader environments.
The setter function takes the result of the computation and returns a function that updates the context from S1 to S2.
Example:
type State struct {
User User
Posts []Post
}
type OuterEnv struct {
Database string
}
type InnerEnv struct {
UserRepo UserRepository
PostRepo PostRepository
}
result := F.Pipe2(
readerreaderioeither.Do[OuterEnv, InnerEnv, error](State{}),
readerreaderioeither.Bind(
func(user User) func(State) State {
return func(s State) State { s.User = user; return s }
},
func(s State) readerreaderioeither.ReaderReaderIOEither[OuterEnv, InnerEnv, error, User] {
return func(outer OuterEnv) readerioeither.ReaderIOEither[InnerEnv, error, User] {
return readerioeither.Asks(func(inner InnerEnv) ioeither.IOEither[error, User] {
return inner.UserRepo.FindUser(outer.Database)
})
}
},
),
readerreaderioeither.Bind(
func(posts []Post) func(State) State {
return func(s State) State { s.Posts = posts; return s }
},
func(s State) readerreaderioeither.ReaderReaderIOEither[OuterEnv, InnerEnv, error, []Post] {
return func(outer OuterEnv) readerioeither.ReaderIOEither[InnerEnv, error, []Post] {
return readerioeither.Asks(func(inner InnerEnv) ioeither.IOEither[error, []Post] {
return inner.PostRepo.FindPostsByUser(outer.Database, s.User.ID)
})
}
},
),
)
func BindEitherK ¶
func BindEitherK[R, C, E, S1, S2, T any]( setter func(T) func(S1) S2, f either.Kleisli[E, S1, T], ) Operator[R, C, E, S1, S2]
BindEitherK binds a computation that returns an Either to the context. The Kleisli function is automatically lifted into ReaderReaderIOEither.
func BindIOEitherK ¶
func BindIOEitherK[R, C, E, S1, S2, T any]( setter func(T) func(S1) S2, f ioeither.Kleisli[E, S1, T], ) Operator[R, C, E, S1, S2]
BindIOEitherK binds a computation that returns an IOEither to the context. The Kleisli function is automatically lifted into ReaderReaderIOEither.
func BindIOEitherKL ¶
func BindIOEitherKL[R, C, E, S, T any]( lens Lens[S, T], f ioeither.Kleisli[E, T, T], ) Operator[R, C, E, S, S]
BindIOEitherKL is a lens-based version of BindIOEitherK.
func BindIOK ¶
func BindIOK[R, C, E, S1, S2, T any]( setter func(T) func(S1) S2, f io.Kleisli[S1, T], ) Operator[R, C, E, S1, S2]
BindIOK binds a computation that returns an IO to the context. The Kleisli function is automatically lifted into ReaderReaderIOEither.
func BindL ¶
func BindL[R, C, E, S, T any]( lens Lens[S, T], f func(T) ReaderReaderIOEither[R, C, E, T], ) Operator[R, C, E, S, S]
BindL is a lens-based version of Bind that uses a lens to focus on a specific field in the context.
func BindReaderIOK ¶
func BindReaderIOK[C, E, R, S1, S2, T any]( setter func(T) func(S1) S2, f readerio.Kleisli[R, S1, T], ) Operator[R, C, E, S1, S2]
BindReaderIOK binds a computation that returns a ReaderIO to the context. The Kleisli function is automatically lifted into ReaderReaderIOEither.
func BindReaderIOKL ¶
func BindReaderIOKL[C, E, R, S, T any]( lens Lens[S, T], f readerio.Kleisli[R, T, T], ) Operator[R, C, E, S, S]
BindReaderIOKL is a lens-based version of BindReaderIOK.
func BindReaderK ¶
func BindReaderK[C, E, R, S1, S2, T any]( setter func(T) func(S1) S2, f reader.Kleisli[R, S1, T], ) Operator[R, C, E, S1, S2]
BindReaderK binds a computation that returns a Reader to the context. The Kleisli function is automatically lifted into ReaderReaderIOEither.
func BindReaderKL ¶
func BindReaderKL[C, E, R, S, T any]( lens Lens[S, T], f reader.Kleisli[R, T, T], ) Operator[R, C, E, S, S]
BindReaderKL is a lens-based version of BindReaderK.
func BindTo ¶
func BindTo[R, C, E, S1, T any]( setter func(T) S1, ) Operator[R, C, E, T, S1]
BindTo wraps a value of type T into a context S1 using the provided setter function. This is typically used as the first operation after Do to initialize the context.
Example:
F.Pipe1(
readerreaderioeither.Of[OuterEnv, InnerEnv, error](42),
readerreaderioeither.BindTo(func(n int) State { return State{Count: n} }),
)
func ChainEitherK ¶
func ChainFirst ¶
func ChainFirst[R, C, E, A, B any](f Kleisli[R, C, E, A, B]) Operator[R, C, E, A, A]
func ChainFirstEitherK ¶
func ChainFirstIOK ¶
func ChainFirstReaderEitherK ¶
func ChainFirstReaderIOK ¶
func ChainFirstReaderK ¶
func ChainIOEitherK ¶
func ChainReaderEitherK ¶
func ChainReaderIOK ¶
func ChainReaderK ¶
func Let ¶
func Let[R, C, E, S1, S2, T any]( setter func(T) func(S1) S2, f func(S1) T, ) Operator[R, C, E, S1, S2]
Let attaches a pure computation result to a context [S1] to produce a context [S2]. Unlike Bind, the computation function f is pure (doesn't perform effects).
Example:
readerreaderioeither.Let(
func(fullName string) func(State) State {
return func(s State) State { s.FullName = fullName; return s }
},
func(s State) string {
return s.FirstName + " " + s.LastName
},
)
func LetL ¶
func LetL[R, C, E, S, T any]( lens Lens[S, T], f func(T) T, ) Operator[R, C, E, S, S]
LetL is a lens-based version of Let that uses a lens to focus on a specific field in the context.
func LetTo ¶
func LetTo[R, C, E, S1, S2, T any]( setter func(T) func(S1) S2, b T, ) Operator[R, C, E, S1, S2]
LetTo attaches a constant value to a context [S1] to produce a context [S2].
Example:
readerreaderioeither.LetTo(
func(status string) func(State) State {
return func(s State) State { s.Status = status; return s }
},
"active",
)
func LetToL ¶
func LetToL[R, C, E, S, T any]( lens Lens[S, T], b T, ) Operator[R, C, E, S, S]
LetToL is a lens-based version of LetTo that uses a lens to focus on a specific field in the context.
func TapEitherK ¶
func TapReaderEitherK ¶
func TapReaderIOK ¶
func TapReaderK ¶
type ReaderEither ¶ added in v2.1.17
type ReaderEither[R, E, A any] = readereither.ReaderEither[R, E, A]
type ReaderIOEither ¶
type ReaderIOEither[R, E, A any] = readerioeither.ReaderIOEither[R, E, A]
type ReaderOption ¶
type ReaderOption[R, A any] = readeroption.ReaderOption[R, A]
type ReaderReaderIOEither ¶
type ReaderReaderIOEither[R, C, E, A any] = Reader[R, ReaderIOEither[C, E, A]]
func Bracket ¶
func Bracket[ R, C, E, A, B, ANY any]( acquire ReaderReaderIOEither[R, C, E, A], use func(A) ReaderReaderIOEither[R, C, E, B], release func(A, Either[E, B]) ReaderReaderIOEither[R, C, E, ANY], ) ReaderReaderIOEither[R, C, E, B]
Bracket ensures that a resource is properly cleaned up regardless of whether the operation succeeds or fails. It follows the acquire-use-release pattern with access to both outer (R) and inner (C) reader contexts.
The release action is always called after the use action completes, whether it succeeds or fails. This makes it ideal for managing resources like file handles, database connections, or locks.
Parameters:
- acquire: Acquires the resource, returning a ReaderReaderIOEither[R, C, E, A]
- use: Uses the acquired resource to perform an operation, returning ReaderReaderIOEither[R, C, E, B]
- release: Releases the resource, receiving both the resource and the result of use
Returns:
- A ReaderReaderIOEither[R, C, E, B] that safely manages the resource lifecycle
The release function receives:
- The acquired resource (A)
- The result of the use function (Either[E, B])
Example:
type OuterConfig struct {
ConnectionPool string
}
type InnerConfig struct {
Timeout time.Duration
}
// Acquire a database connection
acquire := func(outer OuterConfig) readerioeither.ReaderIOEither[InnerConfig, error, *sql.DB] {
return func(inner InnerConfig) ioeither.IOEither[error, *sql.DB] {
return ioeither.TryCatch(
func() (*sql.DB, error) {
return sql.Open("postgres", outer.ConnectionPool)
},
func(err error) error { return err },
)
}
}
// Use the connection
use := func(db *sql.DB) readerreaderioeither.ReaderReaderIOEither[OuterConfig, InnerConfig, error, []User] {
return func(outer OuterConfig) readerioeither.ReaderIOEither[InnerConfig, error, []User] {
return func(inner InnerConfig) ioeither.IOEither[error, []User] {
return queryUsers(db, inner.Timeout)
}
}
}
// Release the connection
release := func(db *sql.DB, result either.Either[error, []User]) readerreaderioeither.ReaderReaderIOEither[OuterConfig, InnerConfig, error, any] {
return func(outer OuterConfig) readerioeither.ReaderIOEither[InnerConfig, error, any] {
return func(inner InnerConfig) ioeither.IOEither[error, any] {
return ioeither.TryCatch(
func() (any, error) {
return nil, db.Close()
},
func(err error) error { return err },
)
}
}
}
result := readerreaderioeither.Bracket(acquire, use, release)
func Do ¶
func Do[R, C, E, S any]( empty S, ) ReaderReaderIOEither[R, C, E, S]
Do creates an empty context of type [S] to be used with the Bind operation. This is the starting point for do-notation style composition with two reader contexts.
Example:
type State struct {
User User
Posts []Post
}
type OuterEnv struct {
Database string
}
type InnerEnv struct {
UserRepo UserRepository
PostRepo PostRepository
}
result := readerreaderioeither.Do[OuterEnv, InnerEnv, error](State{})
func Flatten ¶
func Flatten[R, C, E, A any](mma ReaderReaderIOEither[R, C, E, ReaderReaderIOEither[R, C, E, A]]) ReaderReaderIOEither[R, C, E, A]
func FromEither ¶
func FromEither[R, C, E, A any](t Either[E, A]) ReaderReaderIOEither[R, C, E, A]
func FromIOEither ¶
func FromIOEither[R, C, E, A any](ma IOEither[E, A]) ReaderReaderIOEither[R, C, E, A]
func FromReader ¶
func FromReader[C, E, R, A any](ma Reader[R, A]) ReaderReaderIOEither[R, C, E, A]
func FromReaderEither ¶
func FromReaderEither[R, C, E, A any](ma RE.ReaderEither[R, E, A]) ReaderReaderIOEither[R, C, E, A]
func FromReaderIO ¶
func FromReaderIO[C, E, R, A any](ma ReaderIO[R, A]) ReaderReaderIOEither[R, C, E, A]
func FromReaderIOEither ¶
func FromReaderIOEither[C, E, R, A any](ma ReaderIOEither[R, E, A]) ReaderReaderIOEither[R, C, E, A]
func LeftReader ¶
func LeftReader[C, A, R, E any](ma Reader[R, E]) ReaderReaderIOEither[R, C, E, A]
func LeftReaderIO ¶
func LeftReaderIO[C, A, R, E any](me ReaderIO[R, E]) ReaderReaderIOEither[R, C, E, A]
func MonadAlt ¶
func MonadAlt[R, C, E, A any](first ReaderReaderIOEither[R, C, E, A], second Lazy[ReaderReaderIOEither[R, C, E, A]]) ReaderReaderIOEither[R, C, E, A]
func MonadAp ¶
func MonadAp[R, C, E, A, B any](fab ReaderReaderIOEither[R, C, E, func(A) B], fa ReaderReaderIOEither[R, C, E, A]) ReaderReaderIOEither[R, C, E, B]
func MonadApPar ¶
func MonadApPar[R, C, E, A, B any](fab ReaderReaderIOEither[R, C, E, func(A) B], fa ReaderReaderIOEither[R, C, E, A]) ReaderReaderIOEither[R, C, E, B]
func MonadApSeq ¶
func MonadApSeq[R, C, E, A, B any](fab ReaderReaderIOEither[R, C, E, func(A) B], fa ReaderReaderIOEither[R, C, E, A]) ReaderReaderIOEither[R, C, E, B]
func MonadChain ¶
func MonadChain[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], f Kleisli[R, C, E, A, B]) ReaderReaderIOEither[R, C, E, B]
func MonadChainEitherK ¶
func MonadChainFirst ¶
func MonadChainFirst[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], f Kleisli[R, C, E, A, B]) ReaderReaderIOEither[R, C, E, A]
func MonadChainFirstEitherK ¶
func MonadChainFirstIOK ¶
func MonadChainFirstReaderK ¶
func MonadChainIOEitherK ¶
func MonadChainIOK ¶
func MonadChainLeft ¶
func MonadChainLeft[R, C, EA, EB, A any](fa ReaderReaderIOEither[R, C, EA, A], f Kleisli[R, C, EB, EA, A]) ReaderReaderIOEither[R, C, EB, A]
func MonadChainReaderEitherK ¶
func MonadChainReaderIOK ¶
func MonadChainReaderK ¶
func MonadFlap ¶
func MonadFlap[R, C, E, B, A any](fab ReaderReaderIOEither[R, C, E, func(A) B], a A) ReaderReaderIOEither[R, C, E, B]
func MonadMap ¶
func MonadMap[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], f func(A) B) ReaderReaderIOEither[R, C, E, B]
func MonadMapLeft ¶
func MonadMapLeft[R, C, E1, E2, A any](fa ReaderReaderIOEither[R, C, E1, A], f func(E1) E2) ReaderReaderIOEither[R, C, E2, A]
func MonadMapTo ¶
func MonadMapTo[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], b B) ReaderReaderIOEither[R, C, E, B]
func MonadTap ¶
func MonadTap[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], f Kleisli[R, C, E, A, B]) ReaderReaderIOEither[R, C, E, A]
func MonadTapEitherK ¶
func MonadTapIOK ¶
func MonadTapReaderEitherK ¶
func MonadTapReaderIOK ¶
func MonadTapReaderK ¶
func Retrying ¶
func Retrying[R, C, E, A any]( policy retry.RetryPolicy, action Kleisli[R, C, E, retry.RetryStatus, A], check Predicate[Either[E, A]], ) ReaderReaderIOEither[R, C, E, A]
Retrying retries an action according to a retry policy until it succeeds or the policy gives up. The action receives a RetryStatus that tracks the retry attempt number and cumulative delay. The check predicate determines whether a result should trigger a retry.
This is useful for operations that may fail transiently and need to be retried with backoff, while having access to both outer (R) and inner (C) reader contexts.
Parameters:
- policy: The retry policy that determines delays and when to give up
- action: A Kleisli function that takes RetryStatus and returns a ReaderReaderIOEither
- check: A predicate that returns true if the result should trigger a retry
Returns:
- A ReaderReaderIOEither that will retry according to the policy
Example:
type OuterConfig struct {
MaxRetries int
}
type InnerConfig struct {
Endpoint string
}
// Retry a network call with exponential backoff
policy := retry.ExponentialBackoff(100*time.Millisecond, 2.0)
action := func(status retry.RetryStatus) readerreaderioeither.ReaderReaderIOEither[OuterConfig, InnerConfig, error, Response] {
return func(outer OuterConfig) readerioeither.ReaderIOEither[InnerConfig, error, Response] {
return func(inner InnerConfig) ioeither.IOEither[error, Response] {
return ioeither.TryCatch(
func() (Response, error) {
return makeRequest(inner.Endpoint)
},
func(err error) error { return err },
)
}
}
}
// Retry on network errors
check := func(result either.Either[error, Response]) bool {
return either.IsLeft(result) && isNetworkError(either.GetLeft(result))
}
result := readerreaderioeither.Retrying(policy, action, check)
func RightReader ¶
func RightReader[C, E, R, A any](ma Reader[R, A]) ReaderReaderIOEither[R, C, E, A]
func RightReaderIO ¶
func RightReaderIO[C, E, R, A any](ma ReaderIO[R, A]) ReaderReaderIOEither[R, C, E, A]
type Trampoline ¶
type Trampoline[L, B any] = tailrec.Trampoline[L, B]