Documentation
¶
Overview ¶
Package result provides an idiomatic Go approach to error handling using the (value, error) tuple pattern.
This package represents the Result/Either monad idiomatically in Go, leveraging the standard (T, error) return pattern that Go developers are familiar with. By convention:
- (value, nil) represents a success case (Right)
- (zero, error) represents a failure case (Left)
Core Concepts ¶
The Result pattern is a functional approach to error handling that makes error flows explicit and composable. Instead of checking errors manually at each step, you can chain operations that automatically short-circuit on the first error.
Basic Usage ¶
// Creating Result values
success := result.Right[error](42) // (42, nil)
failure := result.Left[int](errors.New("oops")) // (0, error)
// Pattern matching with Fold
output := result.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/error)
output := result.Chain(func(n int) (int, error) {
return result.Right[error](n * 2)
})(success)
Monadic Operations ¶
Result implements the Monad interface, providing:
- Map: Transform the Right value
- Chain (FlatMap): Chain computations that may fail
- Ap: Apply a function wrapped in Result
Error Handling ¶
Result provides utilities for working with Go's error type:
- FromError: Create Result from error-returning functions
- FromPredicate: Create Result based on a predicate
- ToError: Extract the error from a Result
Subpackages ¶
- result/exec: Execute system commands returning Result
- result/http: HTTP request builders returning Result
Example (Creation) ¶
// Build an Either
leftValue, leftErr := Left[string](fmt.Errorf("some error"))
rightValue, rightErr := Right("value")
// Build from a value
fromNillable := FromNillable[string](fmt.Errorf("value was nil"))
leftFromNil, nilErr := fromNillable(nil)
value := "value"
rightFromPointer, ptrErr := 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, predErrOdd := fromEven(3)
rightFromPred, predErrEven := fromEven(4)
fmt.Println(ToString(leftValue, leftErr))
fmt.Println(ToString(rightValue, rightErr))
fmt.Println(ToString(leftFromNil, nilErr))
fmt.Println(IsRight(rightFromPointer, ptrErr))
fmt.Println(ToString(leftFromPred, predErrOdd))
fmt.Println(ToString(rightFromPred, predErrEven))
Output: Left(some error) Right[string](value) Left(value was nil) true Left(3 is an odd number) Right[int](4)
Example (Extraction) ¶
leftValue, leftErr := Left[int](fmt.Errorf("Division by Zero!"))
rightValue, rightErr := Right(10)
// Convert Either[A] to A with a default value
leftWithDefault := GetOrElse(F.Constant1[error](0))(leftValue, leftErr) // 0
rightWithDefault := GetOrElse(F.Constant1[error](0))(rightValue, rightErr) // 10
// Apply a different function on Left(...)/Right(...)
doubleOrZero := Fold(F.Constant1[error](0), N.Mul(2)) // func(int, error) int
doubleFromLeft := doubleOrZero(leftValue, leftErr) // 0
doubleFromRight := doubleOrZero(rightValue, rightErr) // 20
// You can also chain operations using Map
tripled, tripledErr := Pipe2(
rightValue,
Right[int],
Map(N.Mul(3)),
)
tripledResult := GetOrElse(F.Constant1[error](0))(tripled, tripledErr) // 30
fmt.Println(ToString(leftValue, leftErr))
fmt.Println(ToString(rightValue, rightErr))
fmt.Println(leftWithDefault)
fmt.Println(rightWithDefault)
fmt.Println(doubleFromLeft)
fmt.Println(doubleFromRight)
fmt.Println(tripledResult)
Output: Left(Division by Zero!) Right[int](10) 0 10 0 20 30
Index ¶
- func ApS[S1, S2, T any](setter func(T) func(S1) S2) func(T, error) Operator[S1, S2]
- func ApSL[S, T any](lens Lens[S, T]) func(T, error) Operator[S, S]
- func ApV[B, A any](sg S.Semigroup[error]) func(A, error) Operator[func(A) B, B]
- func ChainOptionK[A, B any](onNone func() error) func(option.Kleisli[A, B]) Operator[A, B]
- func Curry0[R any](f func() (R, error)) func() (R, error)
- func Curry1[T1, R any](f func(T1) (R, error)) func(T1) (R, error)
- func Curry2[T1, T2, R any](f func(T1, T2) (R, error)) func(T1) func(T2) (R, error)
- func Curry3[T1, T2, T3, R any](f func(T1, T2, T3) (R, error)) func(T1) func(T2) func(T3) (R, error)
- func Curry4[T1, T2, T3, T4, R any](f func(T1, T2, T3, T4) (R, error)) func(T1) func(T2) func(T3) func(T4) (R, error)
- func Do[S any](empty S) (S, error)
- func Eq[A any](eq EQ.Eq[A]) func(A, error) func(A, error) bool
- func Flow1[F1 ~func(T0, error) (T1, error), T0, T1 any](f1 F1) func(T0, error) (T1, error)
- func Flow2[F1 ~func(T0, error) (T1, error), F2 ~func(T1, error) (T2, error), ...](f1 F1, f2 F2) func(T0, error) (T2, error)
- func Flow3[F1 ~func(T0, error) (T1, error), F2 ~func(T1, error) (T2, error), ...](f1 F1, f2 F2, f3 F3) func(T0, error) (T3, error)
- func Flow4[F1 ~func(T0, error) (T1, error), F2 ~func(T1, error) (T2, error), ...](f1 F1, f2 F2, f3 F3, f4 F4) func(T0, error) (T4, error)
- func Flow5[F1 ~func(T0, error) (T1, error), F2 ~func(T1, error) (T2, error), ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(T0, error) (T5, error)
- func Fold[A, B any](onLeft func(error) B, onRight func(A) B) func(A, error) B
- func FromOption[A any](onNone func() error) func(A, bool) (A, error)
- func FromStrictEquals[A comparable]() func(A, error) func(A, error) bool
- func GetOrElse[A any](onLeft func(error) A) func(A, error) A
- func IsLeft[A any](_ A, err error) bool
- func IsRight[A any](_ A, err error) bool
- func Left[A any](err error) (A, error)
- func Logger[A any](loggers ...*log.Logger) func(string) Operator[A, A]
- func Memoize[A any](a A, err error) (A, error)
- func Of[A any](a A) (A, error)
- func Pipe1[F1 ~func(T0) (T1, error), T0, T1 any](t0 T0, f1 F1) (T1, error)
- func Pipe2[F1 ~func(T0) (T1, error), F2 ~func(T1, error) (T2, error), T0, T1, T2 any](t0 T0, f1 F1, f2 F2) (T2, error)
- func Pipe3[F1 ~func(T0) (T1, error), F2 ~func(T1, error) (T2, error), ...](t0 T0, f1 F1, f2 F2, f3 F3) (T3, error)
- func Pipe4[F1 ~func(T0) (T1, error), F2 ~func(T1, error) (T2, error), ...](t0 T0, f1 F1, f2 F2, f3 F3, f4 F4) (T4, error)
- func Pipe5[F1 ~func(T0) (T1, error), F2 ~func(T1, error) (T2, error), ...](t0 T0, f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) (T5, error)
- func Reduce[A, B any](f func(B, A) B, initial B) func(A, error) B
- func Right[A any](a A) (A, error)
- func Sequence[A, HKTA, HKTRA any](mof func(A, error) HKTRA, mmap func(Kleisli[A, A]) func(HKTA) HKTRA) func(hkta HKTA, err error) HKTRA
- func ToError[A any](_ A, err error) error
- func ToOption[A any](a A, aerr error) (A, bool)
- func ToString[A any](a A, err error) string
- func Traverse[A, B, HKTB, HKTRB any](mof func(B, error) HKTRB, mmap func(Kleisli[B, B]) func(HKTB) HKTRB) func(func(A) HKTB) func(A, error) HKTRB
- func TraverseTuple1[F1 ~func(A1) (T1, error), E, A1, T1 any](f1 F1) func(A1) (T1, error)
- func TraverseTuple10[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), ...](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) (T1, error), F2 ~func(A2) (T2, error), E, A1, T1, A2, T2 any](f1 F1, f2 F2) func(A1, A2) (T1, T2, error)
- func TraverseTuple3[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), ...](f1 F1, f2 F2, f3 F3) func(A1, A2, A3) (T1, T2, T3, error)
- func TraverseTuple4[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), ...](f1 F1, f2 F2, f3 F3, f4 F4) func(A1, A2, A3, A4) (T1, T2, T3, T4, error)
- func TraverseTuple5[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(A1, A2, A3, A4, A5) (T1, T2, T3, T4, T5, error)
- func TraverseTuple6[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6) func(A1, A2, A3, A4, A5, A6) (T1, T2, T3, T4, T5, T6, error)
- func TraverseTuple7[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7) func(A1, A2, A3, A4, A5, A6, A7) (T1, T2, T3, T4, T5, T6, T7, error)
- func TraverseTuple8[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8) func(A1, A2, A3, A4, A5, A6, A7, A8) (T1, T2, T3, T4, T5, T6, T7, T8, error)
- func TraverseTuple9[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), ...](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9) ...
- func Uncurry0[R any](f func() (R, error)) func() (R, error)
- func Uncurry1[T1, R any](f func(T1) (R, error)) func(T1) (R, error)
- func Uncurry2[T1, T2, R any](f func(T1) func(T2) (R, error)) func(T1, T2) (R, error)
- func Uncurry3[T1, T2, T3, R any](f func(T1) func(T2) func(T3) (R, error)) func(T1, T2, T3) (R, error)
- func Uncurry4[T1, T2, T3, T4, R any](f func(T1) func(T2) func(T3) func(T4) (R, error)) func(T1, T2, T3, T4) (R, error)
- type Applicative
- type Apply
- type Chainable
- type Endomorphism
- type Functor
- type Kleisli
- func FromError[A any](f func(a A) error) Kleisli[A, A]
- func FromNillable[A any](e error) Kleisli[*A, *A]
- func FromPredicate[A any](pred func(A) bool, onFalse func(A) error) Kleisli[A, A]
- func ToType[A any](onError func(any) error) Kleisli[any, A]
- func TraverseArray[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B]
- func TraverseArrayG[GA ~[]A, GB ~[]B, A, B any](f Kleisli[A, B]) Kleisli[GA, GB]
- func TraverseArrayWithIndex[A, B any](f func(int, A) (B, error)) Kleisli[[]A, []B]
- func TraverseArrayWithIndexG[GA ~[]A, GB ~[]B, A, B any](f func(int, A) (B, error)) Kleisli[GA, GB]
- func TraverseRecord[K comparable, A, B any](f Kleisli[A, B]) Kleisli[map[K]A, map[K]B]
- func TraverseRecordG[GA ~map[K]A, GB ~map[K]B, K comparable, A, B any](f Kleisli[A, B]) Kleisli[GA, GB]
- func TraverseRecordWithIndex[K comparable, A, B any](f func(K, A) (B, error)) Kleisli[map[K]A, map[K]B]
- func TraverseRecordWithIndexG[GA ~map[K]A, GB ~map[K]B, K comparable, A, B any](f func(K, A) (B, error)) Kleisli[GA, GB]
- func WithResource[R, A, ANY any](onCreate func() (R, error), onRelease Kleisli[R, ANY]) Kleisli[Kleisli[R, A], A]
- type Lens
- type Monad
- type Operator
- func Alt[A any](that func() (A, error)) Operator[A, A]
- func Ap[B, A any](fa A, faerr error) Operator[func(A) B, B]
- func BiMap[A, B any](f Endomorphism[error], g func(a A) B) Operator[A, B]
- func Bind[S1, S2, T any](setter func(T) func(S1) S2, f Kleisli[S1, T]) Operator[S1, S2]
- func BindL[S, T any](lens Lens[S, T], f Kleisli[T, T]) Operator[S, S]
- func BindTo[S1, T any](setter func(T) S1) Operator[T, S1]
- func Chain[A, B any](f Kleisli[A, B]) Operator[A, B]
- func ChainFirst[A, B any](f Kleisli[A, B]) Operator[A, A]
- func ChainTo[A, B any](b B, berr error) Operator[A, B]
- func FilterOrElse[A any](pred Predicate[A], onFalse func(A) error) Operator[A, A]
- func Flap[B, A any](a A) Operator[func(A) B, B]
- func Let[S1, S2, T any](key func(T) func(S1) S2, f func(S1) T) Operator[S1, S2]
- func LetL[S, T any](lens Lens[S, T], f Endomorphism[T]) Operator[S, S]
- func LetTo[S1, S2, T any](key func(T) func(S1) S2, t T) Operator[S1, S2]
- func LetToL[S, T any](lens Lens[S, T], b T) Operator[S, S]
- func Map[A, B any](f func(A) B) Operator[A, B]
- func MapLeft[A any](f Endomorphism[error]) Operator[A, A]
- func MapTo[A, B any](b B) Operator[A, B]
- func OrElse[A any](onLeft Kleisli[error, A]) Operator[A, A]
- type Option
- type Pointed
- type Predicate
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
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 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[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 ApV ¶
ApV applies a function wrapped in a Result to a value wrapped in a Result, accumulating errors using a semigroup instead of short-circuiting.
This function is designed for validation scenarios where you want to collect all validation errors rather than stopping at the first error. It differs from the standard Ap function in that it combines errors from both the function and the value using the provided semigroup operation.
The function works as follows:
- If both the value and the function have errors, it combines them using the semigroup
- If only one has an error, it returns that error
- If neither has an error, it applies the function to the value
Type Parameters:
- B: The result type after applying the function
- A: The input type to the function
Parameters:
- sg: A semigroup that defines how to combine two error values. The semigroup's Concat operation determines how errors are accumulated (e.g., concatenating error messages, merging error lists, etc.)
Returns:
- A curried function that takes a value (A, error), then takes a function (func(A) B, error), and returns the result (B, error) with accumulated errors
Behavior:
- Right + Right: Applies the function to the value and returns Right(result)
- Right + Left: Returns the Left error from the function
- Left + Right: Returns the Left error from the value
- Left + Left: Returns Left(sg.Concat(function_error, value_error))
Example:
import (
"errors"
"fmt"
"strings"
S "github.com/IBM/fp-go/v2/semigroup"
"github.com/IBM/fp-go/v2/idiomatic/result"
)
// Create a semigroup that combines errors by concatenating their messages
errorSemigroup := S.MakeSemigroup(func(e1, e2 error) error {
return fmt.Errorf("%v; %v", e1, e2)
})
// ApV with both function and value having errors
double := N.Mul(2)
apv := result.ApV[int, int](errorSemigroup)
value := result.Left[int](errors.New("invalid value"))
fn := result.Left[func(int) int](errors.New("invalid function"))
result := apv(value)(fn)
// Left(error: "invalid function; invalid value")
// ApV with successful application
goodValue, _ := result.Right(5)
goodFn, _ := result.Right(double)
result2 := apv(goodValue)(goodFn)
// Right(10)
func ChainOptionK ¶
ChainOptionK is the curried version of [MonadChainOptionK].
func Curry0 ¶
Curry0 converts a Go function that returns (R, error) into a curried version that returns (R, error).
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 (R, error).
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 ¶
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) (R, error)
Curry4 converts a 4-argument Go function that returns (R, error) into a curried version.
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 Eq ¶
Eq constructs an equality predicate for Result values (A, error). Two Result values are equal if they are both Left (error) with equal error values, or both Right (success) with equal values according to the provided equality predicate.
Parameters:
- eq: Equality predicate for the Right (success) type A
Returns a curried comparison function that takes two Result values and returns true if equal.
Example:
eq := result.Eq(eq.FromStrictEquals[int]()) result1 := eq(42, nil)(42, nil) // true result2 := eq(42, nil)(43, nil) // false
func Flow1 ¶
Flow1 creates a function that takes an initial value t0 and successively applies 1 functions where the input of a function is the return value of the previous function The final return value is the result of the last function application
func Flow2 ¶
func Flow2[F1 ~func(T0, error) (T1, error), F2 ~func(T1, error) (T2, error), T0, T1, T2 any](f1 F1, f2 F2) func(T0, error) (T2, error)
Flow2 creates a function that takes an initial value t0 and successively applies 2 functions where the input of a function is the return value of the previous function The final return value is the result of the last function application
func Flow3 ¶
func Flow3[F1 ~func(T0, error) (T1, error), F2 ~func(T1, error) (T2, error), F3 ~func(T2, error) (T3, error), T0, T1, T2, T3 any](f1 F1, f2 F2, f3 F3) func(T0, error) (T3, error)
Flow3 creates a function that takes an initial value t0 and successively applies 3 functions where the input of a function is the return value of the previous function The final return value is the result of the last function application
func Flow4 ¶
func Flow4[F1 ~func(T0, error) (T1, error), F2 ~func(T1, error) (T2, error), F3 ~func(T2, error) (T3, error), F4 ~func(T3, error) (T4, error), T0, T1, T2, T3, T4 any](f1 F1, f2 F2, f3 F3, f4 F4) func(T0, error) (T4, error)
Flow4 creates a function that takes an initial value t0 and successively applies 4 functions where the input of a function is the return value of the previous function The final return value is the result of the last function application
func Flow5 ¶
func Flow5[F1 ~func(T0, error) (T1, error), F2 ~func(T1, error) (T2, error), F3 ~func(T2, error) (T3, error), F4 ~func(T3, error) (T4, error), F5 ~func(T4, error) (T5, error), T0, T1, T2, T3, T4, T5 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(T0, error) (T5, error)
Flow5 creates a function that takes an initial value t0 and successively applies 5 functions where the input of a function is the return value of the previous function The final return value is the result of the last function application
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 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 FromStrictEquals ¶
func FromStrictEquals[A comparable]() func(A, error) func(A, error) bool
FromStrictEquals constructs an equality predicate using Go's == operator. The Right type must be comparable.
Example:
eq := result.FromStrictEquals[int]() result1 := eq(42, nil)(42, nil) // true result2 := eq(42, nil)(43, nil) // false
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 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 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 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 Pipe1 ¶
Pipe1 takes an initial value t0 and successively applies 1 function where the input of a function is the return value of the previous function. The final return value is the result of the last function application.
Example:
result, err := Pipe1(42, func(x int) (int, error) { return x * 2, nil }) // (84, nil)
func Pipe2 ¶
func Pipe2[F1 ~func(T0) (T1, error), F2 ~func(T1, error) (T2, error), T0, T1, T2 any](t0 T0, f1 F1, f2 F2) (T2, error)
Pipe2 takes an initial value t0 and successively applies 2 functions where the input of a function is the return value of the previous function The final return value is the result of the last function application
func Pipe3 ¶
func Pipe3[F1 ~func(T0) (T1, error), F2 ~func(T1, error) (T2, error), F3 ~func(T2, error) (T3, error), T0, T1, T2, T3 any](t0 T0, f1 F1, f2 F2, f3 F3) (T3, error)
Pipe3 takes an initial value t0 and successively applies 3 functions where the input of a function is the return value of the previous function The final return value is the result of the last function application
func Pipe4 ¶
func Pipe4[F1 ~func(T0) (T1, error), F2 ~func(T1, error) (T2, error), F3 ~func(T2, error) (T3, error), F4 ~func(T3, error) (T4, error), T0, T1, T2, T3, T4 any](t0 T0, f1 F1, f2 F2, f3 F3, f4 F4) (T4, error)
Pipe4 takes an initial value t0 and successively applies 4 functions where the input of a function is the return value of the previous function The final return value is the result of the last function application
func Pipe5 ¶
func Pipe5[F1 ~func(T0) (T1, error), F2 ~func(T1, error) (T2, error), F3 ~func(T2, error) (T3, error), F4 ~func(T3, error) (T4, error), F5 ~func(T4, error) (T5, error), T0, T1, T2, T3, T4, T5 any](t0 T0, f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) (T5, error)
Pipe5 takes an initial value t0 and successively applies 5 functions where the input of a function is the return value of the previous function The final return value is the result of the last function application
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 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 Sequence ¶
func Sequence[A, HKTA, HKTRA any]( mof func(A, error) HKTRA, mmap func(Kleisli[A, A]) func(HKTA) HKTRA, ) func(hkta HKTA, err error) 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 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 ToOption ¶
ToOption converts an Either to an Option, discarding the Left value.
Example:
result := either.ToOption(either.Right[error](42)) // Some(42)
result := either.ToOption(either.Left[int](errors.New("err"))) // None
func Traverse ¶
func Traverse[A, B, HKTB, HKTRB any]( mof func(B, error) HKTRB, mmap func(Kleisli[B, B]) func(HKTB) HKTRB, ) func(func(A) HKTB) func(A, error) 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 ¶
TraverseTuple1 converts a [Tuple1] of [A] via transformation functions transforming [A] to [Either[A]] into a [Either[Tuple1]].
func TraverseTuple10 ¶
func TraverseTuple10[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), F4 ~func(A4) (T4, error), F5 ~func(A5) (T5, error), F6 ~func(A6) (T6, error), F7 ~func(A7) (T7, error), F8 ~func(A8) (T8, error), F9 ~func(A9) (T9, error), F10 ~func(A10) (T10, error), 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(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, error)
TraverseTuple10 converts a [Tuple10] of [A] via transformation functions transforming [A] to [Either[A]] into a [Either[Tuple10]].
func TraverseTuple2 ¶
func TraverseTuple2[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), E, A1, T1, A2, T2 any](f1 F1, f2 F2) func(A1, A2) (T1, T2, error)
TraverseTuple2 converts a [Tuple2] of [A] via transformation functions transforming [A] to [Either[A]] into a [Either[Tuple2]].
func TraverseTuple3 ¶
func TraverseTuple3[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), E, A1, T1, A2, T2, A3, T3 any](f1 F1, f2 F2, f3 F3) func(A1, A2, A3) (T1, T2, T3, error)
TraverseTuple3 converts a [Tuple3] of [A] via transformation functions transforming [A] to [Either[A]] into a [Either[Tuple3]].
func TraverseTuple4 ¶
func TraverseTuple4[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), F4 ~func(A4) (T4, error), E, A1, T1, A2, T2, A3, T3, A4, T4 any](f1 F1, f2 F2, f3 F3, f4 F4) func(A1, A2, A3, A4) (T1, T2, T3, T4, error)
TraverseTuple4 converts a [Tuple4] of [A] via transformation functions transforming [A] to [Either[A]] into a [Either[Tuple4]].
func TraverseTuple5 ¶
func TraverseTuple5[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), F4 ~func(A4) (T4, error), F5 ~func(A5) (T5, error), E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(A1, A2, A3, A4, A5) (T1, T2, T3, T4, T5, error)
TraverseTuple5 converts a [Tuple5] of [A] via transformation functions transforming [A] to [Either[A]] into a [Either[Tuple5]].
func TraverseTuple6 ¶
func TraverseTuple6[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), F4 ~func(A4) (T4, error), F5 ~func(A5) (T5, error), F6 ~func(A6) (T6, error), 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(A1, A2, A3, A4, A5, A6) (T1, T2, T3, T4, T5, T6, error)
TraverseTuple6 converts a [Tuple6] of [A] via transformation functions transforming [A] to [Either[A]] into a [Either[Tuple6]].
func TraverseTuple7 ¶
func TraverseTuple7[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), F4 ~func(A4) (T4, error), F5 ~func(A5) (T5, error), F6 ~func(A6) (T6, error), F7 ~func(A7) (T7, error), 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(A1, A2, A3, A4, A5, A6, A7) (T1, T2, T3, T4, T5, T6, T7, error)
TraverseTuple7 converts a [Tuple7] of [A] via transformation functions transforming [A] to [Either[A]] into a [Either[Tuple7]].
func TraverseTuple8 ¶
func TraverseTuple8[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), F4 ~func(A4) (T4, error), F5 ~func(A5) (T5, error), F6 ~func(A6) (T6, error), F7 ~func(A7) (T7, error), F8 ~func(A8) (T8, error), 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(A1, A2, A3, A4, A5, A6, A7, A8) (T1, T2, T3, T4, T5, T6, T7, T8, error)
TraverseTuple8 converts a [Tuple8] of [A] via transformation functions transforming [A] to [Either[A]] into a [Either[Tuple8]].
func TraverseTuple9 ¶
func TraverseTuple9[F1 ~func(A1) (T1, error), F2 ~func(A2) (T2, error), F3 ~func(A3) (T3, error), F4 ~func(A4) (T4, error), F5 ~func(A5) (T5, error), F6 ~func(A6) (T6, error), F7 ~func(A7) (T7, error), F8 ~func(A8) (T8, error), F9 ~func(A9) (T9, error), 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(A1, A2, A3, A4, A5, A6, A7, A8, A9) (T1, T2, T3, T4, T5, T6, T7, T8, T9, error)
TraverseTuple9 converts a [Tuple9] of [A] via transformation functions transforming [A] to [Either[A]] into a [Either[Tuple9]].
func Uncurry0 ¶
Uncurry0 converts a function returning (R, error) 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 (R, error) 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 (R, error) back to Go's (R, error) style.
Types ¶
type Applicative ¶
type Endomorphism ¶
type Endomorphism[T any] = endomorphism.Endomorphism[T]
Endomorphism represents a function from a type to itself (T -> T).
type Functor ¶
type Functor[A, B any] interface { Map(f func(A) B) Operator[A, B] }
func MakeFunctor ¶
func MakeFunctor[A, B any]() Functor[A, B]
MakeFunctor creates a Functor instance for Result operations. A functor provides the Map operation that transforms values inside a context while preserving the structure.
Example:
f := result.MakeFunctor[int, string]() val, err := f.Map(strconv.Itoa)(result.Right[error](42)) // val is "42", err is nil
type Kleisli ¶
Kleisli represents a Kleisli arrow for the idiomatic Result pattern. It's a function from A to (B, error), following Go's idiomatic error handling.
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 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(
N.MoreThan(0),
func(x int) error { return errors.New("not positive") },
)
result := isPositive(42) // Right(42)
result := isPositive(-1) // Left(error)
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 TraverseArray ¶
func TraverseArray[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B]
TraverseArray transforms an array by applying a function that returns a Result (value, error) to each element. It processes elements from left to right, applying the function to each. If any element produces an error, the entire operation short-circuits and returns that error. Otherwise, it returns a successful result containing the array of all transformed values.
This is a convenience wrapper around TraverseArrayG for standard slice types.
Type Parameters:
- A: Source element type
- B: Target element type
Parameters:
- f: A Kleisli arrow (A) -> (B, error) that transforms each element
Returns:
- A Kleisli arrow ([]A) -> ([]B, error) that transforms the entire array
Example - Validate and transform:
validate := func(s string) (int, error) {
n, err := strconv.Atoi(s)
if err != nil {
return 0, err
}
if n < 0 {
return 0, errors.New("negative number")
}
return n * 2, nil
}
result := result.TraverseArray(validate)([]string{"1", "2", "3"})
// result is ([]int{2, 4, 6}, nil)
func TraverseArrayG ¶
func TraverseArrayG[GA ~[]A, GB ~[]B, A, B any](f Kleisli[A, B]) Kleisli[GA, GB]
TraverseArrayG transforms an array by applying a function that returns a Result (value, error) to each element. It processes elements from left to right, applying the function to each. If any element produces an error, the entire operation short-circuits and returns that error. Otherwise, it returns a successful result containing the array of all transformed values.
The G suffix indicates support for generic slice types (e.g., custom slice types based on []T).
Type Parameters:
- GA: Source slice type (must be based on []A)
- GB: Target slice type (must be based on []B)
- A: Source element type
- B: Target element type
Parameters:
- f: A Kleisli arrow (A) -> (B, error) that transforms each element
Returns:
- A Kleisli arrow (GA) -> (GB, error) that transforms the entire array
Behavior:
- Short-circuits on the first error encountered
- Preserves the order of elements
- Returns an empty slice for empty input
Example - Parse strings to integers:
parse := func(s string) (int, error) {
return strconv.Atoi(s)
}
result := result.TraverseArrayG[[]string, []int](parse)([]string{"1", "2", "3"})
// result is ([]int{1, 2, 3}, nil)
Example - Short-circuit on error:
result := result.TraverseArrayG[[]string, []int](parse)([]string{"1", "bad", "3"})
// result is ([]int(nil), error) - stops at "bad"
func TraverseArrayWithIndex ¶
TraverseArrayWithIndex transforms an array by applying an indexed function that returns a Result (value, error). The function receives both the zero-based index and the element for each iteration. If any element produces an error, the entire operation short-circuits and returns that error. Otherwise, it returns a successful result containing the array of all transformed values.
This is a convenience wrapper around TraverseArrayWithIndexG for standard slice types.
Type Parameters:
- A: Source element type
- B: Target element type
Parameters:
- f: An indexed function (int, A) -> (B, error) that transforms each element
Returns:
- A Kleisli arrow ([]A) -> ([]B, error) that transforms the entire array
Example - Validate with position info:
check := func(i int, s string) (string, error) {
if S.IsEmpty(s) {
return "", fmt.Errorf("empty value at position %d", i)
}
return strings.ToUpper(s), nil
}
result := result.TraverseArrayWithIndex(check)([]string{"a", "b", "c"})
// result is ([]string{"A", "B", "C"}, nil)
func TraverseArrayWithIndexG ¶
TraverseArrayWithIndexG transforms an array by applying an indexed function that returns a Result (value, error). The function receives both the zero-based index and the element for each iteration. If any element produces an error, the entire operation short-circuits and returns that error. Otherwise, it returns a successful result containing the array of all transformed values.
The G suffix indicates support for generic slice types (e.g., custom slice types based on []T).
Type Parameters:
- GA: Source slice type (must be based on []A)
- GB: Target slice type (must be based on []B)
- A: Source element type
- B: Target element type
Parameters:
- f: An indexed function (int, A) -> (B, error) that transforms each element
Returns:
- A Kleisli arrow (GA) -> (GB, error) that transforms the entire array
Behavior:
- Processes elements from left to right with their indices (0, 1, 2, ...)
- Short-circuits on the first error encountered
- Preserves the order of elements
Example - Annotate with index:
annotate := func(i int, s string) (string, error) {
if S.IsEmpty(s) {
return "", fmt.Errorf("empty string at index %d", i)
}
return fmt.Sprintf("[%d]=%s", i, s), nil
}
result := result.TraverseArrayWithIndexG[[]string, []string](annotate)([]string{"a", "b", "c"})
// result is ([]string{"[0]=a", "[1]=b", "[2]=c"}, nil)
func TraverseRecord ¶
func TraverseRecord[K comparable, A, B any](f Kleisli[A, B]) Kleisli[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, A, B any](f Kleisli[A, B]) Kleisli[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, A, B any](f func(K, A) (B, error)) Kleisli[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, A, B any](f func(K, A) (B, error)) Kleisli[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[R, A, ANY any](onCreate func() (R, error), onRelease Kleisli[R, ANY]) Kleisli[Kleisli[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 Monad ¶
type Monad[A, B any] interface { Applicative[A, B] Chainable[A, B] }
func MakeMonad ¶
func MakeMonad[A, B any]() Monad[A, B]
MakeMonad creates a Monad instance for Result operations. A monad combines the capabilities of Functor (Map), Applicative (Ap), and Chain (flatMap/bind). This allows for sequential composition of computations that may fail.
Example:
m := result.MakeMonad[int, string]()
val, err := m.Chain(func(x int) (string, error) {
if x > 0 {
return result.Right[error](strconv.Itoa(x))
}
return result.Left[string](errors.New("negative"))
})(result.Right[error](42))
// val is "42", err is nil
type Operator ¶
Operator represents a function that transforms one Result into another. It takes (A, error) and produces (B, error), following Go's idiomatic pattern.
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 BiMap ¶
BiMap is the curried version of [MonadBiMap]. Maps a pair of functions over the two type arguments of the bifunctor.
func Bind ¶
func Bind[S1, S2, T any]( setter func(T) func(S1) S2, f Kleisli[S1, T], ) Operator[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 BindL ¶
func BindL[S, T any]( lens Lens[S, T], f Kleisli[T, T], ) Operator[S, S]
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[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 BindTo ¶
func BindTo[S1, T any]( setter func(T) S1, ) Operator[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[A, B any](f Kleisli[A, B]) Operator[A, B]
Chain is the curried version of [MonadChain]. Sequences two computations where the second depends on the first.
func ChainFirst ¶
func ChainFirst[A, B any](f Kleisli[A, B]) Operator[A, A]
ChainFirst is the curried version of [MonadChainFirst].
func FilterOrElse ¶ added in v2.1.0
FilterOrElse filters a Result value based on a predicate in an idiomatic style. If the Result is Ok and the predicate returns true, returns the original Ok. If the Result is Ok and the predicate returns false, returns Error with the error from onFalse. If the Result is Error, returns the original Error without applying the predicate.
This is the idiomatic version that returns an Operator for use in method chaining. It's useful for adding validation to successful results, converting them to errors if they don't meet certain criteria.
Example:
import (
R "github.com/IBM/fp-go/v2/idiomatic/result"
N "github.com/IBM/fp-go/v2/number"
)
isPositive := N.MoreThan(0)
onNegative := func(x int) error { return fmt.Errorf("%d is not positive", x) }
result := R.Of(5).
Pipe(R.FilterOrElse(isPositive, onNegative)) // Ok(5)
result2 := R.Of(-3).
Pipe(R.FilterOrElse(isPositive, onNegative)) // Error(error: "-3 is not positive")
func Flap ¶
func Flap[B, A any](a A) Operator[func(A) B, B]
Flap is the curried version of [MonadFlap].
func Let ¶
func Let[S1, S2, T any]( key func(T) func(S1) S2, f func(S1) T, ) Operator[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 LetL ¶
func LetL[S, T any]( lens Lens[S, T], f Endomorphism[T], ) Operator[S, S]
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 LetTo ¶
func LetTo[S1, S2, T any]( key func(T) func(S1) S2, t T, ) Operator[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 LetToL ¶
func LetToL[S, T any]( lens Lens[S, T], b T, ) Operator[S, S]
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})
func Map ¶
func Map[A, B any](f func(A) B) Operator[A, B]
Map is the curried version of [MonadMap]. Transforms the Right value using the provided function.
func MapLeft ¶
MapLeft is the curried version of [MonadMapLeft]. Applies a mapping function to the Left (error) channel.
type Option ¶
Option is a type alias for option.Option, provided for convenience when working with Result and Option together.
type Pointed ¶
func MakePointed ¶
func MakePointed[A any]() Pointed[A]
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)
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. |