Documentation
¶
Overview ¶
Package either provides the Either monad, a data structure representing a value of one of two possible types.
Either is commonly used for error handling, where by convention:
- Left represents an error or failure case (type E)
- Right represents a success case (type A)
Fantasy Land Specification ¶
This implementation corresponds to the Fantasy Land Either type: 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
- Foldable: https://github.com/fantasyland/fantasy-land#foldable
Core Concepts ¶
The Either type is a discriminated union that can hold either a Left value (typically an error) or a Right value (typically a successful result). This makes it ideal for computations that may fail.
Basic Usage ¶
// Creating Either values
success := either.Right[error](42) // Right value
failure := either.Left[int](errors.New("oops")) // Left value
// Pattern matching with Fold
result := either.Fold(
func(err error) string { return "Error: " + err.Error() },
func(n int) string { return fmt.Sprintf("Success: %d", n) },
)(success)
// Chaining operations (short-circuits on Left)
result := either.Chain(func(n int) either.Either[error, int] {
return either.Right[error](n * 2)
})(success)
Monadic Operations ¶
Either implements the Monad interface, providing:
- Map: Transform the Right value
- Chain (FlatMap): Chain computations that may fail
- Ap: Apply a function wrapped in Either
Error Handling ¶
Either provides utilities for working with Go's error type:
- TryCatchError: Convert (value, error) tuples to Either
- UnwrapError: Convert Either back to (value, error) tuple
- FromError: Create Either from error-returning functions
Subpackages ¶
- either/exec: Execute system commands returning Either
- either/http: HTTP request builders returning Either
- either/testing: Testing utilities for Either laws
package either implements the Either monad
A data type that can be of either of two types but not both. This is typically used to carry an error or a return value
Index ¶
- func AltSemigroup[E, A any]() S.Semigroup[Either[E, A]]
- func AltW[E, E1, A any](that Lazy[Either[E1, A]]) func(Either[E, A]) Either[E1, A]
- func ApV[B, A, E any](sg S.Semigroup[E]) func(Either[E, A]) Operator[E, func(A) B, B]
- func Applicative[E, A, B any]() ...
- func ApplicativeMonoid[E, A any](m M.Monoid[A]) M.Monoid[Either[E, A]]
- func ApplicativeV[E, A, B any](sg S.Semigroup[E]) ...
- func ApplySemigroup[E, A any](s S.Semigroup[A]) S.Semigroup[Either[E, A]]
- func BiMap[E1, E2, A, B any](f func(E1) E2, g func(a A) B) func(Either[E1, A]) Either[E2, B]
- func ChainOptionK[A, B, E any](onNone func() E) func(func(A) Option[B]) Operator[E, A, B]
- func CompactArray[E, A any](fa []Either[E, A]) []A
- func CompactArrayG[A1 ~[]Either[E, A], A2 ~[]A, E, A any](fa A1) A2
- func CompactRecord[K comparable, E, A any](m map[K]Either[E, A]) map[K]A
- func CompactRecordG[M1 ~map[K]Either[E, A], M2 ~map[K]A, K comparable, E, A any](m M1) M2
- func Curry0[R any](f func() (R, error)) func() Either[error, R]
- func Curry1[T1, R any](f func(T1) (R, error)) func(T1) Either[error, R]
- func Curry2[T1, T2, R any](f func(T1, T2) (R, error)) func(T1) func(T2) Either[error, R]
- func Curry3[T1, T2, T3, R any](f func(T1, T2, T3) (R, error)) func(T1) func(T2) func(T3) Either[error, R]
- func Curry4[T1, T2, T3, T4, R any](f func(T1, T2, T3, T4) (R, error)) func(T1) func(T2) func(T3) func(T4) Either[error, R]
- func Eitherize0[F ~func() (R, error), R any](f F) func() Either[error, R]
- func Eitherize1[F ~func(T0) (R, error), T0, R any](f F) func(T0) Either[error, R]
- func Eitherize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error), ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) Either[error, R]
- func Eitherize11[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) (R, error), ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) Either[error, R]
- func Eitherize12[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) (R, error), ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) Either[error, R]
- func Eitherize13[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) (R, error), ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) Either[error, R]
- func Eitherize14[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) (R, error), ...](f F) ...
- func Eitherize15[...](f F) ...
- func Eitherize2[F ~func(T0, T1) (R, error), T0, T1, R any](f F) func(T0, T1) Either[error, R]
- func Eitherize3[F ~func(T0, T1, T2) (R, error), T0, T1, T2, R any](f F) func(T0, T1, T2) Either[error, R]
- func Eitherize4[F ~func(T0, T1, T2, T3) (R, error), T0, T1, T2, T3, R any](f F) func(T0, T1, T2, T3) Either[error, R]
- func Eitherize5[F ~func(T0, T1, T2, T3, T4) (R, error), T0, T1, T2, T3, T4, R any](f F) func(T0, T1, T2, T3, T4) Either[error, R]
- func Eitherize6[F ~func(T0, T1, T2, T3, T4, T5) (R, error), T0, T1, T2, T3, T4, T5, R any](f F) func(T0, T1, T2, T3, T4, T5) Either[error, R]
- func Eitherize7[F ~func(T0, T1, T2, T3, T4, T5, T6) (R, error), ...](f F) func(T0, T1, T2, T3, T4, T5, T6) Either[error, R]
- func Eitherize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) (R, error), ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) Either[error, R]
- func Eitherize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error), ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) Either[error, R]
- func Eq[E, A any](e EQ.Eq[E], a EQ.Eq[A]) EQ.Eq[Either[E, A]]
- func Fold[E, A, B any](onLeft func(E) B, onRight func(A) B) func(Either[E, A]) B
- func FromError[A any](f func(a A) error) func(A) Either[error, A]
- func FromNillable[A, E any](e E) func(*A) Either[E, *A]
- func FromOption[A, E any](onNone func() E) func(Option[A]) Either[E, A]
- func FromPredicate[E, A any](pred func(A) bool, onFalse func(A) E) func(A) Either[E, A]
- func FromStrictEquals[E, A comparable]() EQ.Eq[Either[E, A]]
- func Functor[E, A, B any]() functor.Functor[A, B, Either[E, A], Either[E, B]]
- func GetOrElse[E, A any](onLeft func(E) A) func(Either[E, A]) A
- func IsLeft[E, A any](val Either[E, A]) bool
- func IsRight[E, A any](val Either[E, A]) bool
- func Logger[E, A any](loggers ...*log.Logger) func(string) Operator[E, A, A]
- func MapLeft[A, E1, E2 any](f func(E1) E2) func(fa Either[E1, A]) Either[E2, A]
- func Monad[E, A, B any]() monad.Monad[A, B, Either[E, A], Either[E, B], Either[E, func(A) B]]
- func MonadApV[B, A, E any](sg S.Semigroup[E]) func(fab Either[E, func(a A) B], fa Either[E, A]) Either[E, B]
- func MonadFold[E, A, B any](ma Either[E, A], onLeft func(e E) B, onRight func(a A) B) B
- func Pointed[E, A any]() pointed.Pointed[A, Either[E, A]]
- func Reduce[E, A, B any](f func(B, A) B, initial B) func(Either[E, A]) B
- func Sequence[E, A, HKTA, HKTRA any](mof func(Either[E, A]) HKTRA, mmap func(Kleisli[E, A, A]) func(HKTA) HKTRA) func(Either[E, HKTA]) HKTRA
- func Sequence2[E, T1, T2, R any](f func(T1, T2) Either[E, R]) func(Either[E, T1], Either[E, T2]) Either[E, R]
- func Sequence3[E, T1, T2, T3, R any](f func(T1, T2, T3) Either[E, R]) func(Either[E, T1], Either[E, T2], Either[E, T3]) Either[E, R]
- func ToError[A any](e Either[error, A]) error
- func ToSLogAttr[E, A any]() func(Either[E, A]) slog.Attr
- func ToType[A, E any](onError func(any) E) func(any) Either[E, A]
- func Traverse[A, E, B, HKTB, HKTRB any](mof func(Either[E, B]) HKTRB, mmap func(Kleisli[E, B, B]) func(HKTB) HKTRB) func(func(A) HKTB) func(Either[E, A]) HKTRB
- func TraverseTuple1[F1 ~func(A1) Either[E, T1], E, A1, T1 any](f1 F1) func(T.Tuple1[A1]) Either[E, T.Tuple1[T1]]
- func TraverseTuple10[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10) ...
- func TraverseTuple11[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, ...) ...
- func TraverseTuple12[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, ...) ...
- func TraverseTuple13[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, ...) ...
- func TraverseTuple14[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, ...) ...
- func TraverseTuple15[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, ...) ...
- func TraverseTuple2[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], E, A1, T1, A2, T2 any](f1 F1, f2 F2) func(T.Tuple2[A1, A2]) Either[E, T.Tuple2[T1, T2]]
- func TraverseTuple3[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3) func(T.Tuple3[A1, A2, A3]) Either[E, T.Tuple3[T1, T2, T3]]
- func TraverseTuple4[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4) func(T.Tuple4[A1, A2, A3, A4]) Either[E, T.Tuple4[T1, T2, T3, T4]]
- func TraverseTuple5[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(T.Tuple5[A1, A2, A3, A4, A5]) Either[E, T.Tuple5[T1, T2, T3, T4, T5]]
- func TraverseTuple6[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6) ...
- func TraverseTuple7[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7) ...
- func TraverseTuple8[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8) ...
- func TraverseTuple9[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9) ...
- func Uncurry0[R any](f func() Either[error, R]) func() (R, error)
- func Uncurry1[T1, R any](f func(T1) Either[error, R]) func(T1) (R, error)
- func Uncurry2[T1, T2, R any](f func(T1) func(T2) Either[error, R]) func(T1, T2) (R, error)
- func Uncurry3[T1, T2, T3, R any](f func(T1) func(T2) func(T3) Either[error, R]) func(T1, T2, T3) (R, error)
- func Uncurry4[T1, T2, T3, T4, R any](f func(T1) func(T2) func(T3) func(T4) Either[error, R]) func(T1, T2, T3, T4) (R, error)
- func Uneitherize0[F ~func() Either[error, R], R any](f F) func() (R, error)
- func Uneitherize1[F ~func(T0) Either[error, R], T0, R any](f F) func(T0) (R, error)
- func Uneitherize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) Either[error, R], ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error)
- func Uneitherize11[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) Either[error, R], ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) (R, error)
- func Uneitherize12[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) Either[error, R], ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) (R, error)
- func Uneitherize13[...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) (R, error)
- func Uneitherize14[...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) (R, error)
- func Uneitherize15[...](f F) ...
- func Uneitherize2[F ~func(T0, T1) Either[error, R], T0, T1, R any](f F) func(T0, T1) (R, error)
- func Uneitherize3[F ~func(T0, T1, T2) Either[error, R], T0, T1, T2, R any](f F) func(T0, T1, T2) (R, error)
- func Uneitherize4[F ~func(T0, T1, T2, T3) Either[error, R], T0, T1, T2, T3, R any](f F) func(T0, T1, T2, T3) (R, error)
- func Uneitherize5[F ~func(T0, T1, T2, T3, T4) Either[error, R], T0, T1, T2, T3, T4, R any](f F) func(T0, T1, T2, T3, T4) (R, error)
- func Uneitherize6[F ~func(T0, T1, T2, T3, T4, T5) Either[error, R], ...](f F) func(T0, T1, T2, T3, T4, T5) (R, error)
- func Uneitherize7[F ~func(T0, T1, T2, T3, T4, T5, T6) Either[error, R], ...](f F) func(T0, T1, T2, T3, T4, T5, T6) (R, error)
- func Uneitherize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) Either[error, R], ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) (R, error)
- func Uneitherize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) Either[error, R], ...](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error)
- func Unvariadic0[V, R any](f func(...V) (R, error)) func([]V) Either[error, R]
- func Unvariadic1[T1, V, R any](f func(T1, ...V) (R, error)) func(T1, []V) Either[error, R]
- func Unvariadic2[T1, T2, V, R any](f func(T1, T2, ...V) (R, error)) func(T1, T2, []V) Either[error, R]
- func Unvariadic3[T1, T2, T3, V, R any](f func(T1, T2, T3, ...V) (R, error)) func(T1, T2, T3, []V) Either[error, R]
- func Unvariadic4[T1, T2, T3, T4, V, R any](f func(T1, T2, T3, T4, ...V) (R, error)) func(T1, T2, T3, T4, []V) Either[error, R]
- func Unwrap[E, A any](ma Either[E, A]) (A, E)
- func UnwrapError[A any](ma Either[error, A]) (A, error)
- func Variadic0[V, R any](f func([]V) (R, error)) func(...V) Either[error, R]
- func Variadic1[T1, V, R any](f func(T1, []V) (R, error)) func(T1, ...V) Either[error, R]
- func Variadic2[T1, T2, V, R any](f func(T1, T2, []V) (R, error)) func(T1, T2, ...V) Either[error, R]
- func Variadic3[T1, T2, T3, V, R any](f func(T1, T2, T3, []V) (R, error)) func(T1, T2, T3, ...V) Either[error, R]
- func Variadic4[T1, T2, T3, T4, V, R any](f func(T1, T2, T3, T4, []V) (R, error)) func(T1, T2, T3, T4, ...V) Either[error, R]
- type Either
- func Do[E, S any](empty S) Either[E, S]
- func Flatten[E, A any](mma Either[E, Either[E, A]]) Either[E, A]
- func FromIO[E any, IO ~func() A, A any](f IO) Either[E, A]
- func Left[A, E any](value E) Either[E, A]
- func Memoize[E, A any](val Either[E, A]) Either[E, A]
- func MonadAlt[E, A any](fa Either[E, A], that Lazy[Either[E, A]]) Either[E, A]
- func MonadAp[B, E, A any](fab Either[E, func(a A) B], fa Either[E, A]) Either[E, B]
- func MonadBiMap[E1, E2, A, B any](fa Either[E1, A], f func(E1) E2, g func(a A) B) Either[E2, B]
- func MonadChain[E, A, B any](fa Either[E, A], f Kleisli[E, A, B]) Either[E, B]
- func MonadChainFirst[E, A, B any](ma Either[E, A], f Kleisli[E, A, B]) Either[E, A]
- func MonadChainOptionK[A, B, E any](onNone func() E, ma Either[E, A], f func(A) Option[B]) Either[E, B]
- func MonadChainTo[A, E, B any](_ Either[E, A], mb Either[E, B]) Either[E, B]
- func MonadFlap[E, B, A any](fab Either[E, func(A) B], a A) Either[E, B]
- func MonadMap[E, A, B any](fa Either[E, A], f func(a A) B) Either[E, B]
- func MonadMapLeft[E1, A, E2 any](fa Either[E1, A], f func(E1) E2) Either[E2, A]
- func MonadMapTo[E, A, B any](fa Either[E, A], b B) Either[E, B]
- func MonadSequence2[E, T1, T2, R any](e1 Either[E, T1], e2 Either[E, T2], f func(T1, T2) Either[E, R]) Either[E, R]
- func MonadSequence3[E, T1, T2, T3, R any](e1 Either[E, T1], e2 Either[E, T2], e3 Either[E, T3], ...) Either[E, R]
- func Of[E, A any](value A) Either[E, A]
- func Right[E, A any](value A) Either[E, A]
- func SequenceArray[E, A any](ma []Either[E, A]) Either[E, []A]
- func SequenceArrayG[GA ~[]A, GOA ~[]Either[E, A], E, A any](ma GOA) Either[E, GA]
- func SequenceRecord[K comparable, E, A any](ma map[K]Either[E, A]) Either[E, map[K]A]
- func SequenceRecordG[GA ~map[K]A, GOA ~map[K]Either[E, A], K comparable, E, A any](ma GOA) Either[E, GA]
- func SequenceT1[E, T1 any](t1 Either[E, T1]) Either[E, T.Tuple1[T1]]
- func SequenceT10[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) Either[E, T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
- func SequenceT11[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) Either[E, T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]]
- func SequenceT12[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) Either[E, T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]]
- func SequenceT13[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) Either[E, T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]]
- func SequenceT14[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) ...
- func SequenceT15[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) ...
- func SequenceT2[E, T1, T2 any](t1 Either[E, T1], t2 Either[E, T2]) Either[E, T.Tuple2[T1, T2]]
- func SequenceT3[E, T1, T2, T3 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3]) Either[E, T.Tuple3[T1, T2, T3]]
- func SequenceT4[E, T1, T2, T3, T4 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4]) Either[E, T.Tuple4[T1, T2, T3, T4]]
- func SequenceT5[E, T1, T2, T3, T4, T5 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) Either[E, T.Tuple5[T1, T2, T3, T4, T5]]
- func SequenceT6[E, T1, T2, T3, T4, T5, T6 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) Either[E, T.Tuple6[T1, T2, T3, T4, T5, T6]]
- func SequenceT7[E, T1, T2, T3, T4, T5, T6, T7 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) Either[E, T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
- func SequenceT8[E, T1, T2, T3, T4, T5, T6, T7, T8 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) Either[E, T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
- func SequenceT9[E, T1, T2, T3, T4, T5, T6, T7, T8, T9 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], ...) Either[E, T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
- func SequenceTuple1[E, T1 any](t T.Tuple1[Either[E, T1]]) Either[E, T.Tuple1[T1]]
- func SequenceTuple10[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](...) Either[E, T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
- func SequenceTuple11[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](...) Either[E, T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]]
- func SequenceTuple12[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](...) Either[E, T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]]
- func SequenceTuple13[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](...) Either[E, T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]]
- func SequenceTuple14[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](...) ...
- func SequenceTuple15[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](...) ...
- func SequenceTuple2[E, T1, T2 any](t T.Tuple2[Either[E, T1], Either[E, T2]]) Either[E, T.Tuple2[T1, T2]]
- func SequenceTuple3[E, T1, T2, T3 any](t T.Tuple3[Either[E, T1], Either[E, T2], Either[E, T3]]) Either[E, T.Tuple3[T1, T2, T3]]
- func SequenceTuple4[E, T1, T2, T3, T4 any](t T.Tuple4[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4]]) Either[E, T.Tuple4[T1, T2, T3, T4]]
- func SequenceTuple5[E, T1, T2, T3, T4, T5 any](...) Either[E, T.Tuple5[T1, T2, T3, T4, T5]]
- func SequenceTuple6[E, T1, T2, T3, T4, T5, T6 any](...) Either[E, T.Tuple6[T1, T2, T3, T4, T5, T6]]
- func SequenceTuple7[E, T1, T2, T3, T4, T5, T6, T7 any](...) Either[E, T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
- func SequenceTuple8[E, T1, T2, T3, T4, T5, T6, T7, T8 any](...) Either[E, T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
- func SequenceTuple9[E, T1, T2, T3, T4, T5, T6, T7, T8, T9 any](...) Either[E, T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
- func Swap[E, A any](val Either[E, A]) Either[A, E]
- func TryCatch[FE func(error) E, E, A any](val A, err error, onThrow FE) Either[E, A]
- func TryCatchError[A any](val A, err error) Either[error, A]
- type Endomorphism
- func ApSL[E, S, T any](lens Lens[S, T], fa Either[E, T]) Endomorphism[Either[E, S]]
- func BindL[E, S, T any](lens Lens[S, T], f Kleisli[E, T, T]) Endomorphism[Either[E, S]]
- func LetL[E, S, T any](lens Lens[S, T], f Endomorphism[T]) Endomorphism[Either[E, S]]
- func LetToL[E, S, T any](lens Lens[S, T], b T) Endomorphism[Either[E, S]]
- type Kleisli
- func TailRec[E, A, B any](f Kleisli[E, A, tailrec.Trampoline[A, B]]) Kleisli[E, A, B]
- func TraverseArray[E, A, B any](f Kleisli[E, A, B]) Kleisli[E, []A, []B]
- func TraverseArrayG[GA ~[]A, GB ~[]B, E, A, B any](f Kleisli[E, A, B]) Kleisli[E, GA, GB]
- func TraverseArrayWithIndex[E, A, B any](f func(int, A) Either[E, B]) Kleisli[E, []A, []B]
- func TraverseArrayWithIndexG[GA ~[]A, GB ~[]B, E, A, B any](f func(int, A) Either[E, B]) Kleisli[E, GA, GB]
- func TraverseRecord[K comparable, E, A, B any](f Kleisli[E, A, B]) Kleisli[E, map[K]A, map[K]B]
- func TraverseRecordG[GA ~map[K]A, GB ~map[K]B, K comparable, E, A, B any](f Kleisli[E, A, B]) Kleisli[E, GA, GB]
- func TraverseRecordWithIndex[K comparable, E, A, B any](f func(K, A) Either[E, B]) Kleisli[E, map[K]A, map[K]B]
- func TraverseRecordWithIndexG[GA ~map[K]A, GB ~map[K]B, K comparable, E, A, B any](f func(K, A) Either[E, B]) Kleisli[E, GA, GB]
- func WithResource[A, E, R, ANY any](onCreate func() Either[E, R], onRelease Kleisli[E, R, ANY]) Kleisli[E, Kleisli[E, R, A], A]
- type Lazy
- type Lens
- type Monoid
- type Operator
- func Alt[E, A any](that Lazy[Either[E, A]]) Operator[E, A, A]
- func Ap[B, E, A any](fa Either[E, A]) Operator[E, func(A) B, B]
- func ApS[E, S1, S2, T any](setter func(T) func(S1) S2, fa Either[E, T]) Operator[E, S1, S2]
- func Bind[E, S1, S2, T any](setter func(T) func(S1) S2, f Kleisli[E, S1, T]) Operator[E, S1, S2]
- func BindTo[E, S1, T any](setter func(T) S1) Operator[E, T, S1]
- func Chain[E, A, B any](f Kleisli[E, A, B]) Operator[E, A, B]
- func ChainFirst[E, A, B any](f Kleisli[E, A, B]) Operator[E, A, A]
- func ChainTo[A, E, B any](mb Either[E, B]) Operator[E, A, B]
- func Flap[E, B, A any](a A) Operator[E, func(A) B, B]
- func Let[E, S1, S2, T any](key func(T) func(S1) S2, f func(S1) T) Operator[E, S1, S2]
- func LetTo[E, S1, S2, T any](key func(T) func(S1) S2, b T) Operator[E, S1, S2]
- func Map[E, A, B any](f func(a A) B) Operator[E, A, B]
- func MapTo[E, A, B any](b B) Operator[E, A, B]
- func OrElse[E, A any](onLeft Kleisli[E, E, A]) Operator[E, A, A]
- type Option
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AltSemigroup ¶
AltSemigroup creates a semigroup for Either that uses the Alt operation for combining values. When combining two Either values, it returns the first Right value, or the second value if the first is Left.
Example:
sg := either.AltSemigroup[error, int]()
result := sg.Concat(either.Left[int](errors.New("error")), either.Right[error](42))
// result is Right(42)
result2 := sg.Concat(either.Right[error](1), either.Right[error](2))
// result2 is Right(1) - first Right wins
func AltW ¶
AltW provides an alternative Either if the first is Left, allowing different error types. The 'W' suffix indicates "widening" of the error type.
Example:
alternative := either.AltW[error, string](func() either.Either[string, int] {
return either.Right[string](99)
})
result := alternative(either.Left[int](errors.New("fail"))) // Right(99)
func ApV ¶
ApV is the curried version of MonadApV that combines errors using a semigroup.
This function provides a more convenient API for validation scenarios by currying the arguments. It first takes the value to validate, then returns a function that takes the validation function. This allows for a more natural composition style.
Like MonadApV, this accumulates all errors using the provided semigroup instead of short-circuiting on the first error. This is the key difference from the standard Ap function.
Type Parameters:
- B: The result type after applying the function
- E: The error type (must support the semigroup operation)
- A: The input type to the function
Parameters:
- sg: A semigroup that defines how to combine two error values
Returns:
- A function that takes a value Either[E, A] and returns an Operator that applies validation functions while accumulating errors
Example:
// Define a semigroup for combining validation errors
type ValidationError struct {
Errors []string
}
errorSemigroup := semigroup.MakeSemigroup(func(e1, e2 ValidationError) ValidationError {
return ValidationError{Errors: append(e1.Errors, e2.Errors...)}
})
// Create validators
validatePositive := func(x int) either.Either[ValidationError, int] {
if x > 0 {
return either.Right[ValidationError](x)
}
return either.Left[int](ValidationError{Errors: []string{"must be positive"}})
}
// Use ApV for validation
applyValidation := either.ApV[int](errorSemigroup)
value := either.Left[int](ValidationError{Errors: []string{"invalid input"}})
validator := either.Left[func(int) int](ValidationError{Errors: []string{"invalid validator"}})
result := applyValidation(value)(validator)
// Left(ValidationError{Errors: []string{"invalid validator", "invalid input"}})
func Applicative ¶
func Applicative[E, A, B any]() applicative.Applicative[A, B, Either[E, A], Either[E, B], Either[E, func(A) B]]
Applicative creates a standard Applicative instance for Either with fail-fast error handling.
This returns a lawful Applicative that satisfies all applicative laws:
- Identity: Ap(Of(identity))(v) == v
- Homomorphism: Ap(Of(f))(Of(x)) == Of(f(x))
- Interchange: Ap(Of(f))(u) == Ap(Map(f => f(y))(u))(Of(y))
- Composition: Ap(Ap(Map(compose)(f))(g))(x) == Ap(f)(Ap(g)(x))
The Applicative operations behave as follows:
- Of: lifts a value into Right
- Map: transforms Right values, preserves Left (standard functor)
- Ap: fails fast - if either operand is Left, returns the first Left encountered
This is the standard Either applicative that stops at the first error, making it suitable for computations where you want to short-circuit on failure.
Example - Fail-Fast Behavior:
app := either.Applicative[error, int, string]()
// Both succeed - function application works
value := either.Right[error](42)
fn := either.Right[error](strconv.Itoa)
result := app.Ap(value)(fn)
// result is Right("42")
// First error stops computation
err1 := either.Left[func(int) string](errors.New("error 1"))
err2 := either.Left[int](errors.New("error 2"))
result2 := app.Ap(err2)(err1)
// result2 is Left(error 1) - only first error is returned
Type Parameters:
- E: The error type (Left value)
- A: The input value type (Right value)
- B: The output value type after transformation
func ApplicativeMonoid ¶
ApplicativeMonoid returns a Monoid that concatenates Either instances via their applicative. Provides an empty Either (Right with monoid's empty value) and combines Right values using the monoid.
Example:
intAddMonoid := monoid.MakeMonoid(0, func(a, b int) int { return a + b })
eitherMon := either.ApplicativeMonoid[error](intAddMonoid)
empty := eitherMon.Empty() // Right(0)
func ApplicativeV ¶
func ApplicativeV[E, A, B any](sg S.Semigroup[E]) applicative.Applicative[A, B, Either[E, A], Either[E, B], Either[E, func(A) B]]
ApplicativeV creates an Applicative with validation-style error accumulation.
This returns a lawful Applicative that accumulates errors using a Semigroup when combining independent computations with Ap. This is the "validation" pattern commonly used for form validation, configuration validation, and parallel error collection.
The returned instance satisfies all applicative laws:
- Identity: Ap(Of(identity))(v) == v
- Homomorphism: Ap(Of(f))(Of(x)) == Of(f(x))
- Interchange: Ap(Of(f))(u) == Ap(Map(f => f(y))(u))(Of(y))
- Composition: Ap(Ap(Map(compose)(f))(g))(x) == Ap(f)(Ap(g)(x))
Key behaviors:
- Of: lifts a value into Right
- Map: transforms Right values, preserves Left (standard functor)
- Ap: when both operands are Left, combines errors using the Semigroup
Comparison with standard Applicative:
- Applicative: Ap fails fast (returns first error)
- ApplicativeV: Ap accumulates errors (combines all errors via Semigroup)
Use cases:
- Form validation: collect all validation errors at once
- Configuration validation: report all configuration problems
- Parallel independent checks: accumulate all failures
Example - Error Accumulation for Form Validation:
type ValidationErrors []string
// Define how to combine error lists
sg := semigroup.MakeSemigroup(func(a, b ValidationErrors) ValidationErrors {
return append(append(ValidationErrors{}, a...), b...)
})
app := either.ApplicativeV[ValidationErrors, User, User](sg)
// Validate multiple fields independently
validateName := func(name string) Either[ValidationErrors, string] {
if len(name) < 3 {
return Left[string](ValidationErrors{"Name must be at least 3 characters"})
}
return Right[ValidationErrors](name)
}
validateAge := func(age int) Either[ValidationErrors, int] {
if age < 18 {
return Left[int](ValidationErrors{"Must be 18 or older"})
}
return Right[ValidationErrors](age)
}
validateEmail := func(email string) Either[ValidationErrors, string] {
if !strings.Contains(email, "@") {
return Left[string](ValidationErrors{"Invalid email format"})
}
return Right[ValidationErrors](email)
}
// Create a constructor function lifted into Either
makeUser := func(name string) func(int) func(string) User {
return func(age int) func(string) User {
return func(email string) User {
return User{Name: name, Age: age, Email: email}
}
}
}
// Apply validations - all errors are collected
name := validateName("ab") // Left: name too short
age := validateAge(16) // Left: age too low
email := validateEmail("invalid") // Left: invalid email
// Combine all validations using ApV
result := app.Ap(name)(
app.Ap(age)(
app.Ap(email)(
app.Of(makeUser),
),
),
)
// result is Left(ValidationErrors{
// "Name must be at least 3 characters",
// "Must be 18 or older",
// "Invalid email format"
// })
// All three errors are collected!
Type Parameters:
- E: The error type that must have a Semigroup for combining errors
- A: The input value type (Right value)
- B: The output value type after transformation
- sg: Semigroup instance for combining Left values when both operands of Ap are Left
func ApplySemigroup ¶
ApplySemigroup lifts a Semigroup over the Right values of Either. Combines two Right values using the provided Semigroup. If either value is Left, returns the first Left encountered.
Example:
intAdd := semigroup.MakeSemigroup(func(a, b int) int { return a + b })
eitherSemi := either.ApplySemigroup[error](intAdd)
result := eitherSemi.Concat(either.Right[error](2), either.Right[error](3)) // Right(5)
func BiMap ¶
BiMap is the curried version of MonadBiMap. Maps a pair of functions over the two type arguments of the bifunctor.
func ChainOptionK ¶
ChainOptionK is the curried version of MonadChainOptionK.
func CompactArray ¶
CompactArray discards all Left values and keeps only the Right values.
Example:
eithers := []either.Either[error, int]{
either.Right[error](1),
either.Left[int](errors.New("error")),
either.Right[error](3),
}
result := either.CompactArray(eithers)
// result is []int{1, 3}
func CompactArrayG ¶
CompactArrayG discards all Left values and keeps only the Right values. The G suffix indicates support for generic slice types.
Example:
eithers := []either.Either[error, int]{
either.Right[error](1),
either.Left[int](errors.New("error")),
either.Right[error](3),
}
result := either.CompactArrayG[[]either.Either[error, int], []int](eithers)
// result is []int{1, 3}
func CompactRecord ¶
func CompactRecord[K comparable, E, A any](m map[K]Either[E, A]) map[K]A
CompactRecord discards all Left values and keeps only the Right values.
Example:
eithers := map[string]either.Either[error, int]{
"a": either.Right[error](1),
"b": either.Left[int](errors.New("error")),
"c": either.Right[error](3),
}
result := either.CompactRecord(eithers)
// result is map[string]int{"a": 1, "c": 3}
func CompactRecordG ¶
func CompactRecordG[M1 ~map[K]Either[E, A], M2 ~map[K]A, K comparable, E, A any](m M1) M2
CompactRecordG discards all Left values and keeps only the Right values. The G suffix indicates support for generic map types.
Example:
eithers := map[string]either.Either[error, int]{
"a": either.Right[error](1),
"b": either.Left[int](errors.New("error")),
"c": either.Right[error](3),
}
result := either.CompactRecordG[map[string]either.Either[error, int], map[string]int](eithers)
// result is map[string]int{"a": 1, "c": 3}
func Curry0 ¶
Curry0 converts a Go function that returns (R, error) into a curried version that returns Either[error, R].
Example:
getConfig := func() (string, error) { return "config", nil }
curried := either.Curry0(getConfig)
result := curried() // Right("config")
func Curry1 ¶
Curry1 converts a Go function that returns (R, error) into a curried version that returns Either[error, R].
Example:
parse := strconv.Atoi
curried := either.Curry1(parse)
result := curried("42") // Right(42)
func Curry2 ¶
Curry2 converts a 2-argument Go function that returns (R, error) into a curried version.
Example:
divide := func(a, b int) (int, error) {
if b == 0 { return 0, errors.New("div by zero") }
return a / b, nil
}
curried := either.Curry2(divide)
result := curried(10)(2) // Right(5)
func Curry3 ¶
func Curry3[T1, T2, T3, R any](f func(T1, T2, T3) (R, error)) func(T1) func(T2) func(T3) Either[error, R]
Curry3 converts a 3-argument Go function that returns (R, error) into a curried version.
func Curry4 ¶
func Curry4[T1, T2, T3, T4, R any](f func(T1, T2, T3, T4) (R, error)) func(T1) func(T2) func(T3) func(T4) Either[error, R]
Curry4 converts a 4-argument Go function that returns (R, error) into a curried version.
func Eitherize0 ¶
Eitherize0 converts a function with 0 parameters returning a tuple into a function with 0 parameters returning an Either The inverse function is Uneitherize0
func Eitherize1 ¶
Eitherize1 converts a function with 1 parameters returning a tuple into a function with 1 parameters returning an Either The inverse function is Uneitherize1
func Eitherize10 ¶
func Eitherize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) Either[error, R]
Eitherize10 converts a function with 10 parameters returning a tuple into a function with 10 parameters returning an Either The inverse function is Uneitherize10
func Eitherize11 ¶
func Eitherize11[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) Either[error, R]
Eitherize11 converts a function with 11 parameters returning a tuple into a function with 11 parameters returning an Either The inverse function is Uneitherize11
func Eitherize12 ¶
func Eitherize12[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) Either[error, R]
Eitherize12 converts a function with 12 parameters returning a tuple into a function with 12 parameters returning an Either The inverse function is Uneitherize12
func Eitherize13 ¶
func Eitherize13[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) Either[error, R]
Eitherize13 converts a function with 13 parameters returning a tuple into a function with 13 parameters returning an Either The inverse function is Uneitherize13
func Eitherize14 ¶
func Eitherize14[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) Either[error, R]
Eitherize14 converts a function with 14 parameters returning a tuple into a function with 14 parameters returning an Either The inverse function is Uneitherize14
func Eitherize15 ¶
func Eitherize15[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) Either[error, R]
Eitherize15 converts a function with 15 parameters returning a tuple into a function with 15 parameters returning an Either The inverse function is Uneitherize15
func Eitherize2 ¶
Eitherize2 converts a function with 2 parameters returning a tuple into a function with 2 parameters returning an Either The inverse function is Uneitherize2
func Eitherize3 ¶
func Eitherize3[F ~func(T0, T1, T2) (R, error), T0, T1, T2, R any](f F) func(T0, T1, T2) Either[error, R]
Eitherize3 converts a function with 3 parameters returning a tuple into a function with 3 parameters returning an Either The inverse function is Uneitherize3
func Eitherize4 ¶
func Eitherize4[F ~func(T0, T1, T2, T3) (R, error), T0, T1, T2, T3, R any](f F) func(T0, T1, T2, T3) Either[error, R]
Eitherize4 converts a function with 4 parameters returning a tuple into a function with 4 parameters returning an Either The inverse function is Uneitherize4
func Eitherize5 ¶
func Eitherize5[F ~func(T0, T1, T2, T3, T4) (R, error), T0, T1, T2, T3, T4, R any](f F) func(T0, T1, T2, T3, T4) Either[error, R]
Eitherize5 converts a function with 5 parameters returning a tuple into a function with 5 parameters returning an Either The inverse function is Uneitherize5
func Eitherize6 ¶
func Eitherize6[F ~func(T0, T1, T2, T3, T4, T5) (R, error), T0, T1, T2, T3, T4, T5, R any](f F) func(T0, T1, T2, T3, T4, T5) Either[error, R]
Eitherize6 converts a function with 6 parameters returning a tuple into a function with 6 parameters returning an Either The inverse function is Uneitherize6
func Eitherize7 ¶
func Eitherize7[F ~func(T0, T1, T2, T3, T4, T5, T6) (R, error), T0, T1, T2, T3, T4, T5, T6, R any](f F) func(T0, T1, T2, T3, T4, T5, T6) Either[error, R]
Eitherize7 converts a function with 7 parameters returning a tuple into a function with 7 parameters returning an Either The inverse function is Uneitherize7
func Eitherize8 ¶
func Eitherize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) Either[error, R]
Eitherize8 converts a function with 8 parameters returning a tuple into a function with 8 parameters returning an Either The inverse function is Uneitherize8
func Eitherize9 ¶
func Eitherize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) Either[error, R]
Eitherize9 converts a function with 9 parameters returning a tuple into a function with 9 parameters returning an Either The inverse function is Uneitherize9
func Eq ¶
Eq constructs an equality predicate for Either values. Two Either values are equal if they are both Left with equal error values, or both Right with equal success values.
Parameters:
- e: Equality predicate for the Left (error) type
- a: Equality predicate for the Right (success) type
Example:
eq := either.Eq(eq.FromStrictEquals[error](), eq.FromStrictEquals[int]()) result := eq.Equals(either.Right[error](42), either.Right[error](42)) // true result2 := eq.Equals(either.Right[error](42), either.Right[error](43)) // false
func Fold ¶
Fold is the curried version of MonadFold. Extracts the value from an Either by providing handlers for both cases.
Example:
result := either.Fold(
func(err error) string { return "Error: " + err.Error() },
func(n int) string { return fmt.Sprintf("Value: %d", n) },
)(either.Right[error](42)) // "Value: 42"
func FromError ¶
FromError creates an Either from a function that may return an error.
Example:
validate := func(x int) error {
if x < 0 { return errors.New("negative") }
return nil
}
toEither := either.FromError(validate)
result := toEither(42) // Right(42)
func FromNillable ¶
FromNillable creates an Either from a pointer, using the provided error for nil pointers.
Example:
var ptr *int = nil
result := either.FromNillable[int](errors.New("nil"))(ptr) // Left(error)
val := 42
result := either.FromNillable[int](errors.New("nil"))(&val) // Right(&42)
func FromOption ¶
FromOption converts an Option to an Either, using the provided function to generate a Left value for None.
Example:
opt := option.Some(42)
result := either.FromOption[int](func() error { return errors.New("none") })(opt) // Right(42)
func FromPredicate ¶
FromPredicate creates an Either based on a predicate. If the predicate returns true, creates a Right; otherwise creates a Left using onFalse.
Example:
isPositive := either.FromPredicate(
func(x int) bool { return x > 0 },
func(x int) error { return errors.New("not positive") },
)
result := isPositive(42) // Right(42)
result := isPositive(-1) // Left(error)
func FromStrictEquals ¶
func FromStrictEquals[E, A comparable]() EQ.Eq[Either[E, A]]
FromStrictEquals constructs an equality predicate using Go's == operator. Both the Left and Right types must be comparable.
Example:
eq := either.FromStrictEquals[error, int]() result := eq.Equals(either.Right[error](42), either.Right[error](42)) // true
func Functor ¶
Functor implements the functoric operations for Either. A functor provides the Map operation that transforms values inside a context while preserving the structure.
Example:
f := either.Functor[error, int, string]()
result := f.Map(strconv.Itoa)(either.Right[error](42))
// result is Right("42")
func GetOrElse ¶
GetOrElse extracts the Right value or computes a default from the Left value.
Example:
result := either.GetOrElse(func(err error) int { return 0 })(either.Right[error](42)) // 42
result := either.GetOrElse(func(err error) int { return 0 })(either.Left[int](err)) // 0
func IsLeft ¶
IsLeft tests if the Either is a Left value. Rather use Fold or MonadFold if you need to access the values. Inverse is IsRight.
Example:
either.IsLeft(either.Left[int](errors.New("err"))) // true
either.IsLeft(either.Right[error](42)) // false
func IsRight ¶
IsRight tests if the Either is a Right value. Rather use Fold or MonadFold if you need to access the values. Inverse is IsLeft.
Example:
either.IsRight(either.Right[error](42)) // true
either.IsRight(either.Left[int](errors.New("err"))) // false
func Logger ¶
Logger creates a logging function for Either values that logs both Left and Right cases. The function logs the value and then returns the original Either unchanged.
Parameters:
- loggers: Optional log.Logger instances. If none provided, uses default logger.
Example:
logger := either.Logger[error, int]()
result := F.Pipe2(
either.Right[error](42),
logger("Processing"),
either.Map(N.Mul(2)),
)
// Logs: "Processing: 42"
// result is Right(84)
func MapLeft ¶
MapLeft is the curried version of MonadMapLeft. Applies a mapping function to the Left (error) channel.
func Monad ¶
Monad creates a lawful Monad instance for Either with fail-fast error handling.
A monad combines the capabilities of four type classes:
- Functor (Map): transform the Right value
- Pointed (Of): lift a pure value into a Right
- Applicative (Ap): apply wrapped functions (fails fast on first Left)
- Chainable (Chain): sequence dependent computations (fails fast on first Left)
The Either monad is left-biased and fails fast: once a Left is encountered, no further computations are performed and the Left is propagated immediately. This makes it ideal for error handling where you want to stop at the first error.
This implementation satisfies all monad laws:
Monad Laws:
- Left Identity: Chain(f)(Of(a)) == f(a)
- Right Identity: Chain(Of)(m) == m
- Associativity: Chain(g)(Chain(f)(m)) == Chain(x => Chain(g)(f(x)))(m)
Additionally, it satisfies all prerequisite laws from Functor, Apply, and Applicative.
Relationship to Applicative:
This Monad uses the standard fail-fast Applicative (see Applicative function). In a lawful monad, Ap can be derived from Chain and Of:
Ap(fa)(ff) == Chain(f => Chain(a => Of(f(a)))(fa))(ff)
The Either monad satisfies this property, making it a true lawful monad.
When to use Monad vs Applicative:
- Use Monad when you need sequential dependent operations (Chain)
- Use Applicative when you only need independent operations (Ap, Map)
- Both fail fast on the first error
When to use Monad vs ApplicativeV:
- Use Monad for sequential error handling (fail-fast)
- Use ApplicativeV for parallel validation (error accumulation)
- Note: There is no "MonadV" because Chain inherently fails fast
Example - Sequential Dependent Operations:
m := either.Monad[error, int, string]()
// Chain allows each step to depend on the previous result
result := m.Chain(func(x int) either.Either[error, string] {
if x > 0 {
return either.Right[error](strconv.Itoa(x))
}
return either.Left[string](errors.New("value must be positive"))
})(either.Right[error](42))
// result is Right("42")
// Fails fast on first error
result2 := m.Chain(func(x int) either.Either[error, string] {
return either.Right[error](strconv.Itoa(x))
})(either.Left[int](errors.New("initial error")))
// result2 is Left("initial error") - Chain never executes
Example - Combining with Applicative operations:
m := either.Monad[error, int, int]() // Map transforms the value value := m.Map(N.Mul(2))(either.Right[error](21)) // value is Right(42) // Ap applies wrapped functions (also fails fast) fn := either.Right[error](N.Add(1)) result := m.Ap(value)(fn) // result is Right(43)
Example - Real-world usage with error handling:
m := either.Monad[error, User, SavedUser]()
// Pipeline of operations that can fail
result := m.Chain(func(user User) either.Either[error, SavedUser] {
// Save to database
return saveToDatabase(user)
})(m.Chain(func(user User) either.Either[error, User] {
// Validate user
return validateUser(user)
})(either.Right[error](inputUser)))
// If any step fails, the error propagates immediately
Type Parameters:
- E: The error type (Left value)
- A: The input value type (Right value)
- B: The output value type after transformation
func MonadApV ¶
func MonadApV[B, A, E any](sg S.Semigroup[E]) func(fab Either[E, func(a A) B], fa Either[E, A]) Either[E, B]
MonadApV is the applicative validation functor that combines errors using a semigroup.
Unlike the standard MonadAp which short-circuits on the first Left (error), MonadApV accumulates all errors using the provided semigroup's Concat operation. This is particularly useful for validation scenarios where you want to collect all validation errors rather than stopping at the first one.
The function takes a semigroup for combining errors and returns a function that applies a wrapped function to a wrapped value, accumulating errors if both are Left.
Behavior:
- If both fab and fa are Left, combines their errors using sg.Concat
- If only fab is Left, returns Left with fab's error
- If only fa is Left, returns Left with fa's error
- If both are Right, applies the function and returns Right with the result
Type Parameters:
- B: The result type after applying the function
- E: The error type (must support the semigroup operation)
- A: The input type to the function
Parameters:
- sg: A semigroup that defines how to combine two error values
Returns:
- A function that takes a wrapped function and a wrapped value, returning Either[E, B] with accumulated errors or the computed result
Example:
// Define a semigroup that concatenates error messages
errorSemigroup := semigroup.MakeSemigroup(func(e1, e2 string) string {
return e1 + "; " + e2
})
// Create the validation applicative
applyV := either.MonadApV[int](errorSemigroup)
// Both are errors - errors get combined
fab := either.Left[func(int) int]("error1")
fa := either.Left[int]("error2")
result := applyV(fab, fa) // Left("error1; error2")
// One error - returns that error
fab2 := either.Right[string](N.Mul(2))
fa2 := either.Left[int]("validation failed")
result2 := applyV(fab2, fa2) // Left("validation failed")
// Both success - applies function
fab3 := either.Right[string](N.Mul(2))
fa3 := either.Right[string](21)
result3 := applyV(fab3, fa3) // Right(42)
func MonadFold ¶
MonadFold extracts the value from an Either by providing handlers for both cases. This is the fundamental pattern matching operation for Either.
Example:
result := either.MonadFold(
either.Right[error](42),
func(err error) string { return "Error: " + err.Error() },
func(n int) string { return fmt.Sprintf("Value: %d", n) },
) // "Value: 42"
func Pointed ¶
Pointed implements the pointed functor operations for Either. A pointed functor provides the Of operation to lift a value into the Either context.
Example:
p := either.Pointed[error, int]() result := p.Of(42) // Right(42)
func Reduce ¶
Reduce folds an Either into a single value using a reducer function. Returns the initial value for Left, or applies the reducer to the Right value.
func Sequence ¶
func Sequence[E, A, HKTA, HKTRA any]( mof func(Either[E, A]) HKTRA, mmap func(Kleisli[E, A, A]) func(HKTA) HKTRA, ) func(Either[E, HKTA]) HKTRA
Sequence converts an Either of some higher kinded type into the higher kinded type of an Either. This is the identity version of Traverse - it doesn't transform the values, just swaps the type constructors.
Parameters:
- mof: Lifts an Either into the target higher-kinded type
- mmap: Maps over the target higher-kinded type
Example (conceptual - requires understanding of higher-kinded types):
// Sequence an Either[error, Option[int]] to Option[Either[error, int]]
result := either.Sequence[error, int, option.Option[int], option.Option[either.Either[error, int]]](
option.Of[either.Either[error, int]],
option.Map[int, either.Either[error, int]],
)(eitherOfOption)
func Sequence2 ¶
func Sequence2[E, T1, T2, R any](f func(T1, T2) Either[E, R]) func(Either[E, T1], Either[E, T2]) Either[E, R]
Sequence2 sequences two Either values using a combining function. Short-circuits on the first Left encountered.
func Sequence3 ¶
func Sequence3[E, T1, T2, T3, R any](f func(T1, T2, T3) Either[E, R]) func(Either[E, T1], Either[E, T2], Either[E, T3]) Either[E, R]
Sequence3 sequences three Either values using a combining function. Short-circuits on the first Left encountered.
func ToError ¶
ToError converts an Either[error, A] to an error, returning nil for Right values.
Example:
err := either.ToError(either.Left[int](errors.New("fail"))) // error
err := either.ToError(either.Right[error](42)) // nil
func ToSLogAttr ¶
ToSLogAttr converts an Either value to a structured logging attribute (slog.Attr).
This function creates a converter that transforms Either values into slog.Attr for use with Go's structured logging (log/slog). It maps:
- Left values to an "error" attribute
- Right values to a "value" attribute
This is particularly useful when integrating Either-based error handling with structured logging systems, allowing you to log both successful values and errors in a consistent, structured format.
Type Parameters:
- E: The Left (error) type of the Either
- A: The Right (success) type of the Either
Returns:
- A function that converts Either[E, A] to slog.Attr
Example with Left (error):
converter := either.ToSLogAttr[error, int]()
leftValue := either.Left[int](errors.New("connection failed"))
attr := converter(leftValue)
// attr is: slog.Any("error", errors.New("connection failed"))
logger.LogAttrs(ctx, slog.LevelError, "Operation failed", attr)
// Logs: {"level":"error","msg":"Operation failed","error":"connection failed"}
Example with Right (success):
converter := either.ToSLogAttr[error, User]()
rightValue := either.Right[error](User{ID: 123, Name: "Alice"})
attr := converter(rightValue)
// attr is: slog.Any("value", User{ID: 123, Name: "Alice"})
logger.LogAttrs(ctx, slog.LevelInfo, "User fetched", attr)
// Logs: {"level":"info","msg":"User fetched","value":{"ID":123,"Name":"Alice"}}
Example in a pipeline with structured logging:
toAttr := either.ToSLogAttr[error, Data]()
result := F.Pipe2(
fetchData(id),
either.Map(processData),
either.Map(validateData),
)
attr := toAttr(result)
logger.LogAttrs(ctx, slog.LevelInfo, "Data processing complete", attr)
// Logs success: {"level":"info","msg":"Data processing complete","value":{...}}
// Or error: {"level":"info","msg":"Data processing complete","error":"validation failed"}
Example with custom log levels based on Either:
toAttr := either.ToSLogAttr[error, Response]()
result := callAPI(endpoint)
level := either.Fold(
func(error) slog.Level { return slog.LevelError },
func(Response) slog.Level { return slog.LevelInfo },
)(result)
logger.LogAttrs(ctx, level, "API call completed", toAttr(result))
Use Cases:
- Structured logging: Convert Either results to structured log attributes
- Error tracking: Log errors with consistent "error" key in structured logs
- Success monitoring: Log successful values with consistent "value" key
- Observability: Integrate Either-based error handling with logging systems
- Debugging: Inspect Either values in logs with proper structure
- Metrics: Extract Either values for metrics collection in logging pipelines
Note: The returned slog.Attr uses "error" for Left values and "value" for Right values. These keys are consistent with common structured logging conventions.
func ToType ¶
ToType attempts to convert an any value to a specific type, returning Either.
Example:
convert := either.ToType[int](func(v any) error {
return fmt.Errorf("cannot convert %v to int", v)
})
result := convert(42) // Right(42)
result := convert("string") // Left(error)
func Traverse ¶
func Traverse[A, E, B, HKTB, HKTRB any]( mof func(Either[E, B]) HKTRB, mmap func(Kleisli[E, B, B]) func(HKTB) HKTRB, ) func(func(A) HKTB) func(Either[E, A]) HKTRB
Traverse converts an Either of some higher kinded type into the higher kinded type of an Either. This is a generic traversal operation that works with any applicative functor.
Parameters:
- mof: Lifts an Either into the target higher-kinded type
- mmap: Maps over the target higher-kinded type
Example (conceptual - requires understanding of higher-kinded types):
// Traverse an Either[error, Option[int]] to Option[Either[error, int]]
result := either.Traverse[int, error, int, option.Option[int], option.Option[either.Either[error, int]]](
option.Of[either.Either[error, int]],
option.Map[int, either.Either[error, int]],
)(f)(eitherOfOption)
func TraverseTuple1 ¶
func TraverseTuple1[F1 ~func(A1) Either[E, T1], E, A1, T1 any](f1 F1) func(T.Tuple1[A1]) Either[E, T.Tuple1[T1]]
TraverseTuple1 converts a [Tuple1] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple1]].
func TraverseTuple10 ¶
func TraverseTuple10[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10) func(T.Tuple10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10]) Either[E, T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
TraverseTuple10 converts a [Tuple10] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple10]].
func TraverseTuple11 ¶
func TraverseTuple11[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], F11 ~func(A11) Either[E, T11], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10, A11, T11 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11) func(T.Tuple11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11]) Either[E, T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]]
TraverseTuple11 converts a [Tuple11] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple11]].
func TraverseTuple12 ¶
func TraverseTuple12[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], F11 ~func(A11) Either[E, T11], F12 ~func(A12) Either[E, T12], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10, A11, T11, A12, T12 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12) func(T.Tuple12[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12]) Either[E, T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]]
TraverseTuple12 converts a [Tuple12] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple12]].
func TraverseTuple13 ¶
func TraverseTuple13[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], F11 ~func(A11) Either[E, T11], F12 ~func(A12) Either[E, T12], F13 ~func(A13) Either[E, T13], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10, A11, T11, A12, T12, A13, T13 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13) func(T.Tuple13[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13]) Either[E, T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]]
TraverseTuple13 converts a [Tuple13] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple13]].
func TraverseTuple14 ¶
func TraverseTuple14[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], F11 ~func(A11) Either[E, T11], F12 ~func(A12) Either[E, T12], F13 ~func(A13) Either[E, T13], F14 ~func(A14) Either[E, T14], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10, A11, T11, A12, T12, A13, T13, A14, T14 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14) func(T.Tuple14[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14]) Either[E, T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]]
TraverseTuple14 converts a [Tuple14] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple14]].
func TraverseTuple15 ¶
func TraverseTuple15[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], F11 ~func(A11) Either[E, T11], F12 ~func(A12) Either[E, T12], F13 ~func(A13) Either[E, T13], F14 ~func(A14) Either[E, T14], F15 ~func(A15) Either[E, T15], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10, A11, T11, A12, T12, A13, T13, A14, T14, A15, T15 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15) func(T.Tuple15[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15]) Either[E, T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]]
TraverseTuple15 converts a [Tuple15] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple15]].
func TraverseTuple2 ¶
func TraverseTuple2[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], E, A1, T1, A2, T2 any](f1 F1, f2 F2) func(T.Tuple2[A1, A2]) Either[E, T.Tuple2[T1, T2]]
TraverseTuple2 converts a [Tuple2] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple2]].
func TraverseTuple3 ¶
func TraverseTuple3[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], E, A1, T1, A2, T2, A3, T3 any](f1 F1, f2 F2, f3 F3) func(T.Tuple3[A1, A2, A3]) Either[E, T.Tuple3[T1, T2, T3]]
TraverseTuple3 converts a [Tuple3] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple3]].
func TraverseTuple4 ¶
func TraverseTuple4[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], E, A1, T1, A2, T2, A3, T3, A4, T4 any](f1 F1, f2 F2, f3 F3, f4 F4) func(T.Tuple4[A1, A2, A3, A4]) Either[E, T.Tuple4[T1, T2, T3, T4]]
TraverseTuple4 converts a [Tuple4] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple4]].
func TraverseTuple5 ¶
func TraverseTuple5[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(T.Tuple5[A1, A2, A3, A4, A5]) Either[E, T.Tuple5[T1, T2, T3, T4, T5]]
TraverseTuple5 converts a [Tuple5] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple5]].
func TraverseTuple6 ¶
func TraverseTuple6[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6) func(T.Tuple6[A1, A2, A3, A4, A5, A6]) Either[E, T.Tuple6[T1, T2, T3, T4, T5, T6]]
TraverseTuple6 converts a [Tuple6] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple6]].
func TraverseTuple7 ¶
func TraverseTuple7[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7) func(T.Tuple7[A1, A2, A3, A4, A5, A6, A7]) Either[E, T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
TraverseTuple7 converts a [Tuple7] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple7]].
func TraverseTuple8 ¶
func TraverseTuple8[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8) func(T.Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]) Either[E, T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
TraverseTuple8 converts a [Tuple8] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple8]].
func TraverseTuple9 ¶
func TraverseTuple9[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9) func(T.Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]) Either[E, T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
TraverseTuple9 converts a [Tuple9] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple9]].
func Uncurry0 ¶
Uncurry0 converts a function returning Either[error, R] back to Go's (R, error) style.
Example:
curried := func() either.Either[error, string] { return either.Right[error]("value") }
uncurried := either.Uncurry0(curried)
result, err := uncurried() // "value", nil
func Uncurry1 ¶
Uncurry1 converts a function returning Either[error, R] back to Go's (R, error) style.
Example:
curried := func(x int) either.Either[error, string] { return either.Right[error](strconv.Itoa(x)) }
uncurried := either.Uncurry1(curried)
result, err := uncurried(42) // "42", nil
func Uncurry2 ¶
Uncurry2 converts a curried function returning Either[error, R] back to Go's (R, error) style.
func Uncurry3 ¶
func Uncurry3[T1, T2, T3, R any](f func(T1) func(T2) func(T3) Either[error, R]) func(T1, T2, T3) (R, error)
Uncurry3 converts a curried function returning Either[error, R] back to Go's (R, error) style.
func Uncurry4 ¶
func Uncurry4[T1, T2, T3, T4, R any](f func(T1) func(T2) func(T3) func(T4) Either[error, R]) func(T1, T2, T3, T4) (R, error)
Uncurry4 converts a curried function returning Either[error, R] back to Go's (R, error) style.
func Uneitherize0 ¶
Uneitherize0 converts a function with 0 parameters returning an Either into a function with 0 parameters returning a tuple The inverse function is Eitherize0
func Uneitherize1 ¶
Uneitherize1 converts a function with 1 parameters returning an Either into a function with 1 parameters returning a tuple The inverse function is Eitherize1
func Uneitherize10 ¶
func Uneitherize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error)
Uneitherize10 converts a function with 10 parameters returning an Either into a function with 10 parameters returning a tuple The inverse function is Eitherize10
func Uneitherize11 ¶
func Uneitherize11[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) (R, error)
Uneitherize11 converts a function with 11 parameters returning an Either into a function with 11 parameters returning a tuple The inverse function is Eitherize11
func Uneitherize12 ¶
func Uneitherize12[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) (R, error)
Uneitherize12 converts a function with 12 parameters returning an Either into a function with 12 parameters returning a tuple The inverse function is Eitherize12
func Uneitherize13 ¶
func Uneitherize13[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) (R, error)
Uneitherize13 converts a function with 13 parameters returning an Either into a function with 13 parameters returning a tuple The inverse function is Eitherize13
func Uneitherize14 ¶
func Uneitherize14[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) (R, error)
Uneitherize14 converts a function with 14 parameters returning an Either into a function with 14 parameters returning a tuple The inverse function is Eitherize14
func Uneitherize15 ¶
func Uneitherize15[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) (R, error)
Uneitherize15 converts a function with 15 parameters returning an Either into a function with 15 parameters returning a tuple The inverse function is Eitherize15
func Uneitherize2 ¶
Uneitherize2 converts a function with 2 parameters returning an Either into a function with 2 parameters returning a tuple The inverse function is Eitherize2
func Uneitherize3 ¶
func Uneitherize3[F ~func(T0, T1, T2) Either[error, R], T0, T1, T2, R any](f F) func(T0, T1, T2) (R, error)
Uneitherize3 converts a function with 3 parameters returning an Either into a function with 3 parameters returning a tuple The inverse function is Eitherize3
func Uneitherize4 ¶
func Uneitherize4[F ~func(T0, T1, T2, T3) Either[error, R], T0, T1, T2, T3, R any](f F) func(T0, T1, T2, T3) (R, error)
Uneitherize4 converts a function with 4 parameters returning an Either into a function with 4 parameters returning a tuple The inverse function is Eitherize4
func Uneitherize5 ¶
func Uneitherize5[F ~func(T0, T1, T2, T3, T4) Either[error, R], T0, T1, T2, T3, T4, R any](f F) func(T0, T1, T2, T3, T4) (R, error)
Uneitherize5 converts a function with 5 parameters returning an Either into a function with 5 parameters returning a tuple The inverse function is Eitherize5
func Uneitherize6 ¶
func Uneitherize6[F ~func(T0, T1, T2, T3, T4, T5) Either[error, R], T0, T1, T2, T3, T4, T5, R any](f F) func(T0, T1, T2, T3, T4, T5) (R, error)
Uneitherize6 converts a function with 6 parameters returning an Either into a function with 6 parameters returning a tuple The inverse function is Eitherize6
func Uneitherize7 ¶
func Uneitherize7[F ~func(T0, T1, T2, T3, T4, T5, T6) Either[error, R], T0, T1, T2, T3, T4, T5, T6, R any](f F) func(T0, T1, T2, T3, T4, T5, T6) (R, error)
Uneitherize7 converts a function with 7 parameters returning an Either into a function with 7 parameters returning a tuple The inverse function is Eitherize7
func Uneitherize8 ¶
func Uneitherize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) (R, error)
Uneitherize8 converts a function with 8 parameters returning an Either into a function with 8 parameters returning a tuple The inverse function is Eitherize8
func Uneitherize9 ¶
func Uneitherize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error)
Uneitherize9 converts a function with 9 parameters returning an Either into a function with 9 parameters returning a tuple The inverse function is Eitherize9
func Unvariadic0 ¶
Unvariadic0 converts a variadic function returning (R, error) into a function taking a slice and returning Either.
func Unvariadic1 ¶
Unvariadic1 converts a variadic function with 1 fixed parameter into a function taking a slice and returning Either.
func Unvariadic2 ¶
func Unvariadic2[T1, T2, V, R any](f func(T1, T2, ...V) (R, error)) func(T1, T2, []V) Either[error, R]
Unvariadic2 converts a variadic function with 2 fixed parameters into a function taking a slice and returning Either.
func Unvariadic3 ¶
func Unvariadic3[T1, T2, T3, V, R any](f func(T1, T2, T3, ...V) (R, error)) func(T1, T2, T3, []V) Either[error, R]
Unvariadic3 converts a variadic function with 3 fixed parameters into a function taking a slice and returning Either.
func Unvariadic4 ¶
func Unvariadic4[T1, T2, T3, T4, V, R any](f func(T1, T2, T3, T4, ...V) (R, error)) func(T1, T2, T3, T4, []V) Either[error, R]
Unvariadic4 converts a variadic function with 4 fixed parameters into a function taking a slice and returning Either.
func Unwrap ¶
Unwrap converts an Either into the idiomatic Go tuple (value, error). For Right values, returns (value, zero-error). For Left values, returns (zero-value, error).
Example:
val, err := either.Unwrap(either.Right[error](42)) // 42, nil
val, err := either.Unwrap(either.Left[int](errors.New("fail"))) // 0, error
func UnwrapError ¶
UnwrapError converts an Either[error, A] into the idiomatic Go tuple (A, error).
Example:
val, err := either.UnwrapError(either.Right[error](42)) // 42, nil
val, err := either.UnwrapError(either.Left[int](errors.New("fail"))) // zero, error
func Variadic0 ¶
Variadic0 converts a function taking a slice and returning (R, error) into a variadic function returning Either.
Example:
sum := func(nums []int) (int, error) {
total := 0
for _, n := range nums { total += n }
return total, nil
}
variadicSum := either.Variadic0(sum)
result := variadicSum(1, 2, 3) // Right(6)
func Variadic1 ¶
Variadic1 converts a function with 1 fixed parameter and a slice into a variadic function returning Either.
func Variadic2 ¶
func Variadic2[T1, T2, V, R any](f func(T1, T2, []V) (R, error)) func(T1, T2, ...V) Either[error, R]
Variadic2 converts a function with 2 fixed parameters and a slice into a variadic function returning Either.
Types ¶
type Either ¶
type Either[E, A any] struct { // contains filtered or unexported fields }
Either defines a data structure that logically holds either an E or an A. The flag discriminates the cases
Example (Creation) ¶
// Build an Either
leftValue := Left[string](fmt.Errorf("some error"))
rightValue := Right[error]("value")
// Build from a value
fromNillable := FromNillable[string](fmt.Errorf("value was nil"))
leftFromNil := fromNillable(nil)
value := "value"
rightFromPointer := fromNillable(&value)
// some predicate
isEven := func(num int) bool {
return num%2 == 0
}
fromEven := FromPredicate(isEven, errors.OnSome[int]("%d is an odd number"))
leftFromPred := fromEven(3)
rightFromPred := fromEven(4)
fmt.Println(leftValue)
fmt.Println(rightValue)
fmt.Println(leftFromNil)
fmt.Println(IsRight(rightFromPointer))
fmt.Println(leftFromPred)
fmt.Println(rightFromPred)
Output: Left[*errors.errorString](some error) Right[string](value) Left[*errors.errorString](value was nil) true Left[*errors.errorString](3 is an odd number) Right[int](4)
Example (Extraction) ¶
leftValue := Left[int](fmt.Errorf("Division by Zero!"))
rightValue := Right[error](10)
// Convert Either[E, A] to A with a default value
leftWithDefault := GetOrElse(F.Constant1[error](0))(leftValue) // 0
rightWithDefault := GetOrElse(F.Constant1[error](0))(rightValue) // 10
// Apply a different function on Left(...)/Right(...)
doubleOrZero := Fold(F.Constant1[error](0), N.Mul(2)) // func(Either[error, int]) int
doubleFromLeft := doubleOrZero(leftValue) // 0
doubleFromRight := doubleOrZero(rightValue) // 20
// Pro-tip: Fold is short for the following:
doubleOrZeroBis := F.Flow2(
Map[error](N.Mul(2)),
GetOrElse(F.Constant1[error](0)),
)
doubleFromLeftBis := doubleOrZeroBis(leftValue) // 0
doubleFromRightBis := doubleOrZeroBis(rightValue) // 20
fmt.Println(leftValue)
fmt.Println(rightValue)
fmt.Println(leftWithDefault)
fmt.Println(rightWithDefault)
fmt.Println(doubleFromLeft)
fmt.Println(doubleFromRight)
fmt.Println(doubleFromLeftBis)
fmt.Println(doubleFromRightBis)
Output: Left[*errors.errorString](Division by Zero!) Right[int](10) 0 10 0 20 0 20
Example (Formatting_comparison) ¶
ExampleEither_formatting_comparison demonstrates different formatting options.
package main
import (
"fmt"
E "github.com/IBM/fp-go/v2/either"
)
func main() {
type User struct {
ID int
Name string
}
user := User{ID: 123, Name: "Alice"}
result := E.Right[error](user)
fmt.Printf("String(): %s\n", result.String())
fmt.Printf("GoString(): %s\n", result.GoString())
fmt.Printf("%%v: %v\n", result)
fmt.Printf("%%#v: %#v\n", result)
}
Output: String(): Right[either_test.User]({123 Alice}) GoString(): either.Right[error](either_test.User{ID:123, Name:"Alice"}) %v: Right[either_test.User]({123 Alice}) %#v: either.Right[error](either_test.User{ID:123, Name:"Alice"})
func Do ¶
Do creates an empty context of type S to be used with the Bind operation. This is the starting point for do-notation style computations.
Example:
type State struct { x, y int }
result := either.Do[error](State{})
func Flatten ¶
Flatten removes one level of nesting from a nested Either.
Example:
nested := either.Right[error](either.Right[error](42)) result := either.Flatten(nested) // Right(42)
func FromIO ¶
FromIO executes an IO operation and wraps the result in a Right value. This is useful for lifting pure IO operations into the Either context.
Example:
getValue := func() int { return 42 }
result := either.FromIO[error](getValue) // Right(42)
go: inline
func Left ¶
Left creates a new Either representing a Left (error/failure) value. By convention, Left represents the error case.
Example:
result := either.Left[int](errors.New("something went wrong"))
func MonadAlt ¶
MonadAlt provides an alternative Either if the first is Left. This is the monadic version of Alt.
func MonadAp ¶
MonadAp applies a function wrapped in Either to a value wrapped in Either. If either the function or the value is Left, returns Left. This is the applicative apply operation.
Example:
fab := either.Right[error](N.Mul(2)) fa := either.Right[error](21) result := either.MonadAp(fab, fa) // Right(42)
func MonadBiMap ¶
MonadBiMap applies two functions: one to transform a Left value, another to transform a Right value. This allows transforming both channels of the Either simultaneously.
Example:
result := either.MonadBiMap(
either.Left[int](errors.New("error")),
error.Error,
func(n int) string { return fmt.Sprint(n) },
) // Left("error")
func MonadChain ¶
MonadChain sequences two computations, where the second depends on the result of the first. If the first Either is Left, returns Left without executing the second computation. This is the monadic bind operation (also known as flatMap).
Example:
result := either.MonadChain(
either.Right[error](21),
func(x int) either.Either[error, int] {
return either.Right[error](x * 2)
},
) // Right(42)
func MonadChainFirst ¶
MonadChainFirst executes a side-effect computation but returns the original value. Useful for performing actions (like logging) without changing the value.
Example:
result := either.MonadChainFirst(
either.Right[error](42),
func(x int) either.Either[error, string] {
fmt.Println(x) // side effect
return either.Right[error]("logged")
},
) // Right(42) - original value preserved
func MonadChainOptionK ¶
func MonadChainOptionK[A, B, E any](onNone func() E, ma Either[E, A], f func(A) Option[B]) Either[E, B]
MonadChainOptionK chains a function that returns an Option, converting None to Left.
Example:
result := either.MonadChainOptionK(
func() error { return errors.New("not found") },
either.Right[error](42),
func(x int) option.Option[string] {
if x > 0 { return option.Some("positive") }
return option.None[string]()
},
) // Right("positive")
func MonadChainTo ¶
MonadChainTo ignores the first Either and returns the second. Useful for sequencing operations where you don't need the first result.
func MonadFlap ¶
MonadFlap applies a value to a function wrapped in Either. This is the reverse of MonadAp.
func MonadMap ¶
MonadMap transforms the Right value using the provided function. If the Either is Left, returns Left unchanged. This is the functor map operation.
Example:
result := either.MonadMap(
either.Right[error](21),
N.Mul(2),
) // Right(42)
func MonadMapLeft ¶
MonadMapLeft applies a transformation function to the Left (error) value. If the Either is Right, returns Right unchanged.
Example:
result := either.MonadMapLeft(
either.Left[int](errors.New("error")),
error.Error,
) // Left("error")
func MonadMapTo ¶
MonadMapTo replaces the Right value with a constant value. If the Either is Left, returns Left unchanged.
Example:
result := either.MonadMapTo(either.Right[error](21), "success") // Right("success")
func MonadSequence2 ¶
func MonadSequence2[E, T1, T2, R any](e1 Either[E, T1], e2 Either[E, T2], f func(T1, T2) Either[E, R]) Either[E, R]
MonadSequence2 sequences two Either values using a combining function. Short-circuits on the first Left encountered.
func MonadSequence3 ¶
func MonadSequence3[E, T1, T2, T3, R any](e1 Either[E, T1], e2 Either[E, T2], e3 Either[E, T3], f func(T1, T2, T3) Either[E, R]) Either[E, R]
MonadSequence3 sequences three Either values using a combining function. Short-circuits on the first Left encountered.
func Of ¶
Of constructs a Right value containing the given value. This is the monadic return/pure operation for Either. Equivalent to Right.
Example:
result := either.Of[error](42) // Right(42)
func Right ¶
Right creates a new Either representing a Right (success) value. By convention, Right represents the success case.
Example:
result := either.Right[error](42)
func SequenceArray ¶
SequenceArray converts a homogeneous sequence of Either into an Either of sequence. If any element is Left, returns that Left (short-circuits). Otherwise, returns Right containing all the Right values.
Example:
eithers := []either.Either[error, int]{
either.Right[error](1),
either.Right[error](2),
either.Right[error](3),
}
result := either.SequenceArray(eithers)
// result is Right([]int{1, 2, 3})
func SequenceArrayG ¶
func SequenceRecord ¶
func SequenceRecord[K comparable, E, A any](ma map[K]Either[E, A]) Either[E, map[K]A]
SequenceRecord converts a map of Either values into an Either of a map. If any value is Left, returns that Left (short-circuits). Otherwise, returns Right containing a map of all the Right values.
Example:
eithers := map[string]either.Either[error, int]{
"a": either.Right[error](1),
"b": either.Right[error](2),
}
result := either.SequenceRecord(eithers)
// result is Right(map[string]int{"a": 1, "b": 2})
func SequenceRecordG ¶
func SequenceRecordG[GA ~map[K]A, GOA ~map[K]Either[E, A], K comparable, E, A any](ma GOA) Either[E, GA]
func SequenceT1 ¶
SequenceT1 converts 1 parameters of [Either[E, T]] into a [Either[E, Tuple1]].
func SequenceT10 ¶
func SequenceT10[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10]) Either[E, T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
SequenceT10 converts 10 parameters of [Either[E, T]] into a [Either[E, Tuple10]].
func SequenceT11 ¶
func SequenceT11[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10], t11 Either[E, T11]) Either[E, T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]]
SequenceT11 converts 11 parameters of [Either[E, T]] into a [Either[E, Tuple11]].
func SequenceT12 ¶
func SequenceT12[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10], t11 Either[E, T11], t12 Either[E, T12]) Either[E, T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]]
SequenceT12 converts 12 parameters of [Either[E, T]] into a [Either[E, Tuple12]].
func SequenceT13 ¶
func SequenceT13[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10], t11 Either[E, T11], t12 Either[E, T12], t13 Either[E, T13]) Either[E, T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]]
SequenceT13 converts 13 parameters of [Either[E, T]] into a [Either[E, Tuple13]].
func SequenceT14 ¶
func SequenceT14[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10], t11 Either[E, T11], t12 Either[E, T12], t13 Either[E, T13], t14 Either[E, T14]) Either[E, T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]]
SequenceT14 converts 14 parameters of [Either[E, T]] into a [Either[E, Tuple14]].
func SequenceT15 ¶
func SequenceT15[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10], t11 Either[E, T11], t12 Either[E, T12], t13 Either[E, T13], t14 Either[E, T14], t15 Either[E, T15]) Either[E, T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]]
SequenceT15 converts 15 parameters of [Either[E, T]] into a [Either[E, Tuple15]].
func SequenceT2 ¶
SequenceT2 converts 2 parameters of [Either[E, T]] into a [Either[E, Tuple2]].
func SequenceT3 ¶
func SequenceT3[E, T1, T2, T3 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3]) Either[E, T.Tuple3[T1, T2, T3]]
SequenceT3 converts 3 parameters of [Either[E, T]] into a [Either[E, Tuple3]].
func SequenceT4 ¶
func SequenceT4[E, T1, T2, T3, T4 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4]) Either[E, T.Tuple4[T1, T2, T3, T4]]
SequenceT4 converts 4 parameters of [Either[E, T]] into a [Either[E, Tuple4]].
func SequenceT5 ¶
func SequenceT5[E, T1, T2, T3, T4, T5 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5]) Either[E, T.Tuple5[T1, T2, T3, T4, T5]]
SequenceT5 converts 5 parameters of [Either[E, T]] into a [Either[E, Tuple5]].
func SequenceT6 ¶
func SequenceT6[E, T1, T2, T3, T4, T5, T6 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6]) Either[E, T.Tuple6[T1, T2, T3, T4, T5, T6]]
SequenceT6 converts 6 parameters of [Either[E, T]] into a [Either[E, Tuple6]].
func SequenceT7 ¶
func SequenceT7[E, T1, T2, T3, T4, T5, T6, T7 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7]) Either[E, T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
SequenceT7 converts 7 parameters of [Either[E, T]] into a [Either[E, Tuple7]].
func SequenceT8 ¶
func SequenceT8[E, T1, T2, T3, T4, T5, T6, T7, T8 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8]) Either[E, T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
SequenceT8 converts 8 parameters of [Either[E, T]] into a [Either[E, Tuple8]].
func SequenceT9 ¶
func SequenceT9[E, T1, T2, T3, T4, T5, T6, T7, T8, T9 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9]) Either[E, T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
SequenceT9 converts 9 parameters of [Either[E, T]] into a [Either[E, Tuple9]].
func SequenceTuple1 ¶
SequenceTuple1 converts a [Tuple1] of [Either[E, T]] into an [Either[E, Tuple1]].
func SequenceTuple10 ¶
func SequenceTuple10[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](t T.Tuple10[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10]]) Either[E, T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
SequenceTuple10 converts a [Tuple10] of [Either[E, T]] into an [Either[E, Tuple10]].
func SequenceTuple11 ¶
func SequenceTuple11[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](t T.Tuple11[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10], Either[E, T11]]) Either[E, T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]]
SequenceTuple11 converts a [Tuple11] of [Either[E, T]] into an [Either[E, Tuple11]].
func SequenceTuple12 ¶
func SequenceTuple12[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](t T.Tuple12[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10], Either[E, T11], Either[E, T12]]) Either[E, T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]]
SequenceTuple12 converts a [Tuple12] of [Either[E, T]] into an [Either[E, Tuple12]].
func SequenceTuple13 ¶
func SequenceTuple13[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](t T.Tuple13[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10], Either[E, T11], Either[E, T12], Either[E, T13]]) Either[E, T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]]
SequenceTuple13 converts a [Tuple13] of [Either[E, T]] into an [Either[E, Tuple13]].
func SequenceTuple14 ¶
func SequenceTuple14[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](t T.Tuple14[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10], Either[E, T11], Either[E, T12], Either[E, T13], Either[E, T14]]) Either[E, T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]]
SequenceTuple14 converts a [Tuple14] of [Either[E, T]] into an [Either[E, Tuple14]].
func SequenceTuple15 ¶
func SequenceTuple15[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](t T.Tuple15[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10], Either[E, T11], Either[E, T12], Either[E, T13], Either[E, T14], Either[E, T15]]) Either[E, T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]]
SequenceTuple15 converts a [Tuple15] of [Either[E, T]] into an [Either[E, Tuple15]].
func SequenceTuple2 ¶
func SequenceTuple2[E, T1, T2 any](t T.Tuple2[Either[E, T1], Either[E, T2]]) Either[E, T.Tuple2[T1, T2]]
SequenceTuple2 converts a [Tuple2] of [Either[E, T]] into an [Either[E, Tuple2]].
func SequenceTuple3 ¶
func SequenceTuple3[E, T1, T2, T3 any](t T.Tuple3[Either[E, T1], Either[E, T2], Either[E, T3]]) Either[E, T.Tuple3[T1, T2, T3]]
SequenceTuple3 converts a [Tuple3] of [Either[E, T]] into an [Either[E, Tuple3]].
func SequenceTuple4 ¶
func SequenceTuple4[E, T1, T2, T3, T4 any](t T.Tuple4[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4]]) Either[E, T.Tuple4[T1, T2, T3, T4]]
SequenceTuple4 converts a [Tuple4] of [Either[E, T]] into an [Either[E, Tuple4]].
func SequenceTuple5 ¶
func SequenceTuple5[E, T1, T2, T3, T4, T5 any](t T.Tuple5[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5]]) Either[E, T.Tuple5[T1, T2, T3, T4, T5]]
SequenceTuple5 converts a [Tuple5] of [Either[E, T]] into an [Either[E, Tuple5]].
func SequenceTuple6 ¶
func SequenceTuple6[E, T1, T2, T3, T4, T5, T6 any](t T.Tuple6[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6]]) Either[E, T.Tuple6[T1, T2, T3, T4, T5, T6]]
SequenceTuple6 converts a [Tuple6] of [Either[E, T]] into an [Either[E, Tuple6]].
func SequenceTuple7 ¶
func SequenceTuple7[E, T1, T2, T3, T4, T5, T6, T7 any](t T.Tuple7[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7]]) Either[E, T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
SequenceTuple7 converts a [Tuple7] of [Either[E, T]] into an [Either[E, Tuple7]].
func SequenceTuple8 ¶
func SequenceTuple8[E, T1, T2, T3, T4, T5, T6, T7, T8 any](t T.Tuple8[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8]]) Either[E, T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
SequenceTuple8 converts a [Tuple8] of [Either[E, T]] into an [Either[E, Tuple8]].
func SequenceTuple9 ¶
func SequenceTuple9[E, T1, T2, T3, T4, T5, T6, T7, T8, T9 any](t T.Tuple9[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9]]) Either[E, T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
SequenceTuple9 converts a [Tuple9] of [Either[E, T]] into an [Either[E, Tuple9]].
func Swap ¶
Swap exchanges the Left and Right type parameters.
Example:
result := either.Swap(either.Right[error](42)) // Left(42)
result := either.Swap(either.Left[int](errors.New("err"))) // Right(error)
func TryCatch ¶
TryCatch converts a (value, error) tuple into an Either, applying a transformation to the error.
Example:
result := either.TryCatch(
42, nil,
func(err error) string { return err.Error() },
) // Right(42)
func TryCatchError ¶
TryCatchError is a specialized version of TryCatch for error types. Converts a (value, error) tuple into Either[error, A].
Example:
result := either.TryCatchError(42, nil) // Right(42)
result := either.TryCatchError(0, errors.New("fail")) // Left(error)
func (Either[E, A]) Format ¶
Format implements fmt.Formatter for Either. Supports all standard format verbs:
- %s, %v, %+v: uses String() representation
- %#v: uses GoString() representation
- %q: quoted String() representation
- other verbs: uses String() representation
Example:
e := either.Right[error](42)
fmt.Printf("%s", e) // "Right[int](42)"
fmt.Printf("%v", e) // "Right[int](42)"
fmt.Printf("%#v", e) // "either.Right[error](42)"
Example ¶
ExampleEither_Format demonstrates the fmt.Formatter interface implementation.
package main
import (
"fmt"
E "github.com/IBM/fp-go/v2/either"
)
func main() {
result := E.Right[error](42)
// Different format verbs
fmt.Printf("%%s: %s\n", result)
fmt.Printf("%%v: %v\n", result)
fmt.Printf("%%+v: %+v\n", result)
fmt.Printf("%%#v: %#v\n", result)
}
Output: %s: Right[int](42) %v: Right[int](42) %+v: Right[int](42) %#v: either.Right[error](42)
func (Either[E, A]) GoString ¶
GoString implements fmt.GoStringer for Either. Returns a Go-syntax representation of the Either value.
Example:
either.Right[error](42).GoString() // "either.Right[error](42)"
either.Left[int](errors.New("fail")).GoString() // "either.Left[int](error)"
Example ¶
ExampleEither_GoString demonstrates the fmt.GoStringer interface implementation.
package main
import (
"errors"
"fmt"
E "github.com/IBM/fp-go/v2/either"
)
func main() {
right := E.Right[error](42)
left := E.Left[int](errors.New("error"))
fmt.Printf("%#v\n", right)
fmt.Printf("%#v\n", left)
}
Output: either.Right[error](42) either.Left[int](&errors.errorString{s:"error"})
func (Either[E, A]) LogValue ¶
LogValue implements slog.LogValuer for Either. Returns a slog.Value that represents the Either for structured logging. Returns a group value with "right" key for Right values and "left" key for Left values.
Example:
logger := slog.Default()
result := either.Right[error](42)
logger.Info("result", "value", result)
// Logs: {"msg":"result","value":{"right":42}}
err := either.Left[int](errors.New("failed"))
logger.Error("error", "value", err)
// Logs: {"msg":"error","value":{"left":"failed"}}
Example ¶
ExampleEither_LogValue demonstrates the slog.LogValuer interface implementation.
package main
import (
"errors"
"log/slog"
"os"
E "github.com/IBM/fp-go/v2/either"
)
func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
// Remove time for consistent output
if a.Key == slog.TimeKey {
return slog.Attr{}
}
return a
},
}))
// Right value
rightResult := E.Right[error](42)
logger.Info("computation succeeded", "result", rightResult)
// Left value
leftResult := E.Left[int](errors.New("computation failed"))
logger.Error("computation failed", "result", leftResult)
}
Output: level=INFO msg="computation succeeded" result.right=42 level=ERROR msg="computation failed" result.left="computation failed"
Example (Structured) ¶
ExampleEither_LogValue_structured demonstrates structured logging with Either.
package main
import (
"errors"
"log/slog"
"os"
E "github.com/IBM/fp-go/v2/either"
)
func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey {
return slog.Attr{}
}
return a
},
}))
// Simulate a computation pipeline
compute := func(x int) E.Either[error, int] {
if x < 0 {
return E.Left[int](errors.New("negative input"))
}
return E.Right[error](x * 2)
}
// Log successful computation
result1 := compute(21)
logger.Info("computation", "input", 21, "output", result1)
// Log failed computation
result2 := compute(-5)
logger.Error("computation", "input", -5, "output", result2)
}
Output: level=INFO msg=computation input=21 output.right=42 level=ERROR msg=computation input=-5 output.left="negative input"
func (Either[E, A]) String ¶
String prints some debug info for the object
Example ¶
ExampleEither_String demonstrates the fmt.Stringer interface implementation.
package main
import (
"errors"
"fmt"
E "github.com/IBM/fp-go/v2/either"
)
func main() {
right := E.Right[error](42)
left := E.Left[int](errors.New("something went wrong"))
fmt.Println(right.String())
fmt.Println(left.String())
}
Output: Right[int](42) Left[*errors.errorString](something went wrong)
type Endomorphism ¶
type Endomorphism[T any] = endomorphism.Endomorphism[T]
Option is a type alias for option.Option, provided for convenience when working with Either and Option together.
func ApSL ¶
ApSL attaches a value to a context using a lens-based setter. This is a convenience function that combines ApS with a lens, allowing you to use optics to update nested structures in a more composable way.
The lens parameter provides both the getter and setter for a field within the structure S. This eliminates the need to manually write setter functions and enables working with nested fields in a type-safe manner.
Unlike BindL, ApSL uses applicative semantics, meaning the computation fa is independent of the current state and can be evaluated concurrently.
Type Parameters:
- E: Error type for the Either
- S: Structure type containing the field to update
- T: Type of the field being updated
Parameters:
- lens: A Lens[S, T] that focuses on a field of type T within structure S
- fa: An Either[E, T] computation that produces the value to set
Returns:
- An endomorphism that updates the focused field in the Either context
Example:
type Person struct {
Name string
Age int
}
ageLens := lens.MakeLens(
func(p Person) int { return p.Age },
func(p Person, a int) Person { p.Age = a; return p },
)
result := F.Pipe2(
either.Right[error](Person{Name: "Alice", Age: 25}),
either.ApSL(ageLens, either.Right[error](30)),
) // Right(Person{Name: "Alice", Age: 30})
func BindL ¶
BindL attaches the result of a computation to a context using a lens-based setter. This is a convenience function that combines Bind with a lens, allowing you to use optics to update nested structures based on their current values.
The lens parameter provides both the getter and setter for a field within the structure S. The computation function f receives the current value of the focused field and returns an Either that produces the new value.
Unlike ApSL, BindL uses monadic sequencing, meaning the computation f can depend on the current value of the focused field.
Type Parameters:
- E: Error type for the Either
- S: Structure type containing the field to update
- T: Type of the field being updated
Parameters:
- lens: A Lens[S, T] that focuses on a field of type T within structure S
- f: A function that takes the current field value and returns an Either[E, T]
Returns:
- An endomorphism that updates the focused field based on its current value
Example:
type Counter struct {
Value int
}
valueLens := lens.MakeLens(
func(c Counter) int { return c.Value },
func(c Counter, v int) Counter { c.Value = v; return c },
)
// Increment the counter, but fail if it would exceed 100
increment := func(v int) either.Either[error, int] {
if v >= 100 {
return either.Left[int](errors.New("counter overflow"))
}
return either.Right[error](v + 1)
}
result := F.Pipe1(
either.Right[error](Counter{Value: 42}),
either.BindL(valueLens, increment),
) // Right(Counter{Value: 43})
func LetL ¶
LetL attaches the result of a pure computation to a context using a lens-based setter. This is a convenience function that combines Let with a lens, allowing you to use optics to update nested structures with pure transformations.
The lens parameter provides both the getter and setter for a field within the structure S. The transformation function f receives the current value of the focused field and returns the new value directly (not wrapped in Either).
This is useful for pure transformations that cannot fail, such as mathematical operations, string manipulations, or other deterministic updates.
Type Parameters:
- E: Error type for the Either
- S: Structure type containing the field to update
- T: Type of the field being updated
Parameters:
- lens: A Lens[S, T] that focuses on a field of type T within structure S
- f: An endomorphism (T → T) that transforms the current field value
Returns:
- An endomorphism that updates the focused field with the transformed value
Example:
type Counter struct {
Value int
}
valueLens := lens.MakeLens(
func(c Counter) int { return c.Value },
func(c Counter, v int) Counter { c.Value = v; return c },
)
// Double the counter value
double := func(v int) int { return v * 2 }
result := F.Pipe1(
either.Right[error](Counter{Value: 21}),
either.LetL(valueLens, double),
) // Right(Counter{Value: 42})
func LetToL ¶
LetToL attaches a constant value to a context using a lens-based setter. This is a convenience function that combines LetTo with a lens, allowing you to use optics to set nested fields to specific values.
The lens parameter provides the setter for a field within the structure S. Unlike LetL which transforms the current value, LetToL simply replaces it with the provided constant value b.
This is useful for resetting fields, initializing values, or setting fields to predetermined constants.
Type Parameters:
- E: Error type for the Either
- S: Structure type containing the field to update
- T: Type of the field being updated
Parameters:
- lens: A Lens[S, T] that focuses on a field of type T within structure S
- b: The constant value to set the field to
Returns:
- An endomorphism that sets the focused field to the constant value
Example:
type Config struct {
Debug bool
Timeout int
}
debugLens := lens.MakeLens(
func(c Config) bool { return c.Debug },
func(c Config, d bool) Config { c.Debug = d; return c },
)
result := F.Pipe1(
either.Right[error](Config{Debug: true, Timeout: 30}),
either.LetToL(debugLens, false),
) // Right(Config{Debug: false, Timeout: 30})
type Kleisli ¶
Option is a type alias for option.Option, provided for convenience when working with Either and Option together.
func TailRec ¶
func TailRec[E, A, B any](f Kleisli[E, A, tailrec.Trampoline[A, B]]) Kleisli[E, A, B]
func TraverseArray ¶
func TraverseArray[E, A, B any](f Kleisli[E, A, B]) Kleisli[E, []A, []B]
TraverseArray transforms an array by applying a function that returns an Either to each element. If any element produces a Left, the entire result is that Left (short-circuits). Otherwise, returns Right containing the array of all Right values.
Example:
parse := func(s string) either.Either[error, int] {
v, err := strconv.Atoi(s)
return either.FromError(v, err)
}
result := either.TraverseArray(parse)([]string{"1", "2", "3"})
// result is Right([]int{1, 2, 3})
func TraverseArrayG ¶
func TraverseArrayG[GA ~[]A, GB ~[]B, E, A, B any](f Kleisli[E, A, B]) Kleisli[E, GA, GB]
TraverseArrayG transforms an array by applying a function that returns an Either to each element. If any element produces a Left, the entire result is that Left (short-circuits). Otherwise, returns Right containing the array of all Right values. The G suffix indicates support for generic slice types.
Example:
parse := func(s string) either.Either[error, int] {
v, err := strconv.Atoi(s)
return either.FromError(v, err)
}
result := either.TraverseArrayG[[]string, []int](parse)([]string{"1", "2", "3"})
// result is Right([]int{1, 2, 3})
func TraverseArrayWithIndex ¶
TraverseArrayWithIndex transforms an array by applying an indexed function that returns an Either. The function receives both the index and the element. If any element produces a Left, the entire result is that Left (short-circuits).
Example:
validate := func(i int, s string) either.Either[error, string] {
if S.IsNonEmpty(s) {
return either.Right[error](fmt.Sprintf("%d:%s", i, s))
}
return either.Left[string](fmt.Errorf("empty at index %d", i))
}
result := either.TraverseArrayWithIndex(validate)([]string{"a", "b"})
// result is Right([]string{"0:a", "1:b"})
func TraverseArrayWithIndexG ¶
func TraverseArrayWithIndexG[GA ~[]A, GB ~[]B, E, A, B any](f func(int, A) Either[E, B]) Kleisli[E, GA, GB]
TraverseArrayWithIndexG transforms an array by applying an indexed function that returns an Either. The function receives both the index and the element. If any element produces a Left, the entire result is that Left (short-circuits). The G suffix indicates support for generic slice types.
Example:
validate := func(i int, s string) either.Either[error, string] {
if S.IsNonEmpty(s) {
return either.Right[error](fmt.Sprintf("%d:%s", i, s))
}
return either.Left[string](fmt.Errorf("empty at index %d", i))
}
result := either.TraverseArrayWithIndexG[[]string, []string](validate)([]string{"a", "b"})
// result is Right([]string{"0:a", "1:b"})
func TraverseRecord ¶
func TraverseRecord[K comparable, E, A, B any](f Kleisli[E, A, B]) Kleisli[E, map[K]A, map[K]B]
TraverseRecord transforms a map by applying a function that returns an Either to each value. If any value produces a Left, the entire result is that Left (short-circuits). Otherwise, returns Right containing the map of all Right values.
Example:
parse := func(s string) either.Either[error, int] {
v, err := strconv.Atoi(s)
return either.FromError(v, err)
}
result := either.TraverseRecord[string](parse)(map[string]string{"a": "1", "b": "2"})
// result is Right(map[string]int{"a": 1, "b": 2})
func TraverseRecordG ¶
func TraverseRecordG[GA ~map[K]A, GB ~map[K]B, K comparable, E, A, B any](f Kleisli[E, A, B]) Kleisli[E, GA, GB]
TraverseRecordG transforms a map by applying a function that returns an Either to each value. If any value produces a Left, the entire result is that Left (short-circuits). Otherwise, returns Right containing the map of all Right values. The G suffix indicates support for generic map types.
Example:
parse := func(s string) either.Either[error, int] {
v, err := strconv.Atoi(s)
return either.FromError(v, err)
}
result := either.TraverseRecordG[map[string]string, map[string]int](parse)(map[string]string{"a": "1", "b": "2"})
// result is Right(map[string]int{"a": 1, "b": 2})
func TraverseRecordWithIndex ¶
func TraverseRecordWithIndex[K comparable, E, A, B any](f func(K, A) Either[E, B]) Kleisli[E, map[K]A, map[K]B]
TraverseRecordWithIndex transforms a map by applying an indexed function that returns an Either. The function receives both the key and the value. If any value produces a Left, the entire result is that Left (short-circuits).
Example:
validate := func(k string, v string) either.Either[error, string] {
if len(v) > 0 {
return either.Right[error](k + ":" + v)
}
return either.Left[string](fmt.Errorf("empty value for key %s", k))
}
result := either.TraverseRecordWithIndex[string](validate)(map[string]string{"a": "1"})
// result is Right(map[string]string{"a": "a:1"})
func TraverseRecordWithIndexG ¶
func TraverseRecordWithIndexG[GA ~map[K]A, GB ~map[K]B, K comparable, E, A, B any](f func(K, A) Either[E, B]) Kleisli[E, GA, GB]
TraverseRecordWithIndexG transforms a map by applying an indexed function that returns an Either. The function receives both the key and the value. If any value produces a Left, the entire result is that Left (short-circuits). The G suffix indicates support for generic map types.
Example:
validate := func(k string, v string) either.Either[error, string] {
if len(v) > 0 {
return either.Right[error](k + ":" + v)
}
return either.Left[string](fmt.Errorf("empty value for key %s", k))
}
result := either.TraverseRecordWithIndexG[map[string]string, map[string]string](validate)(map[string]string{"a": "1"})
// result is Right(map[string]string{"a": "a:1"})
func WithResource ¶
func WithResource[A, E, R, ANY any]( onCreate func() Either[E, R], onRelease Kleisli[E, R, ANY], ) Kleisli[E, Kleisli[E, R, A], A]
WithResource constructs a function that creates a resource, operates on it, and then releases it. This ensures proper resource cleanup even if operations fail. The resource is released immediately after the operation completes.
Parameters:
- onCreate: Function to create/acquire the resource
- onRelease: Function to release/cleanup the resource
Returns a function that takes an operation to perform on the resource.
Example:
withFile := either.WithResource(
func() either.Either[error, *os.File] {
return either.TryCatchError(os.Open("file.txt"))
},
func(f *os.File) either.Either[error, any] {
return either.TryCatchError(f.Close())
},
)
result := withFile(func(f *os.File) either.Either[error, string] {
// Use file here
return either.Right[error]("data")
})
type Lazy ¶
Option is a type alias for option.Option, provided for convenience when working with Either and Option together.
type Lens ¶
Option is a type alias for option.Option, provided for convenience when working with Either and Option together.
type Monoid ¶
Option is a type alias for option.Option, provided for convenience when working with Either and Option together.
func AltMonoid ¶
AltMonoid creates a monoid for Either using the Alt operation. The empty value is provided as a lazy computation. When combining, returns the first Right value, or the second if the first is Left.
Example:
zero := func() either.Either[error, int] { return either.Left[int](errors.New("empty")) }
m := either.AltMonoid[error, int](zero)
result := m.Concat(either.Left[int](errors.New("err1")), either.Right[error](42))
// result is Right(42)
func AlternativeMonoid ¶
AlternativeMonoid creates a monoid for Either using applicative semantics. The empty value is Right with the monoid's empty value. Combines values using applicative operations.
Example:
import "github.com/IBM/fp-go/v2/monoid"
intAdd := monoid.MakeMonoid(0, func(a, b int) int { return a + b })
m := either.AlternativeMonoid[error](intAdd)
result := m.Concat(either.Right[error](1), either.Right[error](2))
// result is Right(3)
type Operator ¶
Option is a type alias for option.Option, provided for convenience when working with Either and Option together.
func Alt ¶
Alt provides an alternative Either if the first is Left.
Example:
alternative := either.Alt[error](func() either.Either[error, int] {
return either.Right[error](99)
})
result := alternative(either.Left[int](errors.New("fail"))) // Right(99)
func Ap ¶
Ap is the curried version of MonadAp. Returns a function that applies a wrapped function to the given wrapped value.
func ApS ¶
ApS attaches a value to a context S1 to produce a context S2 by considering the context and the value concurrently. Uses applicative semantics rather than monadic sequencing.
Example:
type State struct { x, y int }
result := F.Pipe2(
either.Right[error](State{x: 10}),
either.ApS(
func(y int) func(State) State {
return func(s State) State { return State{x: s.x, y: y} }
},
either.Right[error](32),
),
) // Right(State{x: 10, y: 32})
func Bind ¶
func Bind[E, S1, S2, T any]( setter func(T) func(S1) S2, f Kleisli[E, S1, T], ) Operator[E, S1, S2]
Bind attaches the result of a computation to a context S1 to produce a context S2. This enables building up complex computations in a pipeline.
Example:
type State struct { value int }
result := F.Pipe2(
either.Do[error](State{}),
either.Bind(
func(v int) func(State) State {
return func(s State) State { return State{value: v} }
},
func(s State) either.Either[error, int] {
return either.Right[error](42)
},
),
)
func BindTo ¶
func BindTo[E, S1, T any]( setter func(T) S1, ) Operator[E, T, S1]
BindTo initializes a new state S1 from a value T. This is typically used to start a bind chain.
Example:
type State struct { value int }
result := F.Pipe2(
either.Right[error](42),
either.BindTo(func(v int) State { return State{value: v} }),
) // Right(State{value: 42})
func Chain ¶
func Chain[E, A, B any](f Kleisli[E, A, B]) Operator[E, A, B]
Chain is the curried version of MonadChain. Sequences two computations where the second depends on the first.
func ChainFirst ¶
func ChainFirst[E, A, B any](f Kleisli[E, A, B]) Operator[E, A, A]
ChainFirst is the curried version of MonadChainFirst.
func ChainTo ¶
ChainTo is the curried version of MonadChainTo.
func Flap ¶
func Flap[E, B, A any](a A) Operator[E, func(A) B, B]
Flap is the curried version of MonadFlap.
func Let ¶
func Let[E, S1, S2, T any]( key func(T) func(S1) S2, f func(S1) T, ) Operator[E, S1, S2]
Let attaches the result of a pure computation to a context S1 to produce a context S2. Similar to Bind but for pure (non-Either) computations.
Example:
type State struct { value int }
result := F.Pipe2(
either.Right[error](State{value: 10}),
either.Let(
func(v int) func(State) State {
return func(s State) State { return State{value: s.value + v} }
},
func(s State) int { return 32 },
),
) // Right(State{value: 42})
func LetTo ¶
func LetTo[E, S1, S2, T any]( key func(T) func(S1) S2, b T, ) Operator[E, S1, S2]
LetTo attaches a constant value to a context S1 to produce a context S2.
Example:
type State struct { name string }
result := F.Pipe2(
either.Right[error](State{}),
either.LetTo(
func(n string) func(State) State {
return func(s State) State { return State{name: n} }
},
"Alice",
),
) // Right(State{name: "Alice"})
func Map ¶
func Map[E, A, B any](f func(a A) B) Operator[E, A, B]
Map is the curried version of MonadMap. Transforms the Right value using the provided function.
func MapTo ¶
func MapTo[E, A, B any](b B) Operator[E, A, B]
MapTo is the curried version of MonadMapTo.
func OrElse ¶
func OrElse[E, A any](onLeft Kleisli[E, E, A]) Operator[E, A, A]
OrElse recovers from a Left by providing an alternative computation.
Example:
recover := either.OrElse(func(err error) either.Either[error, int] {
return either.Right[error](0) // default value
})
result := recover(either.Left[int](errors.New("fail"))) // Right(0)
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package exec provides utilities for executing system commands with Either-based error handling.
|
Package exec provides utilities for executing system commands with Either-based error handling. |
|
Package http provides utilities for creating HTTP requests with Either-based error handling.
|
Package http provides utilities for creating HTTP requests with Either-based error handling. |
|
Package testing provides utilities for testing Either monad laws.
|
Package testing provides utilities for testing Either monad laws. |