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 LocalEitherK[C, A, R1, R2, E any](f either.Kleisli[E, R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
- func LocalIOEitherK[C, A, R1, R2, E any](f ioeither.Kleisli[E, R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
- func LocalIOK[C, E, A, R1, R2 any](f io.Kleisli[R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
- func LocalReaderIOEitherK[A, C, E, R1, R2 any](f readerioeither.Kleisli[C, E, R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
- func LocalReaderK[E, A, C, R1, R2 any](f reader.Kleisli[C, R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
- func LocalReaderReaderIOEitherK[A, C, E, R1, R2 any](f Kleisli[R2, C, E, 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]
- func TailRec[R, C, E, A, B any](f Kleisli[R, C, E, A, Trampoline[A, B]]) Kleisli[R, C, E, A, B]
- func TraverseArray[R, C, E, A, B any](f Kleisli[R, C, E, A, B]) Kleisli[R, C, E, []A, []B]
- 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 ChainFirstLeft[A, R, C, EA, EB, B any](f Kleisli[R, C, EB, EA, B]) Operator[R, C, EA, A, A]
- func ChainFirstLeftIOK[A, R, C, EA, B any](f io.Kleisli[EA, B]) Operator[R, C, EA, 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 ChainReaderIOEitherK[C, R, E, A, B any](f RIOE.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 TapLeft[A, R, C, EA, EB, B any](f Kleisli[R, C, EB, EA, B]) Operator[R, C, EA, A, A]
- func TapLeftIOK[A, R, C, EA, B any](f io.Kleisli[EA, B]) Operator[R, C, EA, 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], use Kleisli[R, C, E, A, B], ...) ReaderReaderIOEither[R, C, E, B]
- func Defer[R, C, E, A any](fa Lazy[ReaderReaderIOEither[R, C, E, A]]) ReaderReaderIOEither[R, C, E, A]
- 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 MonadChainFirstLeft[R, C, EA, EB, A, B any](ma ReaderReaderIOEither[R, C, EA, A], f Kleisli[R, C, EB, EA, B]) ReaderReaderIOEither[R, C, EA, A]
- func MonadChainFirstLeftIOK[R, C, EA, A, B any](ma ReaderReaderIOEither[R, C, EA, A], f io.Kleisli[EA, B]) ReaderReaderIOEither[R, C, EA, 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 MonadTapLeft[R, C, EA, EB, A, B any](ma ReaderReaderIOEither[R, C, EA, A], f Kleisli[R, C, EB, EA, B]) ReaderReaderIOEither[R, C, EA, A]
- func MonadTapLeftIOK[R, C, EA, A, B any](ma ReaderReaderIOEither[R, C, EA, A], f io.Kleisli[EA, B]) ReaderReaderIOEither[R, C, EA, 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
Examples ¶
- After
- Alt
- AltMonoid
- AlternativeMonoid
- Ap
- ApEitherS
- ApEitherSL
- ApIOEitherS
- ApIOEitherSL
- ApIOS
- ApIOSL
- ApReaderIOS
- ApReaderIOSL
- ApReaderS
- ApReaderSL
- ApS
- ApSL
- ApplicativeMonoid
- ApplicativeMonoidPar
- ApplicativeMonoidSeq
- Ask
- Asks
- Bind
- BindEitherK
- BindIOEitherK
- BindIOEitherKL
- BindIOK
- BindIOKL
- BindL
- BindReaderIOK
- BindReaderIOKL
- BindReaderK
- BindReaderKL
- BindTo
- Bracket
- Bracket (AcquireFails)
- Bracket (Transaction)
- Bracket (UseFails)
- Chain
- ChainEitherK
- ChainFirst
- ChainFirstEitherK
- ChainFirstIOK
- ChainFirstLeft
- ChainFirstLeftIOK
- ChainFirstReaderEitherK
- ChainFirstReaderIOK
- ChainFirstReaderK
- ChainFirstReaderOptionK
- ChainIOEitherK
- ChainIOK
- ChainLeft
- ChainOptionK
- ChainReaderEitherK
- ChainReaderIOEitherK
- ChainReaderIOK
- ChainReaderK
- ChainReaderOptionK
- Defer
- Defer (Composition)
- Defer (ErrorCase)
- Delay
- Do
- Flap
- Flatten
- FromEither
- FromIO
- FromIOEither
- FromOption
- FromPredicate
- FromReader
- FromReaderEither
- FromReaderIO
- FromReaderIOEither
- FromReaderOption
- Left
- LeftIO
- LeftReader
- LeftReaderIO
- Let
- LetL
- LetTo
- LetToL
- Local
- LocalEitherK
- LocalIOEitherK
- LocalIOK
- LocalReaderIOEitherK
- LocalReaderK
- LocalReaderReaderIOEitherK
- Map
- MapLeft
- MapTo
- MonadAlt
- MonadAp
- MonadApPar
- MonadApSeq
- MonadChain
- MonadChainEitherK
- MonadChainFirst
- MonadChainFirstEitherK
- MonadChainFirstIOK
- MonadChainFirstLeft
- MonadChainFirstLeftIOK
- MonadChainFirstReaderEitherK
- MonadChainFirstReaderIOK
- MonadChainFirstReaderK
- MonadChainIOEitherK
- MonadChainIOK
- MonadChainLeft
- MonadChainReaderEitherK
- MonadChainReaderIOK
- MonadChainReaderK
- MonadFlap
- MonadMap
- MonadMapLeft
- MonadMapTo
- MonadTap
- MonadTapEitherK
- MonadTapIOK
- MonadTapLeft
- MonadTapLeftIOK
- MonadTapReaderEitherK
- MonadTapReaderIOK
- MonadTapReaderK
- Of
- Read
- ReadIO
- ReadIO (AlwaysReachesComputation)
- ReadIOEither
- ReadIOEither (LeftPropagation)
- Retrying
- Right
- RightIO
- RightReader
- RightReaderIO
- Sequence
- SequenceReader
- SequenceReaderIO
- TailRec
- Tap
- TapEitherK
- TapIOK
- TapLeft
- TapLeftIOK
- TapReaderEitherK
- TapReaderIOK
- TapReaderK
- TapReaderOptionK
- Traverse
- TraverseArray
- TraverseReader
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]
ChainFirstReaderOptionK chains a ReaderOption computation while preserving the original value. If the ReaderOption is None, the provided error function is called.
Example ¶
ExampleChainFirstReaderOptionK validates with a ReaderOption and keeps the value.
aboveFactor := ChainFirstReaderOptionK[exCfg, exReq, int, int](lazy.Of("too small"))(exAboveFactorRO)
fmt.Println(exRun(aboveFactor(Of[exCfg, exReq, string](15))))
Output: Right[int](15)
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]
ChainLeft returns a function that chains a computation on the error channel. This is the curried version of MonadChainLeft.
Example ¶
ExampleChainLeft recovers from an error with a new computation.
recoverLen := ChainLeft(func(e string) exRRIOE[int] {
return exScale(len(e))
})
fmt.Println(exRun(recoverLen(Left[exCfg, exReq, int]("boom"))))
fmt.Println(exRun(recoverLen(Of[exCfg, exReq, string](1))))
Output: Right[int](40) Right[int](1)
func ChainOptionK ¶
func ChainOptionK[R, C, A, B, E any](onNone Lazy[E]) func(option.Kleisli[A, B]) Operator[R, C, E, A, B]
ChainOptionK returns a function that chains an Option-returning function into ReaderReaderIOEither. If the Option is None, the provided error function is called.
Example ¶
ExampleChainOptionK chains a function that returns an Option and maps None to an error.
positive := ChainOptionK[exCfg, exReq, int, int](lazy.Of("not positive"))(O.FromPredicate(N.MoreThan(0)))
fmt.Println(exRun(positive(Of[exCfg, exReq, string](3))))
fmt.Println(exRun(positive(Of[exCfg, exReq, string](-3))))
Output: Right[int](3) Left[string](not positive)
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]
ChainReaderOptionK returns a function that chains a ReaderOption-returning function into ReaderReaderIOEither. If the ReaderOption is None, the provided error function is called.
Example ¶
ExampleChainReaderOptionK chains a ReaderOption and maps None to an error.
aboveFactor := ChainReaderOptionK[exCfg, exReq, int, int](lazy.Of("too small"))(exAboveFactorRO)
fmt.Println(exRun(aboveFactor(Of[exCfg, exReq, string](15))))
fmt.Println(exRun(aboveFactor(Of[exCfg, exReq, string](5))))
Output: Right[int](15) Left[string](too small)
func FromOption ¶
FromOption converts an Option to a ReaderReaderIOEither. If the Option is None, the provided function is called to produce the error.
Example ¶
ExampleFromOption lifts an Option and maps None to an error.
fromOption := FromOption[exCfg, exReq, int](lazy.Of("missing"))
fmt.Println(exRun(fromOption(O.Some(5))))
fmt.Println(exRun(fromOption(O.None[int]())))
Output: Right[int](5) Left[string](missing)
func FromPredicate ¶
func FromPredicate[R, C, E, A any](pred func(A) bool, onFalse func(A) E) func(A) ReaderReaderIOEither[R, C, E, A]
FromPredicate creates a ReaderReaderIOEither from a predicate. If the predicate returns false, the onFalse function is called to produce the error.
Example ¶
ExampleFromPredicate succeeds if the predicate holds and fails otherwise.
positive := FromPredicate[exCfg, exReq](N.MoreThan(0), strconv.Itoa) fmt.Println(exRun(positive(5))) fmt.Println(exRun(positive(-5)))
Output: Right[int](5) Left[string](-5)
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]
Example ¶
ExampleLocal changes the outer environment with a pure function.
fmt.Println(exRunWith(3, F.Pipe1( exScale(4), Local[exReq, string, int](exMakeCfg), )))
Output: Right[int](12)
func LocalEitherK ¶ added in v2.2.1
func LocalEitherK[C, A, R1, R2, E any](f either.Kleisli[E, R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
Example ¶
ExampleLocalEitherK changes the outer environment with an Either that may fail.
toCfg := F.Flow2(exPositive, E.Map[string](exMakeCfg)) fmt.Println(exRunWith(3, F.Pipe1( exScale(4), LocalEitherK[exReq, int](toCfg), )))
Output: Right[int](12)
func LocalIOEitherK ¶ added in v2.2.1
func LocalIOEitherK[C, A, R1, R2, E any](f ioeither.Kleisli[E, R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
Example ¶
ExampleLocalIOEitherK changes the outer environment with an IOEither that may fail.
toCfg := F.Flow3(exPositive, E.Map[string](exMakeCfg), IOE.FromEither[string, exCfg]) fmt.Println(exRunWith(-3, F.Pipe1( exScale(4), LocalIOEitherK[exReq, int](toCfg), )))
Output: Left[string](not positive)
func LocalIOK ¶ added in v2.2.1
func LocalIOK[C, E, A, R1, R2 any](f io.Kleisli[R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
Example ¶
ExampleLocalIOK changes the outer environment with an IO.
fmt.Println(exRunWith(3, F.Pipe1( exScale(4), LocalIOK[exReq, string, int](F.Flow2(exMakeCfg, io.Of[exCfg])), )))
Output: Right[int](12)
func LocalReaderIOEitherK ¶ added in v2.2.1
func LocalReaderIOEitherK[A, C, E, R1, R2 any](f readerioeither.Kleisli[C, E, R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
Example ¶
ExampleLocalReaderIOEitherK derives the outer environment from the old one and the inner environment.
toCfg := func(n int) RIOE.ReaderIOEither[exReq, string, exCfg] {
return RIOE.Asks[string](func(r exReq) exCfg { return exCfg{Factor: n * len(r.User)} })
}
fmt.Println(exRunWith(3, F.Pipe1(
exScale(4),
LocalReaderIOEitherK[int](toCfg),
)))
Output: Right[int](60)
func LocalReaderK ¶ added in v2.2.49
func LocalReaderK[E, A, C, R1, R2 any](f reader.Kleisli[C, R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
Example ¶
ExampleLocalReaderK derives the outer environment from the old one and the inner environment.
toCfg := func(n int) RD.Reader[exReq, exCfg] {
return func(r exReq) exCfg { return exCfg{Factor: n * len(r.User)} }
}
fmt.Println(exRunWith(3, F.Pipe1(
exScale(4),
LocalReaderK[string, int](toCfg),
)))
Output: Right[int](60)
func LocalReaderReaderIOEitherK ¶ added in v2.2.1
func LocalReaderReaderIOEitherK[A, C, E, R1, R2 any](f Kleisli[R2, C, E, R2, R1]) func(ReaderReaderIOEither[R1, C, E, A]) ReaderReaderIOEither[R2, C, E, A]
Example ¶
ExampleLocalReaderReaderIOEitherK derives the outer environment with a full computation.
toCfg := func(n int) ReaderReaderIOEither[int, exReq, string, exCfg] {
return Asks[exReq, string](func(outer int) exCfg { return exCfg{Factor: n + outer} })
}
fmt.Println(exRunWith(3, F.Pipe1(
exScale(4),
LocalReaderReaderIOEitherK[int](toCfg),
)))
Output: Right[int](24)
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]
MapLeft returns a function that transforms the error channel. This is the curried version of MonadMapLeft.
Example ¶
ExampleMapLeft transforms the error.
fmt.Println(exRun(F.Pipe1(
Left[exCfg, exReq, int]("boom"),
MapLeft[exCfg, exReq, int](strings.ToUpper),
)))
Output: Left[string](BOOM)
func Read ¶
func Read[C, E, A, R any](r R) func(ReaderReaderIOEither[R, C, E, A]) ReaderIOEither[C, E, A]
Read executes a ReaderReaderIOEither by providing a concrete outer environment value.
Example ¶
ExampleRead provides the outer environment and returns a ReaderIOEither on the inner one.
rioe := F.Pipe1(
Asks[exReq, string](exFactor),
Read[exReq, string, int](exCfg{Factor: 3}),
)
fmt.Println(rioe(exRequest)())
Output: Right[int](3)
func ReadIO ¶
func ReadIO[C, E, A, R any](rio IO[R]) func(ReaderReaderIOEither[R, C, E, A]) ReaderIOEither[C, E, A]
ReadIO executes a ReaderReaderIOEither by providing an outer environment obtained from an IO.
Example ¶
// ReadIO collapses a ReaderReaderIOEither into a ReaderIOEither by
// supplying the outer environment from a plain IO (which cannot fail).
// The resulting ReaderIOEither still needs the inner environment C.
configIO := func() OuterConfig {
return OuterConfig{database: "postgres"}
}
computation := func(outer OuterConfig) RIOE.ReaderIOEither[InnerConfig, error, string] {
return func(inner InnerConfig) IOE.IOEither[error, string] {
return IOE.Right[error](fmt.Sprintf("%s/%s", outer.database, inner.apiKey))
}
}
rioe := ReadIO[InnerConfig, error, string, OuterConfig](configIO)(computation)
result := rioe(InnerConfig{apiKey: "tok"})()
fmt.Println(E.IsRight(result))
Output: true
Example (AlwaysReachesComputation) ¶
// Unlike ReadIOEither, ReadIO uses an infallible IO to load the outer env,
// so the computation is always executed.
executed := false
configIO := func() OuterConfig { return OuterConfig{} }
computation := func(_ OuterConfig) RIOE.ReaderIOEither[InnerConfig, error, int] {
executed = true
return RIOE.Of[InnerConfig, error](42)
}
ReadIO[InnerConfig, error, int, OuterConfig](configIO)(computation)(InnerConfig{})()
fmt.Println(executed)
Output: true
func ReadIOEither ¶
func ReadIOEither[A, R, C, E any](rio IOEither[E, R]) func(ReaderReaderIOEither[R, C, E, A]) ReaderIOEither[C, E, A]
ReadIOEither executes a ReaderReaderIOEither by providing an outer environment obtained from an IOEither.
Example ¶
// ReadIOEither collapses a ReaderReaderIOEither into a ReaderIOEither by
// supplying the outer environment from an IOEither. When the IOEither is
// Right the contained value is used as the outer env; when it is Left the
// error propagates immediately and the inner computation is never called.
configIO := IOE.Right[error](OuterConfig{database: "postgres"})
computation := func(outer OuterConfig) RIOE.ReaderIOEither[InnerConfig, error, string] {
return func(inner InnerConfig) IOE.IOEither[error, string] {
return IOE.Right[error](fmt.Sprintf("%s/%s", outer.database, inner.apiKey))
}
}
// Supply the outer env; still need to provide the inner env.
rioe := ReadIOEither[string, OuterConfig, InnerConfig, error](configIO)(computation)
result := rioe(InnerConfig{apiKey: "tok"})()
fmt.Println(E.IsRight(result))
Output: true
Example (LeftPropagation) ¶
// When the IOEither is Left the error is forwarded and the computation
// is never executed.
loadErr := errors.New("config unavailable")
configIO := IOE.Left[OuterConfig](loadErr)
executed := false
computation := func(_ OuterConfig) RIOE.ReaderIOEither[InnerConfig, error, int] {
executed = true
return RIOE.Of[InnerConfig, error](0)
}
rioe := ReadIOEither[int, OuterConfig, InnerConfig, error](configIO)(computation)
result := rioe(InnerConfig{})()
fmt.Println(E.IsLeft(result))
fmt.Println(executed)
Output: true false
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]
TapReaderOptionK is an alias for ChainFirstReaderOptionK, executing a ReaderOption side effect while preserving the original value.
Example ¶
ExampleTapReaderOptionK is an alias for ChainFirstReaderOptionK.
aboveFactor := TapReaderOptionK[exCfg, exReq, int, int](lazy.Of("too small"))(exAboveFactorRO)
fmt.Println(exRun(aboveFactor(Of[exCfg, exReq, string](5))))
Output: Left[string](too small)
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"})()
Example ¶
ExampleTraverse maps with a computation on another outer environment and moves that environment first.
traversed := Traverse[string](exScale)(Of[string, exReq, string](4))
fmt.Println(traversed(exConfig)("unused")(exRequest)())
Output: Right[int](40)
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"})()
Example ¶
ExampleTraverseReader maps with a Reader and moves its environment first.
traversed := TraverseReader[string, exCfg, exReq, string](exScaleR)(Of[string, exReq, string](4))
fmt.Println(traversed(exConfig)("unused")(exRequest)())
Output: Right[int](40)
Types ¶
type Either ¶
Either represents a value that is either a Left (error) E or a Right (success) A. It's an alias for either.Either[E, A].
type IO ¶
IO represents a side-effecting computation that produces a value A. It's an alias for io.IO[A].
type IOEither ¶
IOEither represents a side-effecting computation that produces either an error E or a value A. It's an alias for ioeither.IOEither[E, A].
type Kleisli ¶
type Kleisli[R, C, E, A, B any] = Reader[A, ReaderReaderIOEither[R, C, E, B]]
Kleisli represents a Kleisli arrow for ReaderReaderIOEither. It's a function that takes a value A and returns a ReaderReaderIOEither[R, C, E, B].
Kleisli arrows are used for monadic composition, allowing you to chain computations that depend on two environments, perform side effects, and may fail.
Type Parameters:
- R: The outer environment type
- C: The inner environment type
- E: The error type
- A: The input value type
- B: The output value type
Example:
// A Kleisli arrow that validates and processes a user ID
validateUser := func(userID int) ReaderReaderIOEither[Config, Context, error, User] {
return func(cfg Config) readerioeither.ReaderIOEither[Context, error, User] {
return func(ctx Context) ioeither.IOEither[error, User] {
return func() either.Either[error, User] {
if userID <= 0 {
return either.Left[User](errors.New("invalid user ID"))
}
return either.Right[error](User{ID: userID})
}
}
}
}
func FromReaderOption ¶
func FromReaderOption[R, C, A, E any](onNone Lazy[E]) Kleisli[R, C, E, ReaderOption[R, A], A]
FromReaderOption converts a ReaderOption to a ReaderReaderIOEither. If the ReaderOption is None, the provided function is called to produce the error.
Example ¶
ExampleFromReaderOption lifts a ReaderOption and maps None to an error.
fromRO := FromReaderOption[exCfg, exReq, int](lazy.Of("missing"))
fmt.Println(exRun(fromRO(RO.Of[exCfg](5))))
fmt.Println(exRun(fromRO(RO.None[exCfg, int]())))
Output: Right[int](5) Left[string](missing)
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})()
Example ¶
ExampleSequence swaps the order of the outer environments of a nested computation.
nested := Of[string, exReq, string](exScale(4))
fmt.Println(Sequence(nested)(exConfig)("unused")(exRequest)())
Output: Right[int](40)
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"})()
Example ¶
ExampleSequenceReader turns a computation that produces a Reader into one that takes its environment first.
nested := Of[string, exReq, string](RD.Reader[exCfg, int](exFactor))
fmt.Println(SequenceReader(nested)(exConfig)("unused")(exRequest)())
Output: Right[int](10)
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"})()
Example ¶
ExampleSequenceReaderIO turns a computation that produces a ReaderIO into one that takes its environment first.
nested := Of[string, exReq, string](RIO.Asks(exFactor))
fmt.Println(SequenceReaderIO(nested)(exConfig)("unused")(exRequest)())
Output: Right[int](10)
func TailRec ¶ added in v2.4.0
func TailRec[R, C, E, A, B any](f Kleisli[R, C, E, A, Trampoline[A, B]]) Kleisli[R, C, E, A, B]
TailRec implements stack-safe tail recursion for the ReaderReaderIOEither monad.
The step function f maps the current state to a computation that produces a Trampoline:
- Bounce(A): continue the recursion with the new state A
- Land(B): stop the recursion with the final result B
A Left value produced by any step stops the recursion and is returned as is.
The recursion runs in a loop, so the stack does not grow with the number of steps. The step function is only called when the resulting IO runs, and both environments R and C are passed unchanged to every step.
Type Parameters:
- R: The outer environment type
- C: The inner environment type
- E: The error type
- A: The state type that changes during the recursion
- B: The final result type
Parameters:
- f: A Kleisli arrow that computes the next step from the current state
Returns:
- Kleisli[R, C, E, A, B]: A Kleisli arrow that runs the recursion from an initial state
See Also:
- readerioeither.TailRec: Tail recursion with a single environment
- Chain: Sequences computations without loop semantics
Example ¶
ExampleTailRec runs a stack safe loop; each step reads the decrement from the outer environment.
countdown := TailRec(func(n int) exRRIOE[Trampoline[int, string]] {
if n <= 0 {
return Of[exCfg, exReq, string](tailrec.Land[int]("liftoff"))
}
return Asks[exReq, string](func(c exCfg) Trampoline[int, string] {
return tailrec.Bounce[string](n - c.Factor)
})
})
fmt.Println(exRun(countdown(1_000_000)))
Output: Right[string](liftoff)
func TraverseArray ¶ added in v2.2.1
func TraverseArray[R, C, E, A, B any](f Kleisli[R, C, E, A, B]) Kleisli[R, C, E, []A, []B]
TraverseArray transforms an array by applying a function that returns a ReaderReaderIOEither to each element, collecting the results. The first Left short-circuits the traversal.
For an empty input array the resulting array is nil, the canonical empty array.
Example ¶
ExampleTraverseArray applies a computation to each element and collects the results.
fmt.Println(exRun(TraverseArray(exScale)([]int{1, 2, 3})))
fmt.Println(exRun(TraverseArray(F.Flow2(exPositive, FromEither[exCfg, exReq, string, int]))([]int{1, -2, 3})))
Output: Right[[]int]([10 20 30]) Left[string](not positive)
type Lazy ¶
Lazy represents a lazily evaluated computation that produces a value of type A. It's an alias for lazy.Lazy[A].
type Lens ¶
Lens represents an optic for focusing on a part of a data structure. It's an alias for common.Lens[S, T].
type Monoid ¶
func AltMonoid ¶
Example ¶
ExampleAltMonoid picks the first successful computation.
m := AltMonoid(lazy.Of(Left[exCfg, exReq, string]("none")))
fmt.Println(exRun(m.Concat(Left[exCfg, exReq, string]("boom"), exGreet(1))))
fmt.Println(exRun(m.Concat(m.Empty(), F.Pipe1(exScale(1), Map[exCfg, exReq, string](strconv.Itoa)))))
Output: Right[string](hi alice ) Right[string](10)
func AlternativeMonoid ¶
Example ¶
ExampleAlternativeMonoid combines successes and skips failures.
m := AlternativeMonoid[exCfg, exReq, string](N.MonoidSum[int]())
fmt.Println(exRun(m.Concat(exScale(1), exScale(2))))
fmt.Println(exRun(m.Concat(Left[exCfg, exReq, int]("boom"), exScale(2))))
Output: Right[int](30) Right[int](20)
func ApplicativeMonoid ¶
Example ¶
ExampleApplicativeMonoid combines the results of two computations with a monoid.
m := ApplicativeMonoid[exCfg, exReq, string](N.MonoidSum[int]()) fmt.Println(exRun(m.Concat(exScale(1), exScale(2)))) fmt.Println(exRun(m.Empty()))
Output: Right[int](30) Right[int](0)
func ApplicativeMonoidPar ¶
Example ¶
ExampleApplicativeMonoidPar combines the results of two computations concurrently.
m := ApplicativeMonoidPar[exCfg, exReq, string](N.MonoidSum[int]()) fmt.Println(exRun(m.Concat(exScale(1), exScale(2))))
Output: Right[int](30)
func ApplicativeMonoidSeq ¶
Example ¶
ExampleApplicativeMonoidSeq combines the results of two computations sequentially.
m := ApplicativeMonoidSeq[exCfg, exReq, string](N.MonoidSum[int]())
fmt.Println(exRun(m.Concat(exScale(1), Left[exCfg, exReq, int]("boom"))))
Output: Left[string](boom)
type Operator ¶
type Operator[R, C, E, A, B any] = Kleisli[R, C, E, ReaderReaderIOEither[R, C, E, A], B]
Operator represents an endomorphism in the Kleisli category for ReaderReaderIOEither. It's a Kleisli arrow where the input is itself a ReaderReaderIOEither[R, C, E, A].
Operators are useful for transforming or enhancing existing computations, such as adding logging, retry logic, or resource management.
Type Parameters:
- R: The outer environment type
- C: The inner environment type
- E: The error type
- A: The input computation's value type
- B: The output value type
Example:
// An operator that adds retry logic to a computation
withRetry := func(computation ReaderReaderIOEither[Config, Context, error, int]) ReaderReaderIOEither[Config, Context, error, int] {
return func(cfg Config) readerioeither.ReaderIOEither[Context, error, int] {
return func(ctx Context) ioeither.IOEither[error, int] {
return func() either.Either[error, int] {
// Retry logic here
return computation(cfg)(ctx)()
}
}
}
}
func After ¶
After creates an operation that passes after the given time.Time.
Example ¶
ExampleAfter waits until the given time before running the computation.
delayed := F.Pipe1( Of[exCfg, exReq, string](42), After[exCfg, exReq, string, int](time.Now().Add(time.Millisecond)), ) fmt.Println(exRun(delayed))
Output: Right[int](42)
func Alt ¶
func Alt[R, C, E, A any](second Lazy[ReaderReaderIOEither[R, C, E, A]]) Operator[R, C, E, A, A]
Alt returns a function that tries an alternative computation if the first fails. This is the curried version of MonadAlt.
Example ¶
ExampleAlt falls back to another computation on failure.
fallback := Alt(lazy.Of(Of[exCfg, exReq, string](0)))
fmt.Println(exRun(fallback(Of[exCfg, exReq, string](42))))
fmt.Println(exRun(fallback(Left[exCfg, exReq, int]("boom"))))
Output: Right[int](42) Right[int](0)
func Ap ¶
func Ap[B, R, C, E, A any](fa ReaderReaderIOEither[R, C, E, A]) Operator[R, C, E, func(A) B, B]
Ap returns a function that applies a function in a context to a value in a context. This is the curried version of MonadAp.
Example ¶
ExampleAp applies a wrapped function to a wrapped value.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](N.Mul(2)), Ap[int](Of[exCfg, exReq, string](21)), )))
Output: Right[int](42)
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.
Example ¶
ExampleApEitherS adds an independent Either to the state.
fmt.Println(exRun(F.Pipe1( exDo, ApEitherS[exCfg, exReq](exSetX, E.Right[string](7)), )))
Output: Right[readerreaderioeither.exState]({7 })
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.
Example ¶
ExampleApEitherSL sets a field through a lens from an independent Either.
fmt.Println(exRun(F.Pipe1(
exDo,
ApEitherSL[exCfg, exReq](exXLens, E.Left[int]("invalid")),
)))
Output: Left[string](invalid)
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.
Example ¶
ExampleApIOEitherS adds the result of an independent IOEither to the state.
fmt.Println(exRun(F.Pipe1( exDo, ApIOEitherS[exCfg, exReq](exSetX, IOE.Of[string](7)), )))
Output: Right[readerreaderioeither.exState]({7 })
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.
Example ¶
ExampleApIOEitherSL sets a field through a lens from an independent IOEither.
fmt.Println(exRun(F.Pipe1( exDo, ApIOEitherSL[exCfg, exReq](exXLens, IOE.Of[string](7)), )))
Output: Right[readerreaderioeither.exState]({7 })
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.
Example ¶
ExampleApIOS adds the result of an independent IO to the state.
fmt.Println(exRun(F.Pipe1(
exDo,
ApIOS[exCfg, exReq, string](exSetName, io.Of("bob")),
)))
Output: Right[readerreaderioeither.exState]({0 bob})
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.
Example ¶
ExampleApIOSL sets a field through a lens from an independent IO.
fmt.Println(exRun(F.Pipe1( exDo, ApIOSL[exCfg, exReq, string](exXLens, io.Of(7)), )))
Output: Right[readerreaderioeither.exState]({7 })
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.
Example ¶
ExampleApReaderIOS adds the result of an independent ReaderIO on the outer environment to the state.
fmt.Println(exRun(F.Pipe1( exDo, ApReaderIOS[exReq, string](exSetX, RIO.Asks(exFactor)), )))
Output: Right[readerreaderioeither.exState]({10 })
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.
Example ¶
ExampleApReaderIOSL sets a field through a lens from an independent ReaderIO.
fmt.Println(exRun(F.Pipe1( exDo, ApReaderIOSL[exReq, string](exXLens, RIO.Asks(exFactor)), )))
Output: Right[readerreaderioeither.exState]({10 })
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.
Example ¶
ExampleApReaderS adds the result of an independent Reader on the outer environment to the state.
fmt.Println(exRun(F.Pipe1( exDo, ApReaderS[exReq, string](exSetX, exFactor), )))
Output: Right[readerreaderioeither.exState]({10 })
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.
Example ¶
ExampleApReaderSL sets a field through a lens from an independent Reader.
fmt.Println(exRun(F.Pipe1( exDo, ApReaderSL[exReq, string](exXLens, exFactor), )))
Output: Right[readerreaderioeither.exState]({10 })
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]
)
Example ¶
ExampleApS adds the result of an independent computation to the state.
fmt.Println(exRun(F.Pipe2( exDo, ApS(exSetX, exScale(3)), ApS(exSetName, exGreet(1)), )))
Output: Right[readerreaderioeither.exState]({30 hi alice })
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.
Example ¶
ExampleApSL adds the result of an independent computation through a lens.
fmt.Println(exRun(F.Pipe1( exDo, ApSL(exXLens, exScale(3)), )))
Output: Right[readerreaderioeither.exState]({30 })
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)
})
}
},
),
)
Example ¶
ExampleBind adds the result of a computation that depends on the state.
fmt.Println(exRun(F.Pipe2(
exDo,
Bind(exSetX, F.Constant1[exState](exScale(4))),
Bind(exSetName, F.Flow3(exGetX, S.Format[int]("x=%d"), Of[exCfg, exReq, string, string])),
)))
Output: Right[readerreaderioeither.exState]({40 x=40})
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.
Example ¶
ExampleBindEitherK adds the result of an Either to the state.
fmt.Println(exRun(F.Pipe2( exDo, LetToL[exCfg, exReq, string](exXLens, -1), BindEitherK[exCfg, exReq](exSetX, F.Flow2(exGetX, exPositive)), )))
Output: Left[string](not positive)
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.
Example ¶
ExampleBindIOEitherK adds the result of an IOEither to the state.
fmt.Println(exRun(F.Pipe1(
exDo,
BindIOEitherK[exCfg, exReq](exSetX, func(_ exState) IOEither[string, int] {
return IOE.Left[int]("failed")
}),
)))
Output: Left[string](failed)
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.
Example ¶
ExampleBindIOEitherKL updates a field through a lens with an IOEither.
fmt.Println(exRun(F.Pipe2( exDo, LetToL[exCfg, exReq, string](exXLens, 3), BindIOEitherKL[exCfg, exReq](exXLens, F.Flow2(exPositive, IOE.FromEither[string, int])), )))
Output: Right[readerreaderioeither.exState]({3 })
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.
Example ¶
ExampleBindIOK adds the result of an IO to the state.
fmt.Println(exRun(F.Pipe1( exDo, BindIOK[exCfg, exReq, string](exSetX, F.Constant1[exState](io.Of(5))), )))
Output: Right[readerreaderioeither.exState]({5 })
func BindIOKL ¶
BindIOKL is a lens-based version of BindIOK.
Example ¶
ExampleBindIOKL updates a field through a lens with an IO.
fmt.Println(exRun(F.Pipe2( exDo, LetToL[exCfg, exReq, string](exXLens, 3), BindIOKL[exCfg, exReq, string](exXLens, F.Flow2(N.Mul(2), io.Of[int])), )))
Output: Right[readerreaderioeither.exState]({6 })
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.
Example ¶
ExampleBindL updates a field through a lens with a computation.
fmt.Println(exRun(F.Pipe2( exDo, LetToL[exCfg, exReq, string](exXLens, 4), BindL(exXLens, exScale), )))
Output: Right[readerreaderioeither.exState]({40 })
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.
Example ¶
ExampleBindReaderIOK adds the result of a ReaderIO on the outer environment to the state.
fmt.Println(exRun(F.Pipe1( exDo, BindReaderIOK[exReq, string](exSetX, F.Constant1[exState](RIO.Asks(exFactor))), )))
Output: Right[readerreaderioeither.exState]({10 })
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.
Example ¶
ExampleBindReaderIOKL updates a field through a lens with a ReaderIO on the outer environment.
fmt.Println(exRun(F.Pipe2( exDo, LetToL[exCfg, exReq, string](exXLens, 3), BindReaderIOKL[exReq, string](exXLens, exScaleRIO), )))
Output: Right[readerreaderioeither.exState]({30 })
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.
Example ¶
ExampleBindReaderK adds the result of a Reader on the outer environment to the state.
fmt.Println(exRun(F.Pipe1( exDo, BindReaderK[exReq, string](exSetX, F.Constant1[exState](RD.Reader[exCfg, int](exFactor))), )))
Output: Right[readerreaderioeither.exState]({10 })
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.
Example ¶
ExampleBindReaderKL updates a field through a lens with a Reader on the outer environment.
fmt.Println(exRun(F.Pipe2( exDo, LetToL[exCfg, exReq, string](exXLens, 3), BindReaderKL[exReq, string](exXLens, exScaleR), )))
Output: Right[readerreaderioeither.exState]({30 })
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} }),
)
Example ¶
ExampleBindTo starts the do-notation from an existing computation.
fmt.Println(exRun(F.Pipe1(
exScale(1),
BindTo[exCfg, exReq, string](func(x int) exState { return exState{X: x} }),
)))
Output: Right[readerreaderioeither.exState]({10 })
func Chain ¶
func Chain[R, C, E, A, B any](f Kleisli[R, C, E, A, B]) Operator[R, C, E, A, B]
Chain returns a function that sequences computations where the second depends on the first. This is the curried version of MonadChain.
Example ¶
ExampleChain sequences a computation that depends on the previous result.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](2), Chain(exGreet), )))
Output: Right[string](hi alice hi alice )
func ChainEitherK ¶
ChainEitherK returns a function that chains an Either-returning function into ReaderReaderIOEither. This is the curried version of MonadChainEitherK.
Example ¶
ExampleChainEitherK chains a function that returns an Either.
positive := ChainEitherK[exCfg, exReq](exPositive) fmt.Println(exRun(positive(Of[exCfg, exReq, string](3)))) fmt.Println(exRun(positive(Of[exCfg, exReq, string](-3))))
Output: Right[int](3) Left[string](not positive)
func ChainFirst ¶
func ChainFirst[R, C, E, A, B any](f Kleisli[R, C, E, A, B]) Operator[R, C, E, A, A]
ChainFirst returns a function that sequences computations but keeps the first result. This is the curried version of MonadChainFirst.
Example ¶
ExampleChainFirst runs a computation for its effect and keeps the original value.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](4), ChainFirst(exScale), )))
Output: Right[int](4)
func ChainFirstEitherK ¶
ChainFirstEitherK returns a function that chains an Either computation while preserving the original value. This is the curried version of MonadChainFirstEitherK.
Example ¶
ExampleChainFirstEitherK validates the value with an Either and keeps it.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](3), ChainFirstEitherK[exCfg, exReq](exPositive), )))
Output: Right[int](3)
func ChainFirstIOK ¶
ChainFirstIOK returns a function that chains an IO computation while preserving the original value. This is the curried version of MonadChainFirstIOK.
Example ¶
ExampleChainFirstIOK runs a side effect and keeps the original value.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](7), ChainFirstIOK[exCfg, exReq, string](exPrintInt), )))
Output: log: 7 Right[int](7)
func ChainFirstLeft ¶ added in v2.3.44
func ChainFirstLeft[A, R, C, EA, EB, B any](f Kleisli[R, C, EB, EA, B]) Operator[R, C, EA, A, A]
ChainFirstLeft chains a computation that depends on the Left value (error) but discards its result, preserving the original Left value.
This is useful for performing side effects or additional computations when an error occurs, while maintaining the original error in the result. The function executes only when the input is Left (error case).
Type Parameters:
- A: Success value type
- R: Outer reader environment type
- C: Inner reader environment type
- EA: Original error type
- EB: Error type of the chained computation
- B: Type of the chained computation's success value (discarded)
Parameters:
- f: Kleisli arrow that takes the error and returns a new ReaderReaderIOEither computation
Returns:
- An operator that transforms a ReaderReaderIOEither, executing f on Left values
Example:
type OuterCfg struct{ AppName string }
type InnerCfg struct{ LogLevel string }
logError := func(err error) ReaderReaderIOEither[OuterCfg, InnerCfg, error, F.Void] {
return func(outer OuterCfg) ReaderIOEither[InnerCfg, error, F.Void] {
return func(inner InnerCfg) func() IOE.IOEither[error, F.Void] {
return func() IOE.IOEither[error, F.Void] {
fmt.Printf("[%s][%s] Error: %v\n", outer.AppName, inner.LogLevel, err)
return IOE.Of[error](F.VOID)
}
}
}
}
computation := F.Pipe1(
Left[OuterCfg, InnerCfg, int](errors.New("validation failed")),
ChainFirstLeft[int](logError),
)
result := computation(OuterCfg{AppName: "MyApp"})(InnerCfg{LogLevel: "ERROR"})()
// Logs: [MyApp][ERROR] Error: validation failed
// Returns: Left(validation failed)
See Also:
- ChainFirst: Chains on Right values instead of Left
- TapLeft: Alias for ChainFirstLeft
Example ¶
ExampleChainFirstLeft runs a computation on the error and keeps the original error.
logErr := func(e string) exRRIOE[F.Void] {
return FromIO[exCfg, exReq, string](io.FromImpure(func() { fmt.Println("error:", e) }))
}
fmt.Println(exRun(F.Pipe1(
Left[exCfg, exReq, int]("boom"),
ChainFirstLeft[int](logErr),
)))
Output: error: boom Left[string](boom)
func ChainFirstLeftIOK ¶ added in v2.3.44
ChainFirstLeftIOK chains an IO computation that depends on the Left value (error) but discards its result, preserving the original Left value.
This is useful for performing IO side effects (like logging to a file or sending metrics) when an error occurs, while maintaining the original error in the result. The IO computation executes only when the input is Left (error case).
Type Parameters:
- A: Success value type
- R: Outer reader environment type
- C: Inner reader environment type
- EA: Error type
- B: Type of the IO computation's result (discarded)
Parameters:
- f: IO Kleisli arrow that takes the error and returns an IO computation
Returns:
- An operator that transforms a ReaderReaderIOEither, executing f on Left values
Example:
logToFile := func(err error) io.IO[F.Void] {
return func() F.Void {
log.Printf("Error occurred: %v\n", err)
return F.VOID
}
}
computation := F.Pipe1(
Left[OuterCfg, InnerCfg, int](errors.New("database error")),
ChainFirstLeftIOK[int, OuterCfg, InnerCfg](logToFile),
)
result := computation(OuterCfg{})(InnerCfg{})()
// Logs: Error occurred: database error
// Returns: Left(database error)
See Also:
- ChainFirstLeft: Chains ReaderReaderIOEither computations on Left values
- TapLeftIOK: Alias for ChainFirstLeftIOK
Example ¶
ExampleChainFirstLeftIOK runs a side effect on the error and keeps it.
fmt.Println(exRun(F.Pipe1(
Left[exCfg, exReq, int]("boom"),
ChainFirstLeftIOK[int, exCfg, exReq](exPrintErr),
)))
Output: error: boom Left[string](boom)
func ChainFirstReaderEitherK ¶
ChainFirstReaderEitherK returns a function that chains a ReaderEither computation while preserving the original value. This is the curried version of MonadChainFirstReaderEitherK.
Example ¶
ExampleChainFirstReaderEitherK validates with a ReaderEither and keeps the value.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](15), ChainFirstReaderEitherK[exReq](exAboveFactor), )))
Output: Right[int](15)
func ChainFirstReaderIOK ¶
ChainFirstReaderIOK returns a function that chains a ReaderIO computation while preserving the original value. This is the curried version of MonadChainFirstReaderIOK.
Example ¶
ExampleChainFirstReaderIOK runs a ReaderIO and keeps the original value.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](4), ChainFirstReaderIOK[exReq, string](exScaleRIO), )))
Output: Right[int](4)
func ChainFirstReaderK ¶
ChainFirstReaderK returns a function that chains a Reader computation while preserving the original value. This is the curried version of MonadChainFirstReaderK.
Example ¶
ExampleChainFirstReaderK runs a Reader and keeps the original value.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](4), ChainFirstReaderK[exReq, string](exScaleR), )))
Output: Right[int](4)
func ChainIOEitherK ¶
ChainIOEitherK returns a function that chains an IOEither-returning function into ReaderReaderIOEither. This is the curried version of MonadChainIOEitherK.
Example ¶
ExampleChainIOEitherK chains a function that returns an IOEither.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](-1), ChainIOEitherK[exCfg, exReq](F.Flow2(exPositive, IOE.FromEither[string, int])), )))
Output: Left[string](not positive)
func ChainIOK ¶
ChainIOK returns a function that chains an IO-returning function into ReaderReaderIOEither. This is the curried version of MonadChainIOK.
Example ¶
ExampleChainIOK chains a side effect that cannot fail.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](7), ChainIOK[exCfg, exReq, string](F.Flow2(strconv.Itoa, io.Of[string])), )))
Output: Right[string](7)
func ChainReaderEitherK ¶
ChainReaderEitherK returns a function that chains a ReaderEither-returning function into ReaderReaderIOEither. This is the curried version of MonadChainReaderEitherK.
Example ¶
ExampleChainReaderEitherK chains a ReaderEither on the outer environment.
aboveFactor := ChainReaderEitherK[exReq](exAboveFactor) fmt.Println(exRun(aboveFactor(Of[exCfg, exReq, string](15)))) fmt.Println(exRun(aboveFactor(Of[exCfg, exReq, string](5))))
Output: Right[int](5) Left[string](not positive)
func ChainReaderIOEitherK ¶ added in v2.2.1
ChainReaderIOEitherK returns a function that chains a ReaderIOEither-returning function into ReaderReaderIOEither.
Example ¶
ExampleChainReaderIOEitherK chains a ReaderIOEither on the outer environment.
scale := func(n int) RIOE.ReaderIOEither[exCfg, string, int] {
return RIOE.Asks[string](exScaleR(n))
}
fmt.Println(exRun(F.Pipe1(
Of[exCfg, exReq, string](4),
ChainReaderIOEitherK[exReq](scale),
)))
Output: Right[int](40)
func ChainReaderIOK ¶
ChainReaderIOK returns a function that chains a ReaderIO-returning function into ReaderReaderIOEither. This is the curried version of MonadChainReaderIOK.
Example ¶
ExampleChainReaderIOK chains a ReaderIO on the outer environment.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](4), ChainReaderIOK[exReq, string](exScaleRIO), )))
Output: Right[int](40)
func ChainReaderK ¶
ChainReaderK returns a function that chains a Reader-returning function into ReaderReaderIOEither. This is the curried version of MonadChainReaderK.
Example ¶
ExampleChainReaderK chains a Reader on the outer environment.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](4), ChainReaderK[exReq, string](exScaleR), )))
Output: Right[int](40)
func Delay ¶
Delay creates an operation that passes in the value after some delay.
Example ¶
ExampleDelay waits before running the computation.
delayed := F.Pipe1( Of[exCfg, exReq, string](42), Delay[exCfg, exReq, string, int](time.Millisecond), ) fmt.Println(exRun(delayed))
Output: Right[int](42)
func Flap ¶
func Flap[R, C, E, B, A any](a A) Operator[R, C, E, func(A) B, B]
Flap returns a function that applies a fixed value to a function in a context. This is the curried version of MonadFlap.
Example ¶
ExampleFlap applies a wrapped function to a plain value.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](N.Mul(2)), Flap[exCfg, exReq, string, int](21), )))
Output: Right[int](42)
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
},
)
Example ¶
ExampleLet adds the result of a pure computation on the state.
fmt.Println(exRun(F.Pipe2( exDo, LetTo[exCfg, exReq, string](exSetX, 2), Let[exCfg, exReq, string](exSetName, F.Flow2(exGetX, strconv.Itoa)), )))
Output: Right[readerreaderioeither.exState]({2 2})
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.
Example ¶
ExampleLetL updates a field through a lens with a pure function.
fmt.Println(exRun(F.Pipe2( exDo, LetToL[exCfg, exReq, string](exXLens, 4), LetL[exCfg, exReq, string](exXLens, N.Mul(3)), )))
Output: Right[readerreaderioeither.exState]({12 })
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",
)
Example ¶
ExampleLetTo adds a constant to the state.
fmt.Println(exRun(F.Pipe1( exDo, LetTo[exCfg, exReq, string](exSetName, "bob"), )))
Output: Right[readerreaderioeither.exState]({0 bob})
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.
Example ¶
ExampleLetToL sets a field through a lens.
fmt.Println(exRun(F.Pipe1( exDo, LetToL[exCfg, exReq, string](exXLens, 4), )))
Output: Right[readerreaderioeither.exState]({4 })
func Map ¶
func Map[R, C, E, A, B any](f func(A) B) Operator[R, C, E, A, B]
Map returns a function that applies a transformation to the success value. This is the curried version of MonadMap.
Example ¶
ExampleMap transforms the success value.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](21), Map[exCfg, exReq, string](N.Mul(2)), )))
Output: Right[int](42)
func MapTo ¶
func MapTo[R, C, E, A, B any](b B) Operator[R, C, E, A, B]
MapTo returns a function that replaces the success value with a constant. This is the curried version of MonadMapTo.
Example ¶
ExampleMapTo replaces the success value.
fmt.Println(exRun(F.Pipe1(
Of[exCfg, exReq, string](21),
MapTo[exCfg, exReq, string, int]("done"),
)))
Output: Right[string](done)
func Tap ¶
func Tap[R, C, E, A, B any](f Kleisli[R, C, E, A, B]) Operator[R, C, E, A, A]
Tap is an alias for ChainFirst, executing a side effect while preserving the original value.
Example ¶
ExampleTap is an alias for ChainFirst.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](4), Tap(exScale), )))
Output: Right[int](4)
func TapEitherK ¶
TapEitherK is an alias for ChainFirstEitherK, executing an Either side effect while preserving the original value.
Example ¶
ExampleTapEitherK is an alias for ChainFirstEitherK.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](0), TapEitherK[exCfg, exReq](exPositive), )))
Output: Left[string](not positive)
func TapIOK ¶
TapIOK is an alias for ChainFirstIOK, executing an IO side effect while preserving the original value.
Example ¶
ExampleTapIOK is an alias for ChainFirstIOK; the side effect is skipped on failure.
fmt.Println(exRun(F.Pipe1(
Left[exCfg, exReq, int]("boom"),
TapIOK[exCfg, exReq, string](exPrintInt),
)))
Output: Left[string](boom)
func TapLeft ¶ added in v2.3.44
func TapLeft[A, R, C, EA, EB, B any](f Kleisli[R, C, EB, EA, B]) Operator[R, C, EA, A, A]
TapLeft is an alias for ChainFirstLeft.
Chains a computation that depends on the Left value (error) but discards its result, preserving the original Left value. The name "Tap" emphasizes the side-effect nature of the operation.
This is useful for logging, metrics, or other side effects when an error occurs, without modifying the error value itself.
Type Parameters:
- A: Success value type
- R: Outer reader environment type
- C: Inner reader environment type
- EA: Original error type
- EB: Error type of the chained computation
- B: Type of the chained computation's success value (discarded)
Parameters:
- f: Kleisli arrow that takes the error and returns a new ReaderReaderIOEither computation
Returns:
- An operator that transforms a ReaderReaderIOEither, executing f on Left values
Example:
type OuterMetrics struct{ ErrorCount int }
type InnerMetrics struct{ LastError time.Time }
recordError := func(err error) ReaderReaderIOEither[OuterMetrics, InnerMetrics, error, F.Void] {
return func(outer OuterMetrics) ReaderIOEither[InnerMetrics, error, F.Void] {
return func(inner InnerMetrics) func() IOE.IOEither[error, F.Void] {
return func() IOE.IOEither[error, F.Void] {
outer.ErrorCount++
inner.LastError = time.Now()
return IOE.Of[error](F.VOID)
}
}
}
}
pipeline := F.Pipe1(
Left[OuterMetrics, InnerMetrics, int](errors.New("database error")),
TapLeft[int](recordError),
)
result := pipeline(OuterMetrics{})(InnerMetrics{})()
// Increments error count and records timestamp
// Returns: Left(database error)
See Also:
- ChainFirstLeft: The underlying implementation
- Tap: Taps on Right values instead of Left
Example ¶
ExampleTapLeft is an alias for ChainFirstLeft.
fmt.Println(exRun(F.Pipe1(
Left[exCfg, exReq, int]("boom"),
TapLeft[int](F.Flow2(exPrintErr, FromIO[exCfg, exReq, string, string])),
)))
Output: error: boom Left[string](boom)
func TapLeftIOK ¶ added in v2.3.44
TapLeftIOK is an alias for ChainFirstLeftIOK.
Chains an IO computation that depends on the Left value (error) but discards its result, preserving the original Left value. The name "Tap" emphasizes the side-effect nature of the IO operation.
This is useful for IO side effects like logging to files, sending metrics to external services, or updating counters when an error occurs, without modifying the error value itself.
Type Parameters:
- A: Success value type
- R: Outer reader environment type
- C: Inner reader environment type
- EA: Error type
- B: Type of the IO computation's result (discarded)
Parameters:
- f: IO Kleisli arrow that takes the error and returns an IO computation
Returns:
- An operator that transforms a ReaderReaderIOEither, executing f on Left values
Example:
sendAlert := func(err error) io.IO[F.Void] {
return func() F.Void {
alertService.Send("Critical error: " + err.Error())
return F.VOID
}
}
pipeline := F.Pipe1(
Left[OuterCfg, InnerCfg, int](errors.New("critical failure")),
TapLeftIOK[int, OuterCfg, InnerCfg](sendAlert),
)
result := pipeline(OuterCfg{})(InnerCfg{})()
// Sends alert to external service
// Returns: Left(critical failure)
See Also:
- ChainFirstLeftIOK: The underlying implementation
- TapLeft: Taps with ReaderReaderIOEither computations
Example ¶
ExampleTapLeftIOK is an alias for ChainFirstLeftIOK; nothing happens on success.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](1), TapLeftIOK[int, exCfg, exReq](exPrintErr), )))
Output: Right[int](1)
func TapReaderEitherK ¶
TapReaderEitherK is an alias for ChainFirstReaderEitherK, executing a ReaderEither side effect while preserving the original value.
Example ¶
ExampleTapReaderEitherK is an alias for ChainFirstReaderEitherK.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](15), TapReaderEitherK[exReq](exAboveFactor), )))
Output: Right[int](15)
func TapReaderIOK ¶
TapReaderIOK is an alias for ChainFirstReaderIOK, executing a ReaderIO side effect while preserving the original value.
Example ¶
ExampleTapReaderIOK is an alias for ChainFirstReaderIOK.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](4), TapReaderIOK[exReq, string](exScaleRIO), )))
Output: Right[int](4)
func TapReaderK ¶
TapReaderK is an alias for ChainFirstReaderK, executing a Reader side effect while preserving the original value.
Example ¶
ExampleTapReaderK is an alias for ChainFirstReaderK.
fmt.Println(exRun(F.Pipe1( Of[exCfg, exReq, string](4), TapReaderK[exReq, string](exScaleR), )))
Output: Right[int](4)
type Option ¶
Option represents an optional value that may or may not be present. It's an alias for option.Option[A].
type Predicate ¶
Predicate represents a function that tests a value of type A and returns a boolean. It's an alias for predicate.Predicate[A].
type Reader ¶
Reader represents a computation that depends on an environment R and produces a value A. It's an alias for reader.Reader[R, A].
type ReaderEither ¶ added in v2.1.17
type ReaderEither[R, E, A any] = readereither.ReaderEither[R, E, A]
ReaderEither represents a computation that depends on an environment R and produces either an error E or a value A. It's an alias for readereither.ReaderEither[R, E, A].
type ReaderIO ¶
ReaderIO represents a computation that depends on an environment R and performs side effects to produce a value A. It's an alias for readerio.ReaderIO[R, A].
type ReaderIOEither ¶
type ReaderIOEither[R, E, A any] = readerioeither.ReaderIOEither[R, E, A]
ReaderIOEither represents a computation that depends on an environment R, performs side effects, and produces either an error E or a value A. It's an alias for readerioeither.ReaderIOEither[R, E, A].
type ReaderOption ¶
type ReaderOption[R, A any] = readeroption.ReaderOption[R, A]
ReaderOption represents a computation that depends on an environment R and produces an optional value A. It's an alias for readeroption.ReaderOption[R, A].
type ReaderReaderIOEither ¶
type ReaderReaderIOEither[R, C, E, A any] = Reader[R, ReaderIOEither[C, E, A]]
ReaderReaderIOEither represents a nested Reader monad transformer that: 1. Takes an outer environment R 2. Returns a ReaderIOEither that takes an inner environment C 3. Performs side effects 4. Produces either an error E or a value A
This is the core type of this package, enabling computations with two levels of environment dependencies, side effects, and error handling.
Type Parameters:
- R: The outer environment type (first Reader layer)
- C: The inner environment type (ReaderIOEither layer)
- E: The error type
- A: The success value type
Example:
type OuterConfig struct { DatabaseURL string }
type InnerContext struct { RequestID string }
computation := func(outer OuterConfig) readerioeither.ReaderIOEither[InnerContext, error, string] {
return func(inner InnerContext) ioeither.IOEither[error, string] {
return func() either.Either[error, string] {
return either.Right[error](fmt.Sprintf("DB: %s, Request: %s",
outer.DatabaseURL, inner.RequestID))
}
}
}
func Ask ¶
func Ask[R, C, E any]() ReaderReaderIOEither[R, C, E, R]
Ask returns a ReaderReaderIOEither that retrieves the outer context.
Example ¶
ExampleAsk returns the outer environment.
fmt.Println(exRun(Ask[exCfg, exReq, string]()))
Output: Right[readerreaderioeither.exCfg]({10})
func Asks ¶
func Asks[C, E, R, A any](r Reader[R, A]) ReaderReaderIOEither[R, C, E, A]
Asks returns a ReaderReaderIOEither that retrieves a value derived from the outer context.
Example ¶
ExampleAsks projects a value from the outer environment.
fmt.Println(exRun(Asks[exReq, string](exFactor)))
Output: Right[int](10)
func Bracket ¶
func Bracket[ R, C, E, A, B, ANY any]( acquire ReaderReaderIOEither[R, C, E, A], use Kleisli[R, C, E, A, B], release func(A, Either[E, B]) ReaderReaderIOEither[R, C, E, ANY], ) ReaderReaderIOEither[R, C, E, B]
Bracket safely acquires a resource, uses it, and releases it again, following the acquire-use-release pattern. All three steps run with access to both the outer (R) and the inner (C) environment.
Semantics:
- acquire is executed. If it fails, its error is returned and neither use nor release is executed (there is nothing to release).
- use is executed with the acquired resource.
- release is executed with the resource and the outcome of use (an Either[E, B]). It runs no matter whether use succeeded or failed.
- If release succeeds, the outcome of use is returned unchanged (a failed use stays failed). If release fails, its error is returned instead, even if use succeeded, and it replaces the error of a failed use.
The value produced by a successful release (of type ANY) is discarded.
Bracket is lazy: no step runs until both environments have been supplied and the resulting IO is executed. Every execution acquires and releases a fresh resource.
Bracket is implemented point-free on top of the generic bracket combinator: the resource is threaded through MonadChain, and the outcome of use, which may be a Left, is fed into release via a chain over the full Either.
Type Parameters:
- R: The outer environment type
- C: The inner environment type
- E: The error type
- A: The resource type
- B: The result type of use
- ANY: The (ignored) result type of release
Parameters:
- acquire: Produces the resource
- use: Computes the result from the resource
- release: Frees the resource; it receives the resource and the outcome of use
Returns:
- A ReaderReaderIOEither[R, C, E, B] that yields the result of use and guarantees that release runs whenever acquire succeeded
See Also:
- ExampleBracket: basic acquire/use/close pattern
- ExampleBracket_useFails: resource released even when use returns Left
- ExampleBracket_acquireFails: neither use nor release run when acquire returns Left
- ExampleBracket_transaction: release receives the outcome of use to commit or roll back
Example ¶
ExampleBracket acquires a connection using the outer environment, uses it with the inner environment and closes it again.
query := func(conn *exampleConn) ReaderReaderIOEither[exampleConfig, exampleRequest, error, string] {
return func(_ exampleConfig) ReaderIOEither[exampleRequest, error, string] {
return func(req exampleRequest) IOEither[error, string] {
return IOE.Of[error](fmt.Sprintf("%s queried %s", req.user, conn.pool))
}
}
}
program := Bracket(openConn, query, closeConn[string])
// nothing has happened so far, the program only runs once both environments
// are provided and the resulting IO is executed
fmt.Println(program(exampleConfig{pool: "users-db"})(exampleRequest{user: "alice"})())
Output: open users-db for alice close users-db Right[string](alice queried users-db)
Example (AcquireFails) ¶
ExampleBracket_acquireFails shows that neither use nor release run if the resource cannot be acquired.
acquire := Left[exampleConfig, exampleRequest, *exampleConn](errors.New("pool exhausted"))
query := func(conn *exampleConn) ReaderReaderIOEither[exampleConfig, exampleRequest, error, string] {
fmt.Println("query")
return Of[exampleConfig, exampleRequest, error](conn.pool)
}
program := Bracket(acquire, query, closeConn[string])
fmt.Println(program(exampleConfig{pool: "users-db"})(exampleRequest{user: "carol"})())
Output: Left[*errors.errorString](pool exhausted)
Example (Transaction) ¶
ExampleBracket_transaction uses the outcome passed to release to either commit or roll back a transaction. The Bracket is wrapped in a Kleisli arrow so that the same resource handling applies to every input.
type tx struct{ id int }
begin := FromIO[exampleConfig, exampleRequest, error](func() *tx {
fmt.Println("begin")
return &tx{id: 1}
})
commitOrRollback := func(t *tx, outcome Either[error, int]) ReaderReaderIOEither[exampleConfig, exampleRequest, error, F.Void] {
return FromIO[exampleConfig, exampleRequest, error](func() F.Void {
if E.IsRight(outcome) {
fmt.Printf("commit %d\n", t.id)
} else {
fmt.Printf("rollback %d\n", t.id)
}
return F.VOID
})
}
transfer := func(amount int) ReaderReaderIOEither[exampleConfig, exampleRequest, error, int] {
return Bracket(
begin,
func(_ *tx) ReaderReaderIOEither[exampleConfig, exampleRequest, error, int] {
if amount <= 0 {
return Left[exampleConfig, exampleRequest, int](fmt.Errorf("invalid amount %d", amount))
}
return Of[exampleConfig, exampleRequest, error](amount)
},
commitOrRollback,
)
}
cfg := exampleConfig{pool: "ledger"}
req := exampleRequest{user: "dave"}
fmt.Println(transfer(100)(cfg)(req)())
fmt.Println(transfer(-5)(cfg)(req)())
Output: begin commit 1 Right[int](100) begin rollback 1 Left[*errors.errorString](invalid amount -5)
Example (UseFails) ¶
ExampleBracket_useFails shows that the resource is released even if using it fails, and that the error of use is returned.
query := func(_ *exampleConn) ReaderReaderIOEither[exampleConfig, exampleRequest, error, string] {
return Left[exampleConfig, exampleRequest, string](errors.New("query failed"))
}
program := Bracket(openConn, query, closeConn[string])
fmt.Println(program(exampleConfig{pool: "users-db"})(exampleRequest{user: "bob"})())
Output: open users-db for bob close users-db Left[*errors.errorString](query failed)
func Defer ¶ added in v2.2.1
func Defer[R, C, E, A any](fa Lazy[ReaderReaderIOEither[R, C, E, A]]) ReaderReaderIOEither[R, C, E, A]
Defer creates a ReaderReaderIOEither lazily via a generator function. The generator is called each time the ReaderReaderIOEither is executed.
Example ¶
// Defer creates a ReaderReaderIOEither lazily: the generator function is
// called every time the computation is executed, not when it is constructed.
callCount := 0
computation := Defer(func() ReaderReaderIOEither[OuterConfig, InnerConfig, error, int] {
callCount++
return Of[OuterConfig, InnerConfig, error](callCount * 10)
})
// Generator has not been called yet.
fmt.Println("before execution:", callCount)
r1 := computation(OuterConfig{})(InnerConfig{})()
fmt.Println("after first execution:", E.IsRight(r1), callCount)
r2 := computation(OuterConfig{})(InnerConfig{})()
fmt.Println("after second execution:", E.IsRight(r2), callCount)
Output: before execution: 0 after first execution: true 1 after second execution: true 2
Example (Composition) ¶
// Defer composes naturally with other operators in a pipeline.
computation := F.Pipe1(
Defer(func() ReaderReaderIOEither[OuterConfig, InnerConfig, error, int] {
return Of[OuterConfig, InnerConfig, error](21)
}),
Chain(func(n int) ReaderReaderIOEither[OuterConfig, InnerConfig, error, int] {
return Of[OuterConfig, InnerConfig, error](n * 2)
}),
)
result := computation(OuterConfig{})(InnerConfig{})()
fmt.Println(E.IsRight(result))
Output: true
Example (ErrorCase) ¶
// Defer propagates the Left value produced by the deferred computation.
expectedErr := errors.New("something failed")
computation := Defer(func() ReaderReaderIOEither[OuterConfig, InnerConfig, error, int] {
return Left[OuterConfig, InnerConfig, int](expectedErr)
})
result := computation(OuterConfig{})(InnerConfig{})()
fmt.Println(E.IsLeft(result))
Output: true
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{})
Example ¶
ExampleDo starts a do-notation pipeline with an initial state.
fmt.Println(exRun(Do[exCfg, exReq, string](exState{X: 1})))
Output: Right[readerreaderioeither.exState]({1 })
func Flatten ¶
func Flatten[R, C, E, A any](mma ReaderReaderIOEither[R, C, E, ReaderReaderIOEither[R, C, E, A]]) ReaderReaderIOEither[R, C, E, A]
Flatten removes one level of nesting from a nested ReaderReaderIOEither.
Example ¶
ExampleFlatten removes one level of nesting.
nested := Of[exCfg, exReq, string](Of[exCfg, exReq, string](42)) fmt.Println(exRun(Flatten(nested)))
Output: Right[int](42)
func FromEither ¶
func FromEither[R, C, E, A any](t Either[E, A]) ReaderReaderIOEither[R, C, E, A]
FromEither lifts an Either into a ReaderReaderIOEither context.
Example ¶
ExampleFromEither lifts an Either.
fmt.Println(exRun(FromEither[exCfg, exReq](exPositive(3)))) fmt.Println(exRun(FromEither[exCfg, exReq](exPositive(-3))))
Output: Right[int](3) Left[string](not positive)
func FromIO ¶
func FromIO[R, C, E, A any](ma IO[A]) ReaderReaderIOEither[R, C, E, A]
FromIO lifts an IO into a ReaderReaderIOEither context.
Example ¶
ExampleFromIO lifts a side effect that cannot fail.
fmt.Println(exRun(FromIO[exCfg, exReq, string](func() int {
fmt.Println("side effect")
return 1
})))
Output: side effect Right[int](1)
func FromIOEither ¶
func FromIOEither[R, C, E, A any](ma IOEither[E, A]) ReaderReaderIOEither[R, C, E, A]
FromIOEither lifts an IOEither into a ReaderReaderIOEither context.
Example ¶
ExampleFromIOEither lifts an IOEither.
fmt.Println(exRun(FromIOEither[exCfg, exReq](IOE.Of[string](7))))
Output: Right[int](7)
func FromReader ¶
func FromReader[C, E, R, A any](ma Reader[R, A]) ReaderReaderIOEither[R, C, E, A]
FromReader lifts a Reader into a ReaderReaderIOEither context.
Example ¶
ExampleFromReader lifts a Reader on the outer environment.
fmt.Println(exRun(FromReader[exReq, string](exFactor)))
Output: Right[int](10)
func FromReaderEither ¶
func FromReaderEither[R, C, E, A any](ma RE.ReaderEither[R, E, A]) ReaderReaderIOEither[R, C, E, A]
FromReaderEither lifts a ReaderEither into a ReaderReaderIOEither context.
Example ¶
ExampleFromReaderEither lifts a ReaderEither on the outer environment.
fmt.Println(exRun(FromReaderEither[exCfg, exReq](RE.Of[exCfg, string](5))))
Output: Right[int](5)
func FromReaderIO ¶
func FromReaderIO[C, E, R, A any](ma ReaderIO[R, A]) ReaderReaderIOEither[R, C, E, A]
FromReaderIO lifts a ReaderIO into a ReaderReaderIOEither, placing the result in the Right side.
Example ¶
ExampleFromReaderIO lifts a ReaderIO on the outer environment.
fmt.Println(exRun(FromReaderIO[exReq, string](RIO.Asks(exFactor))))
Output: Right[int](10)
func FromReaderIOEither ¶
func FromReaderIOEither[C, E, R, A any](ma ReaderIOEither[R, E, A]) ReaderReaderIOEither[R, C, E, A]
FromReaderIOEither lifts a ReaderIOEither into a ReaderReaderIOEither context.
Example ¶
ExampleFromReaderIOEither lifts a ReaderIOEither on the outer environment.
fmt.Println(exRun(FromReaderIOEither[exReq](RIOE.Of[exCfg, string](5))))
Output: Right[int](5)
func Left ¶
func Left[R, C, A, E any](e E) ReaderReaderIOEither[R, C, E, A]
Left creates a failed ReaderReaderIOEither with the given error.
Example ¶
ExampleLeft creates a failed computation.
fmt.Println(exRun(Left[exCfg, exReq, int]("boom")))
Output: Left[string](boom)
func LeftIO ¶
func LeftIO[R, C, A, E any](ma IO[E]) ReaderReaderIOEither[R, C, E, A]
LeftIO lifts an IO into a ReaderReaderIOEither, placing the result in the Left (error) side.
Example ¶
ExampleLeftIO lifts a side effect that produces an error.
fmt.Println(exRun(LeftIO[exCfg, exReq, int](lazy.Of("boom"))))
Output: Left[string](boom)
func LeftReader ¶
func LeftReader[C, A, R, E any](ma Reader[R, E]) ReaderReaderIOEither[R, C, E, A]
LeftReader lifts a Reader into a ReaderReaderIOEither, placing the result in the Left (error) side.
Example ¶
ExampleLeftReader derives an error from the outer environment.
fmt.Println(exRun(LeftReader[exReq, int](F.Flow2(exFactor, strconv.Itoa))))
Output: Left[string](10)
func LeftReaderIO ¶
func LeftReaderIO[C, A, R, E any](me ReaderIO[R, E]) ReaderReaderIOEither[R, C, E, A]
LeftReaderIO lifts a ReaderIO into a ReaderReaderIOEither, placing the result in the Left (error) side.
Example ¶
ExampleLeftReaderIO derives an error from the outer environment with a side effect.
fmt.Println(exRun(LeftReaderIO[exReq, int](RIO.Of[exCfg]("boom"))))
Output: Left[string](boom)
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]
MonadAlt tries the first computation, and if it fails, tries the second.
Example ¶
ExampleMonadAlt is the non curried version of Alt.
fmt.Println(exRun(MonadAlt(Left[exCfg, exReq, int]("boom"), lazy.Of(exScale(1)))))
Output: Right[int](10)
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]
MonadAp applies a function wrapped in a context to a value wrapped in a context.
Example ¶
ExampleMonadAp is the non curried version of Ap.
fmt.Println(exRun(MonadAp(Of[exCfg, exReq, string](N.Mul(2)), exScale(2))))
Output: Right[int](40)
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]
MonadApPar applies a function in a context to a value in a context, executing them in parallel.
Example ¶
ExampleMonadApPar evaluates the function and the value concurrently.
fmt.Println(exRun(MonadApPar(Of[exCfg, exReq, string](N.Mul(2)), Left[exCfg, exReq, int]("boom"))))
Output: Left[string](boom)
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]
MonadApSeq applies a function in a context to a value in a context, executing them sequentially.
Example ¶
ExampleMonadApSeq evaluates the function before the value.
fmt.Println(exRun(MonadApSeq(Of[exCfg, exReq, string](S.Format[int]("#%d")), exScale(2))))
Output: Right[string](#20)
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]
MonadChain sequences two computations where the second depends on the result of the first.
Example ¶
ExampleMonadChain is the non curried version of Chain.
fmt.Println(exRun(MonadChain(Of[exCfg, exReq, string](4), exScale)))
Output: Right[int](40)
func MonadChainEitherK ¶
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]
MonadChainEitherK chains a computation that returns an Either into a ReaderReaderIOEither.
Example ¶
ExampleMonadChainEitherK is the non curried version of ChainEitherK.
fmt.Println(exRun(MonadChainEitherK(Of[exCfg, exReq, string](-3), exPositive)))
Output: Left[string](not positive)
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]
MonadChainFirst sequences two computations but keeps the result of the first. Useful for performing side effects while preserving the original value.
Example ¶
ExampleMonadChainFirst is the non curried version of ChainFirst.
fmt.Println(exRun(MonadChainFirst(Of[exCfg, exReq, string](4), exGreet)))
Output: Right[int](4)
func MonadChainFirstEitherK ¶
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]
MonadChainFirstEitherK chains an Either-returning computation but keeps the original value.
Example ¶
ExampleMonadChainFirstEitherK is the non curried version of ChainFirstEitherK.
fmt.Println(exRun(MonadChainFirstEitherK(Of[exCfg, exReq, string](0), exPositive)))
Output: Left[string](not positive)
func MonadChainFirstIOK ¶
func MonadChainFirstIOK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f io.Kleisli[A, B]) ReaderReaderIOEither[R, C, E, A]
MonadChainFirstIOK chains an IO computation but keeps the original value.
Example ¶
ExampleMonadChainFirstIOK is the non curried version of ChainFirstIOK.
fmt.Println(exRun(MonadChainFirstIOK(Of[exCfg, exReq, string](7), exPrintInt)))
Output: log: 7 Right[int](7)
func MonadChainFirstLeft ¶ added in v2.3.44
func MonadChainFirstLeft[R, C, EA, EB, A, B any](ma ReaderReaderIOEither[R, C, EA, A], f Kleisli[R, C, EB, EA, B]) ReaderReaderIOEither[R, C, EA, A]
MonadChainFirstLeft is the monadic version of ChainFirstLeft.
Chains a computation that depends on the Left value (error) but discards its result, preserving the original Left value. This is the uncurried version that takes both the ReaderReaderIOEither and the function as parameters.
Type Parameters:
- R: Outer reader environment type
- C: Inner reader environment type
- EA: Original error type
- EB: Error type of the chained computation
- A: Success value type
- B: Type of the chained computation's success value (discarded)
Parameters:
- ma: The input ReaderReaderIOEither computation
- f: Kleisli arrow that takes the error and returns a new ReaderReaderIOEither computation
Returns:
- A ReaderReaderIOEither that executes f on Left values but preserves the original error
Example:
type OuterCfg struct{ RetryCount int }
type InnerCfg struct{ Timeout time.Duration }
incrementRetry := func(err error) ReaderReaderIOEither[OuterCfg, InnerCfg, error, F.Void] {
return func(outer OuterCfg) ReaderIOEither[InnerCfg, error, F.Void] {
return func(inner InnerCfg) func() IOE.IOEither[error, F.Void] {
return func() IOE.IOEither[error, F.Void] {
outer.RetryCount++
return IOE.Of[error](F.VOID)
}
}
}
}
failedOp := Left[OuterCfg, InnerCfg, string](errors.New("network timeout"))
result := MonadChainFirstLeft(failedOp, incrementRetry)
// Increments retry count but returns: Left(network timeout)
See Also:
- ChainFirstLeft: Curried version
- MonadChainFirst: Chains on Right values instead of Left
Example ¶
ExampleMonadChainFirstLeft is the non curried version of ChainFirstLeft.
fmt.Println(exRun(MonadChainFirstLeft( Of[exCfg, exReq, string](1), F.Flow2(strings.ToUpper, Left[exCfg, exReq, int, string]), )))
Output: Right[int](1)
func MonadChainFirstLeftIOK ¶ added in v2.3.44
func MonadChainFirstLeftIOK[R, C, EA, A, B any](ma ReaderReaderIOEither[R, C, EA, A], f io.Kleisli[EA, B]) ReaderReaderIOEither[R, C, EA, A]
MonadChainFirstLeftIOK is the monadic version of ChainFirstLeftIOK.
Chains an IO computation that depends on the Left value (error) but discards its result, preserving the original Left value. This is the uncurried version that takes both the ReaderReaderIOEither and the IO function as parameters.
Type Parameters:
- R: Outer reader environment type
- C: Inner reader environment type
- EA: Error type
- A: Success value type
- B: Type of the IO computation's result (discarded)
Parameters:
- ma: The input ReaderReaderIOEither computation
- f: IO Kleisli arrow that takes the error and returns an IO computation
Returns:
- A ReaderReaderIOEither that executes f on Left values but preserves the original error
Example:
incrementCounter := func(err error) io.IO[F.Void] {
return func() F.Void {
errorCounter++
return F.VOID
}
}
failedOp := Left[OuterCfg, InnerCfg, string](errors.New("timeout"))
result := MonadChainFirstLeftIOK(failedOp, incrementCounter)
// Increments counter but returns: Left(timeout)
See Also:
- ChainFirstLeftIOK: Curried version
- MonadChainFirstLeft: Chains ReaderReaderIOEither computations on Left values
Example ¶
ExampleMonadChainFirstLeftIOK is the non curried version of ChainFirstLeftIOK.
fmt.Println(exRun(MonadChainFirstLeftIOK(Left[exCfg, exReq, int]("boom"), exPrintErr)))
Output: error: boom Left[string](boom)
func MonadChainFirstReaderEitherK ¶
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]
MonadChainFirstReaderEitherK chains a ReaderEither computation but keeps the original value.
Example ¶
ExampleMonadChainFirstReaderEitherK is the non curried version of ChainFirstReaderEitherK.
fmt.Println(exRun(MonadChainFirstReaderEitherK(Of[exCfg, exReq, string](5), exAboveFactor)))
Output: Left[string](not positive)
func MonadChainFirstReaderIOK ¶
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]
MonadChainFirstReaderIOK chains a ReaderIO computation but keeps the original value.
Example ¶
ExampleMonadChainFirstReaderIOK is the non curried version of ChainFirstReaderIOK.
fmt.Println(exRun(MonadChainFirstReaderIOK(Of[exCfg, exReq, string](4), exScaleRIO)))
Output: Right[int](4)
func MonadChainFirstReaderK ¶
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]
MonadChainFirstReaderK chains a Reader computation but keeps the original value.
Example ¶
ExampleMonadChainFirstReaderK is the non curried version of ChainFirstReaderK.
fmt.Println(exRun(MonadChainFirstReaderK(Of[exCfg, exReq, string](4), exScaleR)))
Output: Right[int](4)
func MonadChainIOEitherK ¶
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]
MonadChainIOEitherK chains an IOEither-returning computation into a ReaderReaderIOEither.
Example ¶
ExampleMonadChainIOEitherK is the non curried version of ChainIOEitherK.
fmt.Println(exRun(MonadChainIOEitherK( Of[exCfg, exReq, string](1), F.Flow2(exPositive, IOE.FromEither[string, int]), )))
Output: Right[int](1)
func MonadChainIOK ¶
func MonadChainIOK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f io.Kleisli[A, B]) ReaderReaderIOEither[R, C, E, B]
MonadChainIOK chains an IO-returning computation into a ReaderReaderIOEither.
Example ¶
ExampleMonadChainIOK is the non curried version of ChainIOK.
fmt.Println(exRun(MonadChainIOK(Of[exCfg, exReq, string](7), exPrintInt)))
Output: log: 7 Right[int](7)
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]
MonadChainLeft chains a computation on the error channel, allowing error recovery or transformation.
Example ¶
ExampleMonadChainLeft is the non curried version of ChainLeft.
res := MonadChainLeft(
Left[exCfg, exReq, int]("boom"),
F.Flow2(strings.ToUpper, Left[exCfg, exReq, int, string]),
)
fmt.Println(exRun(res))
Output: Left[string](BOOM)
func MonadChainReaderEitherK ¶
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]
MonadChainReaderEitherK chains a ReaderEither-returning computation into a ReaderReaderIOEither.
Example ¶
ExampleMonadChainReaderEitherK is the non curried version of ChainReaderEitherK.
fmt.Println(exRun(MonadChainReaderEitherK(Of[exCfg, exReq, string](15), exAboveFactor)))
Output: Right[int](5)
func MonadChainReaderIOK ¶
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]
MonadChainReaderIOK chains a ReaderIO-returning computation into a ReaderReaderIOEither.
Example ¶
ExampleMonadChainReaderIOK is the non curried version of ChainReaderIOK.
fmt.Println(exRun(MonadChainReaderIOK(Of[exCfg, exReq, string](4), exScaleRIO)))
Output: Right[int](40)
func MonadChainReaderK ¶
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]
MonadChainReaderK chains a Reader-returning computation into a ReaderReaderIOEither.
Example ¶
ExampleMonadChainReaderK is the non curried version of ChainReaderK.
fmt.Println(exRun(MonadChainReaderK(Of[exCfg, exReq, string](4), exScaleR)))
Output: Right[int](40)
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]
MonadFlap applies a value to a function wrapped in a context.
Example ¶
ExampleMonadFlap is the non curried version of Flap.
fmt.Println(exRun(MonadFlap(Of[exCfg, exReq, string](N.Mul(2)), 21)))
Output: Right[int](42)
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]
MonadMap applies a function to the value inside a ReaderReaderIOEither context. If the computation is successful (Right), the function is applied to the value.
Example ¶
ExampleMonadMap is the non curried version of Map.
fmt.Println(exRun(MonadMap(Of[exCfg, exReq, string](21), N.Mul(2))))
Output: Right[int](42)
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]
MonadMapLeft applies a function to the error value, leaving success unchanged.
Example ¶
ExampleMonadMapLeft is the non curried version of MapLeft; it can change the error type.
res := MonadMapLeft(Left[exCfg, exReq, int]("boom"), S.Size)(exConfig)(exRequest)()
fmt.Println(res)
Output: Left[int](4)
func MonadMapTo ¶
func MonadMapTo[R, C, E, A, B any](fa ReaderReaderIOEither[R, C, E, A], b B) ReaderReaderIOEither[R, C, E, B]
MonadMapTo replaces the success value with a constant value.
Example ¶
ExampleMonadMapTo is the non curried version of MapTo.
fmt.Println(exRun(MonadMapTo(Of[exCfg, exReq, string](21), "done")))
Output: Right[string](done)
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]
MonadTap is an alias for MonadChainFirst, executing a side effect while preserving the original value.
Example ¶
ExampleMonadTap is the non curried version of Tap.
fmt.Println(exRun(MonadTap(Left[exCfg, exReq, int]("boom"), exScale)))
Output: Left[string](boom)
func MonadTapEitherK ¶
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]
MonadTapEitherK is an alias for MonadChainFirstEitherK, executing an Either side effect while preserving the original value.
Example ¶
ExampleMonadTapEitherK is the non curried version of TapEitherK.
fmt.Println(exRun(MonadTapEitherK(Of[exCfg, exReq, string](3), exPositive)))
Output: Right[int](3)
func MonadTapIOK ¶
func MonadTapIOK[R, C, E, A, B any](ma ReaderReaderIOEither[R, C, E, A], f io.Kleisli[A, B]) ReaderReaderIOEither[R, C, E, A]
MonadTapIOK is an alias for MonadChainFirstIOK, executing an IO side effect while preserving the original value.
Example ¶
ExampleMonadTapIOK is the non curried version of TapIOK.
fmt.Println(exRun(MonadTapIOK(Of[exCfg, exReq, string](7), exPrintInt)))
Output: log: 7 Right[int](7)
func MonadTapLeft ¶ added in v2.3.44
func MonadTapLeft[R, C, EA, EB, A, B any](ma ReaderReaderIOEither[R, C, EA, A], f Kleisli[R, C, EB, EA, B]) ReaderReaderIOEither[R, C, EA, A]
MonadTapLeft is the monadic version of TapLeft.
Chains a computation that depends on the Left value (error) but discards its result, preserving the original Left value. This is the uncurried version that takes both the ReaderReaderIOEither and the function as parameters. The name "Tap" emphasizes the side-effect nature of the operation.
Type Parameters:
- R: Outer reader environment type
- C: Inner reader environment type
- EA: Original error type
- EB: Error type of the chained computation
- A: Success value type
- B: Type of the chained computation's success value (discarded)
Parameters:
- ma: The input ReaderReaderIOEither computation
- f: Kleisli arrow that takes the error and returns a new ReaderReaderIOEither computation
Returns:
- A ReaderReaderIOEither that executes f on Left values but preserves the original error
Example:
type OuterLogger struct{ Prefix string }
type InnerLogger struct{ Verbose bool }
logFailure := func(err error) ReaderReaderIOEither[OuterLogger, InnerLogger, error, F.Void] {
return func(outer OuterLogger) ReaderIOEither[InnerLogger, error, F.Void] {
return func(inner InnerLogger) func() IOE.IOEither[error, F.Void] {
return func() IOE.IOEither[error, F.Void] {
if inner.Verbose {
fmt.Printf("%s: %v\n", outer.Prefix, err)
}
return IOE.Of[error](F.VOID)
}
}
}
}
operation := Left[OuterLogger, InnerLogger, int](errors.New("parse error"))
result := MonadTapLeft(operation, logFailure)
// Logs the error with prefix if verbose mode is enabled
// Returns: Left(parse error)
See Also:
- TapLeft: Curried version
- MonadTap: Taps on Right values instead of Left
Example ¶
ExampleMonadTapLeft is the non curried version of TapLeft.
fmt.Println(exRun(MonadTapLeft(
Left[exCfg, exReq, int]("boom"),
F.Flow2(exPrintErr, FromIO[exCfg, exReq, string, string]),
)))
Output: error: boom Left[string](boom)
func MonadTapLeftIOK ¶ added in v2.3.44
func MonadTapLeftIOK[R, C, EA, A, B any](ma ReaderReaderIOEither[R, C, EA, A], f io.Kleisli[EA, B]) ReaderReaderIOEither[R, C, EA, A]
MonadTapLeftIOK is the monadic version of TapLeftIOK.
Chains an IO computation that depends on the Left value (error) but discards its result, preserving the original Left value. This is the uncurried version that takes both the ReaderReaderIOEither and the IO function as parameters. The name "Tap" emphasizes the side-effect nature of the IO operation.
Type Parameters:
- R: Outer reader environment type
- C: Inner reader environment type
- EA: Error type
- A: Success value type
- B: Type of the IO computation's result (discarded)
Parameters:
- ma: The input ReaderReaderIOEither computation
- f: IO Kleisli arrow that takes the error and returns an IO computation
Returns:
- A ReaderReaderIOEither that executes f on Left values but preserves the original error
Example:
writeToLog := func(err error) io.IO[F.Void] {
return func() F.Void {
logFile.WriteString(fmt.Sprintf("[ERROR] %v\n", err))
return F.VOID
}
}
operation := Left[OuterCfg, InnerCfg, int](errors.New("parse error"))
result := MonadTapLeftIOK(operation, writeToLog)
// Writes error to log file
// Returns: Left(parse error)
See Also:
- TapLeftIOK: Curried version
- MonadTapLeft: Taps with ReaderReaderIOEither computations
Example ¶
ExampleMonadTapLeftIOK is the non curried version of TapLeftIOK.
fmt.Println(exRun(MonadTapLeftIOK(Left[exCfg, exReq, int]("boom"), exPrintErr)))
Output: error: boom Left[string](boom)
func MonadTapReaderEitherK ¶
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]
MonadTapReaderEitherK is an alias for MonadChainFirstReaderEitherK, executing a ReaderEither side effect while preserving the original value.
Example ¶
ExampleMonadTapReaderEitherK is the non curried version of TapReaderEitherK.
fmt.Println(exRun(MonadTapReaderEitherK(Of[exCfg, exReq, string](15), exAboveFactor)))
Output: Right[int](15)
func MonadTapReaderIOK ¶
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]
MonadTapReaderIOK is an alias for MonadChainFirstReaderIOK, executing a ReaderIO side effect while preserving the original value.
Example ¶
ExampleMonadTapReaderIOK is the non curried version of TapReaderIOK.
fmt.Println(exRun(MonadTapReaderIOK(Of[exCfg, exReq, string](4), exScaleRIO)))
Output: Right[int](4)
func MonadTapReaderK ¶
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]
MonadTapReaderK is an alias for MonadChainFirstReaderK, executing a Reader side effect while preserving the original value.
Example ¶
ExampleMonadTapReaderK is the non curried version of TapReaderK.
fmt.Println(exRun(MonadTapReaderK(Of[exCfg, exReq, string](4), exScaleR)))
Output: Right[int](4)
func Of ¶
func Of[R, C, E, A any](a A) ReaderReaderIOEither[R, C, E, A]
Of creates a successful ReaderReaderIOEither with the given value. This is the pointed functor operation.
Example ¶
ExampleOf lifts a pure value into a computation that ignores both environments.
fmt.Println(exRun(Of[exCfg, exReq, string](42)))
Output: Right[int](42)
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)
Example ¶
ExampleRetrying retries an action as long as it fails, up to the limit of the policy.
action := func(status retry.RetryStatus) exRRIOE[int] {
return FromEither[exCfg, exReq](exPositive(int(status.IterNumber) - 1))
}
retried := Retrying(retry.LimitRetries(5), action, E.IsLeft[string, int])
fmt.Println(exRun(retried))
Output: Right[int](1)
func Right ¶
func Right[R, C, E, A any](a A) ReaderReaderIOEither[R, C, E, A]
Right creates a successful ReaderReaderIOEither with the given value.
Example ¶
ExampleRight creates a successful computation.
fmt.Println(exRun(Right[exCfg, exReq, string](42)))
Output: Right[int](42)
func RightIO ¶
func RightIO[R, C, E, A any](ma IO[A]) ReaderReaderIOEither[R, C, E, A]
RightIO lifts an IO into a ReaderReaderIOEither, placing the result in the Right side.
Example ¶
ExampleRightIO is an alias for FromIO.
fmt.Println(exRun(RightIO[exCfg, exReq, string](lazy.Of(1))))
Output: Right[int](1)
func RightReader ¶
func RightReader[C, E, R, A any](ma Reader[R, A]) ReaderReaderIOEither[R, C, E, A]
RightReader lifts a Reader into a ReaderReaderIOEither, placing the result in the Right side.
Example ¶
ExampleRightReader is an alias for FromReader.
fmt.Println(exRun(RightReader[exReq, string](exFactor)))
Output: Right[int](10)
func RightReaderIO ¶
func RightReaderIO[C, E, R, A any](ma ReaderIO[R, A]) ReaderReaderIOEither[R, C, E, A]
RightReaderIO lifts a ReaderIO into a ReaderReaderIOEither, placing the result in the Right side.
Example ¶
ExampleRightReaderIO is an alias for FromReaderIO.
fmt.Println(exRun(RightReaderIO[exReq, string](RIO.Asks(exFactor))))
Output: Right[int](10)
type Trampoline ¶
type Trampoline[L, B any] = tailrec.Trampoline[L, B]
Trampoline represents a tail-recursive computation that can be executed without stack overflow. It's an alias for tailrec.Trampoline[L, B].