result

package
v2.1.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

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

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ApS

func ApS[S1, S2, T any](
	setter func(T) func(S1) S2,
) func(T, error) Operator[S1, S2]

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

func ApSL[S, T any](
	lens Lens[S, T],
) func(T, error) Operator[S, S]

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

func ApV[B, A any](sg S.Semigroup[error]) func(A, error) Operator[func(A) B, B]

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

func ChainOptionK[A, B any](onNone func() error) func(option.Kleisli[A, B]) Operator[A, B]

ChainOptionK is the curried version of [MonadChainOptionK].

func Curry0

func Curry0[R any](f func() (R, error)) func() (R, error)

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

func Curry1[T1, R any](f func(T1) (R, error)) func(T1) (R, error)

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

func Curry2[T1, T2, R any](f func(T1, T2) (R, error)) func(T1) func(T2) (R, error)

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) (R, error)

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

func Do[S any](
	empty S,
) (S, error)

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

func Eq[A any](eq EQ.Eq[A]) func(A, error) func(A, error) bool

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

func Flow1[F1 ~func(T0, error) (T1, error), T0, T1 any](f1 F1) func(T0, error) (T1, error)

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

func Fold[A, B any](onLeft func(error) B, onRight func(A) B) func(A, error) B

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

func FromOption[A any](onNone func() error) func(A, bool) (A, error)

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

func GetOrElse[A any](onLeft func(error) A) func(A, error) A

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

func IsLeft[A any](_ A, err error) bool

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

func IsRight[A any](_ A, err error) bool

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

func Left[A any](err error) (A, error)

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

func Logger[A any](loggers ...*log.Logger) func(string) Operator[A, A]

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 Memoize

func Memoize[A any](a A, err error) (A, error)

Memoize returns the Either unchanged (Either values are already memoized).

func Of

func Of[A any](a A) (A, error)

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

func Pipe1[F1 ~func(T0) (T1, error), T0, T1 any](t0 T0, f1 F1) (T1, error)

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

func Reduce[A, B any](f func(B, A) B, initial B) func(A, error) B

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[A any](a A) (A, error)

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

func ToError[A any](_ A, err error) error

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

func ToOption[A any](a A, aerr error) (A, bool)

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 ToString

func ToString[A any](a A, err error) string

String prints some debug info for the object

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

func TraverseTuple1[F1 ~func(A1) (T1, error), E, A1, T1 any](f1 F1) func(A1) (T1, error)

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

func Uncurry0[R any](f func() (R, error)) func() (R, error)

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

func Uncurry1[T1, R any](f func(T1) (R, error)) func(T1) (R, error)

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

func Uncurry2[T1, T2, R any](f func(T1) func(T2) (R, error)) func(T1, T2) (R, error)

Uncurry2 converts a curried function returning (R, error) back to Go's (R, error) style.

func Uncurry3

func Uncurry3[T1, T2, T3, R any](f func(T1) func(T2) func(T3) (R, error)) func(T1, T2, T3) (R, error)

Uncurry3 converts a curried function returning (R, error) 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) (R, error)) func(T1, T2, T3, T4) (R, error)

Uncurry4 converts a curried function returning (R, error) back to Go's (R, error) style.

Types

type Applicative

type Applicative[A, B any] interface {
	Apply[A, B]
	Pointed[A]
}

type Apply

type Apply[A, B any] interface {
	Functor[A, B]
	Ap(A, error) Operator[func(A) B, B]
}

type Chainable

type Chainable[A, B any] interface {
	Apply[A, B]
	Chain(Kleisli[A, B]) Operator[A, B]
}

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

type Kleisli[A, B any] = func(A) (B, error)

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

func FromError[A any](f func(a A) error) Kleisli[A, A]

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

func FromNillable[A any](e error) Kleisli[*A, *A]

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

func FromPredicate[A any](pred func(A) bool, onFalse func(A) error) Kleisli[A, A]

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

func ToType[A any](onError func(any) error) Kleisli[any, A]

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

func TraverseArrayWithIndex[A, B any](f func(int, A) (B, error)) Kleisli[[]A, []B]

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

func TraverseArrayWithIndexG[GA ~[]A, GB ~[]B, A, B any](f func(int, A) (B, error)) Kleisli[GA, GB]

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 Lens

type Lens[S, T any] = lens.Lens[S, T]

Lens is an optic that focuses on a field of type T within a structure of type S.

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

type Operator[A, B any] = func(A, error) (B, error)

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

func Alt[A any](that func() (A, error)) Operator[A, A]

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

func Ap[B, A any](fa A, faerr error) Operator[func(A) B, B]

Ap is the curried version of [MonadAp]. Returns a function that applies a wrapped function to the given wrapped value.

func BiMap

func BiMap[A, B any](f Endomorphism[error], g func(a A) B) Operator[A, B]

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 ChainTo

func ChainTo[A, B any](b B, berr error) Operator[A, B]

ChainTo is the curried version of [MonadChainTo].

func FilterOrElse added in v2.1.0

func FilterOrElse[A any](pred Predicate[A], onFalse func(A) error) Operator[A, A]

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

func MapLeft[A any](f Endomorphism[error]) Operator[A, A]

MapLeft is the curried version of [MonadMapLeft]. Applies a mapping function to the Left (error) channel.

func MapTo

func MapTo[A, B any](b B) Operator[A, B]

MapTo is the curried version of [MonadMapTo].

func OrElse

func OrElse[A any](onLeft Kleisli[error, A]) Operator[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)

type Option

type Option[A any] = option.Option[A]

Option is a type alias for option.Option, provided for convenience when working with Result and Option together.

type Pointed

type Pointed[A any] interface {
	Of(a A) (A, error)
}

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)

type Predicate added in v2.1.0

type Predicate[A any] = predicate.Predicate[A]

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL