iterresult

package
v2.3.5 Latest Latest
Warning

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

Go to latest
Published: May 15, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package iterresult provides the SeqResult type, which represents an iterator that yields Result values, combining iteration with error handling.

SeqResult[A] is defined as iter.Seq[Result[A]], representing a sequence of values that can each be either an error or a success value of type A.

Fantasy Land Specification

This package implements a monad transformer combining iteration with Result for error handling. It follows the Fantasy Land specification for functional programming patterns.

Implemented algebras:

  • Functor: Map operations over successful values
  • Bifunctor: Map operations over both error and success values
  • Apply: Apply wrapped functions to wrapped values
  • Applicative: Lift pure values into the context
  • Chain: Sequence dependent computations
  • Monad: Full monadic operations
  • Alt: Alternative computations for error recovery

Core Concepts

SeqResult combines two powerful abstractions:

  • Iteration: Processing sequences of values lazily
  • Result: Representing computations that can fail with typed errors

This allows for elegant error handling in iterator pipelines, where each element can independently succeed or fail, and operations can be chained while preserving error information.

Common Use Cases

  • Processing streams of data where individual items may fail
  • Parsing sequences where each element requires validation
  • Transforming collections with operations that can error
  • Building pipelines with graceful error propagation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ChainOptionK

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

func Fold

func Fold[A, B any](onLeft iter.Kleisli[error, B], onRight iter.Kleisli[A, B]) func(SeqResult[A]) Seq[B]

Fold converts a SeqResult into a Seq by providing handlers for both the error and success cases

func Functor

func Functor[A, B any]() functor.Functor[A, B, SeqResult[A], SeqResult[B]]

Functor implements the monadic operations for SeqResult

func GetOrElse

func GetOrElse[A any](onLeft iter.Kleisli[error, A]) func(SeqResult[A]) Seq[A]

GetOrElse extracts the value from a successful SeqResult or computes a default value from the error

func GetOrElseOf

func GetOrElseOf[A any](onLeft func(error) A) func(SeqResult[A]) Seq[A]

GetOrElseOf extracts the value from a successful SeqResult or computes a default value from the error

func Monad

func Monad[A, B any]() monad.Monad[A, B, SeqResult[A], SeqResult[B], SeqResult[func(A) B]]

Monad implements the monadic operations for SeqResult

func Pointed

func Pointed[A any]() pointed.Pointed[A, SeqResult[A]]

Pointed implements the pointed operations for SeqResult

func Reduce

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

Reduce returns a function that reduces a SeqResult to a single Result value. This is the curried version of MonadReduce.

The return type is IOResult because a SeqResult represents a dynamic lazy sequence of Result values. Reducing it requires consuming the iterator, so the final Result must also remain deferred as a lazy effect. IOResult is the single-value counterpart to SeqResult: both are lazy, and both represent work that is only performed when evaluated.

Type Parameters:

  • A: The element type in the sequence
  • B: The accumulator and result type

Parameters:

  • f: The reducer function that combines the accumulator with each element
  • initial: The initial accumulator value

Returns:

  • A function that takes a SeqResult and returns IOResult[B]

Example:

sum := Reduce(func(acc, x int) int { return acc + x }, 0)
seq := func(yield func(Result[int]) bool) {
    yield(Right(1))
    yield(Right(2))
    yield(Right(3))
}
resultIO := sum(seq)
result := resultIO()
// returns: Right(6)

func TraverseParTuple1

func TraverseParTuple1[F1 ~func(A1) SeqResult[T1], T1, A1 any](f1 F1) func(tuple.Tuple1[A1]) SeqResult[tuple.Tuple1[T1]]

TraverseParTuple1 converts a [tuple.Tuple1[A1]] into a [SeqResult[tuple.Tuple1[T1]]]

func TraverseSeqTuple1

func TraverseSeqTuple1[F1 ~func(A1) SeqResult[T1], T1, A1 any](f1 F1) func(tuple.Tuple1[A1]) SeqResult[tuple.Tuple1[T1]]

TraverseSeqTuple1 converts a [tuple.Tuple1[A1]] into a [SeqResult[tuple.Tuple1[T1]]]

func TraverseTuple1

func TraverseTuple1[F1 ~func(A1) SeqResult[T1], T1, A1 any](f1 F1) func(tuple.Tuple1[A1]) SeqResult[tuple.Tuple1[T1]]

TraverseTuple1 converts a [tuple.Tuple1[A1]] into a [SeqResult[tuple.Tuple1[T1]]]

func TraverseTuple2

func TraverseTuple2[F1 ~func(A1) SeqResult[T1], F2 ~func(A2) SeqResult[T2], T1, T2, A1, A2 any](f1 F1, f2 F2) func(tuple.Tuple2[A1, A2]) SeqResult[tuple.Tuple2[T1, T2]]

TraverseTuple2 converts a [tuple.Tuple2[A1, A2]] into a [SeqResult[tuple.Tuple2[T1, T2]]]

func TraverseTuple3

func TraverseTuple3[F1 ~func(A1) SeqResult[T1], F2 ~func(A2) SeqResult[T2], F3 ~func(A3) SeqResult[T3], T1, T2, T3, A1, A2, A3 any](f1 F1, f2 F2, f3 F3) func(tuple.Tuple3[A1, A2, A3]) SeqResult[tuple.Tuple3[T1, T2, T3]]

TraverseTuple3 converts a [tuple.Tuple3[A1, A2, A3]] into a [SeqResult[tuple.Tuple3[T1, T2, T3]]]

func TraverseTuple4

func TraverseTuple4[F1 ~func(A1) SeqResult[T1], F2 ~func(A2) SeqResult[T2], F3 ~func(A3) SeqResult[T3], F4 ~func(A4) SeqResult[T4], T1, T2, T3, T4, A1, A2, A3, A4 any](f1 F1, f2 F2, f3 F3, f4 F4) func(tuple.Tuple4[A1, A2, A3, A4]) SeqResult[tuple.Tuple4[T1, T2, T3, T4]]

TraverseTuple4 converts a [tuple.Tuple4[A1, A2, A3, A4]] into a [SeqResult[tuple.Tuple4[T1, T2, T3, T4]]]

func TraverseTuple5

func TraverseTuple5[F1 ~func(A1) SeqResult[T1], F2 ~func(A2) SeqResult[T2], F3 ~func(A3) SeqResult[T3], F4 ~func(A4) SeqResult[T4], F5 ~func(A5) SeqResult[T5], T1, T2, T3, T4, T5, A1, A2, A3, A4, A5 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(tuple.Tuple5[A1, A2, A3, A4, A5]) SeqResult[tuple.Tuple5[T1, T2, T3, T4, T5]]

TraverseTuple5 converts a [tuple.Tuple5[A1, A2, A3, A4, A5]] into a [SeqResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]

func TraverseTuple6

func TraverseTuple6[F1 ~func(A1) SeqResult[T1], F2 ~func(A2) SeqResult[T2], F3 ~func(A3) SeqResult[T3], F4 ~func(A4) SeqResult[T4], F5 ~func(A5) SeqResult[T5], F6 ~func(A6) SeqResult[T6], T1, T2, T3, T4, T5, T6, A1, A2, A3, A4, A5, A6 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6) func(tuple.Tuple6[A1, A2, A3, A4, A5, A6]) SeqResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]

TraverseTuple6 converts a [tuple.Tuple6[A1, A2, A3, A4, A5, A6]] into a [SeqResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]

func TraverseTuple7

func TraverseTuple7[F1 ~func(A1) SeqResult[T1], F2 ~func(A2) SeqResult[T2], F3 ~func(A3) SeqResult[T3], F4 ~func(A4) SeqResult[T4], F5 ~func(A5) SeqResult[T5], F6 ~func(A6) SeqResult[T6], F7 ~func(A7) SeqResult[T7], T1, T2, T3, T4, T5, T6, T7, A1, A2, A3, A4, A5, A6, A7 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7) func(tuple.Tuple7[A1, A2, A3, A4, A5, A6, A7]) SeqResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]

TraverseTuple7 converts a [tuple.Tuple7[A1, A2, A3, A4, A5, A6, A7]] into a [SeqResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]

func TraverseTuple8

func TraverseTuple8[F1 ~func(A1) SeqResult[T1], F2 ~func(A2) SeqResult[T2], F3 ~func(A3) SeqResult[T3], F4 ~func(A4) SeqResult[T4], F5 ~func(A5) SeqResult[T5], F6 ~func(A6) SeqResult[T6], F7 ~func(A7) SeqResult[T7], F8 ~func(A8) SeqResult[T8], T1, T2, T3, T4, T5, T6, T7, T8, A1, A2, A3, A4, A5, A6, A7, A8 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8) func(tuple.Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]) SeqResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]

TraverseTuple8 converts a [tuple.Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]] into a [SeqResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]

func TraverseTuple9

func TraverseTuple9[F1 ~func(A1) SeqResult[T1], F2 ~func(A2) SeqResult[T2], F3 ~func(A3) SeqResult[T3], F4 ~func(A4) SeqResult[T4], F5 ~func(A5) SeqResult[T5], F6 ~func(A6) SeqResult[T6], F7 ~func(A7) SeqResult[T7], F8 ~func(A8) SeqResult[T8], F9 ~func(A9) SeqResult[T9], T1, T2, T3, T4, T5, T6, T7, T8, T9, A1, A2, A3, A4, A5, A6, A7, A8, A9 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9) func(tuple.Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]) SeqResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]

TraverseTuple9 converts a [tuple.Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]] into a [SeqResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]

func TraverseTuple10

func TraverseTuple10[F1 ~func(A1) SeqResult[T1], F2 ~func(A2) SeqResult[T2], F3 ~func(A3) SeqResult[T3], F4 ~func(A4) SeqResult[T4], F5 ~func(A5) SeqResult[T5], F6 ~func(A6) SeqResult[T6], F7 ~func(A7) SeqResult[T7], F8 ~func(A8) SeqResult[T8], F9 ~func(A9) SeqResult[T9], F10 ~func(A10) SeqResult[T10], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10) func(tuple.Tuple10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10]) SeqResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]

TraverseTuple10 converts a [tuple.Tuple10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10]] into a [SeqResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]

Types

type Endomorphism

type Endomorphism[T any] = endomorphism.Endomorphism[T]

Endomorphism represents a function from a type to itself. It represents transformations that preserve the type.

Type Parameters:

  • T: The type being transformed

Example:

increment := func(x int) int { return x + 1 }
// increment is an Endomorphism[int]

type IO added in v2.3.0

type IO[T any] = io.IO[T]

IO represents a computation that performs side effects and returns a value of type T. IO computations are lazy - they don't execute until explicitly called. This allows for composing side-effecting operations in a pure, functional way.

Type Parameters:

  • T: The type of value produced by the IO computation

Example:

getCurrentTime := func() time.Time { return time.Now() }
// getCurrentTime is an IO[time.Time]

type IOResult added in v2.3.0

type IOResult[T any] = ioresult.IOResult[T]

IOResult represents an IO computation that can either fail with an error or succeed with a value of type T. It combines the side-effect handling of IO with the error handling of Result.

This is useful for operations that perform I/O and may fail, providing a type-safe alternative to returning (T, error) tuples.

Type Parameters:

  • T: The success type

Example:

readFile := func() result.Result[string] {
    data, err := os.ReadFile("config.txt")
    if err != nil {
        return result.Left(err)
    }
    return result.Of(string(data))
}
// readFile is an IOResult[string]

func Collect added in v2.3.0

func Collect[T any](fa SeqResult[T]) IOResult[[]T]

Collect materializes a SeqResult into a Result containing a slice. It consumes all elements from the sequence, collecting successful values into a slice. If any error is encountered during iteration, collection stops immediately and returns that error.

The return type is IOResult because collecting a SeqResult is a reduction over a dynamic lazy source. The final Result is not available until iteration has happened, so it must stay deferred. IOResult is the single-value counterpart to SeqResult: both are lazy, and both represent work that is only performed when evaluated.

Type Parameters:

  • T: The type of elements in the sequence

Parameters:

  • fa: The SeqResult to collect into a slice

Returns:

  • IOResult[[]T]: A deferred computation that yields the first error encountered or a slice of all values

Example - Success case:

seq := func(yield func(Result[int]) bool) {
    yield(Right(1))
    yield(Right(2))
    yield(Right(3))
}
resultIO := Collect(seq)
result := resultIO()
// result = Right([]int{1, 2, 3})

Example - Error case:

seq := func(yield func(Result[int]) bool) {
    yield(Right(1))
    yield(Left[int](errors.New("error")))
    yield(Right(3))
}
resultIO := Collect(seq)
result := resultIO()
// result = Left(error: "error")

Example - Empty sequence:

seq := iter.Empty[Result[int]]()
resultIO := Collect(seq)
result := resultIO()
// result = Right([]int{})

See Also:

  • MonadReduce: Reduces a SeqResult to a single value
  • Fold: Converts SeqResult to Seq by handling both cases
  • GetOrElse: Extracts value or provides default

func MonadReduce

func MonadReduce[A, B any](fa SeqResult[A], f func(B, A) B, initial B) IOResult[B]

MonadReduce reduces a SeqResult to a single Result value by applying a function to each Right element and an accumulator, starting with an initial value. If any Left is encountered, reduction stops immediately and returns that Left value.

Type Parameters:

  • E: The error type
  • A: The element type in the sequence
  • B: The accumulator and result type

Parameters:

  • fa: The SeqResult to reduce
  • f: The reducer function that combines the accumulator with each element
  • initial: The initial accumulator value

Returns:

  • Result[B]: Left with the first error encountered, or Right with the final accumulated value

Marble Diagram:

Input:  --R(1)--R(2)--R(3)--R(4)--R(5)--|
Reduce((acc, x) => acc + x, 0)
Output: Right(15)

Input:  --R(1)--R(2)--L(e)--R(4)--R(5)--|
Reduce((acc, x) => acc + x, 0)
Output: Left(e)

Example:

seq := func(yield func(Result[int]) bool) {
    yield(Right(1))
    yield(Right(2))
    yield(Right(3))
}
sum := MonadReduce(seq, func(acc, x int) int { return acc + x }, 0)
// returns: Right(6)

seqWithError := func(yield func(Result[int]) bool) {
    yield(Right(1))
    yield(Left[int](errors.New("error")))
    yield(Right(3))
}
result := MonadReduce(seqWithError, func(acc, x int) int { return acc + x }, 0)
// returns: Left(error: "error")

type Kleisli

type Kleisli[A, B any] = R.Reader[A, SeqResult[B]]

Kleisli represents a function that takes a value and returns a SeqResult. This is the monadic bind operation for SeqResult, enabling composition of computations that may produce sequences of results or errors.

Type Parameters:

  • A: The input type
  • B: The element type of the output sequence

Example:

validate := func(x int) SeqResult[int] {
    if x > 0 {
        return Of(x)
    }
    return Left[int](errors.New("must be positive"))
}
// validate is a Kleisli[int, int]

func FromOption

func FromOption[A any](onNone Lazy[error]) Kleisli[O.Option[A], A]

func TraverseArray

func TraverseArray[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B]

TraverseArray transforms an array

func TraverseArrayWithIndex

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

TraverseArrayWithIndex transforms an array

func TraverseRecord

func TraverseRecord[K comparable, A, B any](f Kleisli[A, B]) Kleisli[map[K]A, map[K]B]

TraverseRecord transforms a record

func TraverseRecordWithIndex

func TraverseRecordWithIndex[K comparable, A, B any](f func(K, A) SeqResult[B]) Kleisli[map[K]A, map[K]B]

TraverseRecordWithIndex transforms a record

func WithResource

func WithResource[A, R, ANY any](onCreate SeqResult[R], onRelease Kleisli[R, ANY]) Kleisli[Kleisli[R, A], A]

WithResource constructs a function that safely manages a resource with automatic cleanup. It creates a resource, operates on it, and ensures the resource is released even if an error occurs.

type Lazy

type Lazy[A any] = lazy.Lazy[A]

Lazy represents a deferred computation that produces a value of type A. The computation is not executed until the Lazy value is called. This is an alias for IO and provides semantic clarity when working with lazy evaluations that don't necessarily involve side effects.

Type Parameters:

  • A: The type of value produced by the lazy computation

Example:

expensiveCalc := func() int {
    // Expensive computation
    return 42
}
// expensiveCalc is a Lazy[int]

type Monoid

type Monoid[A any] = itereither.Monoid[error, A]

func ApplicativeMonoid

func ApplicativeMonoid[A any](
	m monoid.Monoid[A],
) Monoid[A]

ApplicativeMonoid returns a Monoid that concatenates SeqResult instances via their applicative

type Operator

type Operator[A, B any] = Kleisli[SeqResult[A], B]

Operator represents a transformation from one SeqResult to another. It takes a SeqResult[A] and returns a SeqResult[B], allowing for composition of sequence transformations in a functional pipeline.

Type Parameters:

  • A: The element type of the input sequence
  • B: The element type of the output sequence

Example:

double := Map(func(x int) int { return x * 2 })
// double is an Operator[int, int]

func Alt

func Alt[A any](second Lazy[SeqResult[A]]) Operator[A, A]

Alt returns a function that provides an alternative SeqResult computation if the first one fails

func Ap

func Ap[B, A any](ma SeqResult[A]) Operator[func(A) B, B]

Ap applies a function wrapped in a SeqResult to a value wrapped in a SeqResult. This is an alias of ApPar which applies the function and value in parallel.

func ApFirst

func ApFirst[A, B any](second SeqResult[B]) Operator[A, A]

ApFirst combines two effectful actions, keeping only the result of the first.

Marble diagram:

First:  ---R(1)---R(2)---|
Second: ---R(10)---R(20)---|
Output: ---R(1)---R(2)---|

If either sequence contains a Left, the error is propagated.

func ApS

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

ApS attaches a value to a context S1 to produce a context S2 by considering the context and the value concurrently (using Applicative rather than Monad). This allows independent computations to be combined without one depending on the result of the other.

Unlike Bind, which sequences operations, ApS can be used when operations are independent and can conceptually run in parallel.

Example:

type State struct {
    User  User
    Posts []Post
}

// These operations are independent and can be combined with ApS
getUser := Right(User{ID: 1, Name: "Alice"})
getPosts := Right([]Post{{ID: 1, Title: "Hello"}})

result := F.Pipe2(
    Do(State{}),
    ApS(
        func(user User) func(State) State {
            return func(s State) State { s.User = user; return s }
        },
        getUser,
    ),
    ApS(
        func(posts []Post) func(State) State {
            return func(s State) State { s.Posts = posts; return s }
        },
        getPosts,
    ),
)

func ApSL

func ApSL[S, T any](
	lens L.Lens[S, T],
	fa SeqResult[T],
) 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.

Example:

type Config struct {
    Host string
    Port int
}

portLens := lens.MakeLens(
    func(c Config) int { return c.Port },
    func(c Config, p int) Config { c.Port = p; return c },
)

result := F.Pipe1(
    Of(Config{Host: "localhost"}),
    ApSL(portLens, Of(8080)),
)

func ApSecond

func ApSecond[A, B any](second SeqResult[B]) Operator[A, B]

ApSecond combines two effectful actions, keeping only the result of the second.

Marble diagram:

First:  ---R(1)---R(2)---|
Second: ---R(10)---R(20)---|
Output: ---R(10)---R(20)---|

If either sequence contains a Left, the error is propagated.

func BiMap

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

BiMap returns a function that 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 sequential composition where each step can depend on the results of previous steps.

The setter function takes the result of the computation and returns a function that updates the context from S1 to S2.

Example:

type State struct {
    User  User
    Posts []Post
}

result := F.Pipe2(
    Do(State{}),
    Bind(
        func(user User) func(State) State {
            return func(s State) State { s.User = user; return s }
        },
        func(s State) SeqResult[User] {
            return FromEither(result.Eitherize1(fetchUser)())
        },
    ),
    Bind(
        func(posts []Post) func(State) State {
            return func(s State) State { s.Posts = posts; return s }
        },
        func(s State) SeqResult[[]Post] {
            return FromEither(result.Eitherize1(fetchPostsForUser)(s.User.ID))
        },
    ),
)

func BindL

func BindL[S, T any](
	lens L.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 a SeqResult that produces the new 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 := func(v int) SeqResult[int] {
    return FromEither(result.TryCatch(func() (int, error) {
        if v >= 100 {
            return 0, errors.New("overflow")
        }
        return v + 1, nil
    }))
}

result := F.Pipe1(
    Of(Counter{Value: 42}),
    BindL(valueLens, increment),
)

func BindTo

func BindTo[S1, T any](
	setter func(T) S1,
) Operator[T, S1]

BindTo initializes a new state S1 from a value T

func Chain

func Chain[A, B any](f Kleisli[A, B]) Operator[A, B]

Chain returns a function that sequences two SeqResult computations

func ChainEitherK

func ChainEitherK[A, B any](f result.Kleisli[A, B]) Operator[A, B]

func ChainFirst

func ChainFirst[A, B any](f Kleisli[A, B]) Operator[A, A]

ChainFirst returns a function that executes a side-effecting SeqResult computation but returns the original value

func ChainFirstEitherK

func ChainFirstEitherK[A, B any](f either.Kleisli[error, A, B]) Operator[A, A]

ChainFirstEitherK returns a function that executes a side-effecting Result computation but returns the original value

func ChainFirstLeft

func ChainFirstLeft[A, B any](f Kleisli[error, B]) Operator[A, A]

ChainFirstLeft is the curried version of MonadChainFirstLeft. It returns a function that chains a computation on the left (error) side while always preserving the original error.

This is particularly useful for adding error handling side effects (like logging, metrics, or notifications) in a functional pipeline. The original error is always returned regardless of what f returns (Left or Right), ensuring the error path is preserved.

Parameters:

  • f: A function that takes an error of type EA and returns a SeqResult (typically for side effects)

Returns:

  • An Operator that performs the side effect but always returns the original error if input was Left

Example:

// Create a reusable error logger
logError := ChainFirstLeft(func(err error) SeqResult[int] {
    log.Printf("Error: %s", err)
    return Right(0)
})

result := F.Pipe1(
    Left[int](errors.New("validation failed")),
    logError, // logs the error
)
// result is always Left(error: "validation failed"), even though f returns Right

func ChainFirstResultK

func ChainFirstResultK[A, B any](f result.Kleisli[A, B]) Operator[A, A]

ChainFirstResultK returns a function that executes a side-effecting Result computation but returns the original value

func ChainLeft

func ChainLeft[A any](f Kleisli[error, A]) Operator[A, A]

ChainLeft is the curried version of MonadChainLeft. It returns a function that chains a computation on the left (error) side of a SeqResult.

Note: ChainLeft is identical to OrElse - both provide the same functionality for error recovery.

This is particularly useful in functional composition pipelines where you want to handle errors by performing another computation that may also fail.

Parameters:

  • f: A function that takes an error of type EA and returns a SeqResult with error type EB

Returns:

  • A function that transforms a SeqResult with error type EA to one with error type EB

Example:

// Create a reusable error handler
recoverFromNetworkError := ChainLeft(func(err error) SeqResult[int] {
    if strings.Contains(err.Error(), "network") {
        return Right(0) // return default value
    }
    return Left[int](err) // propagate other errors
})

result := F.Pipe1(
    Left[int](errors.New("network timeout")),
    recoverFromNetworkError,
)

func ChainSeqK

func ChainSeqK[A, B any](f iter.Kleisli[A, B]) Operator[A, B]

func ChainTo

func ChainTo[A, B any](fb SeqResult[B]) Operator[A, B]

ChainTo returns a function that sequences two SeqResult computations, discarding the result of the first

func ChainToSeq

func ChainToSeq[A, B any](fb Seq[B]) Operator[A, B]

ChainToSeq returns a function that sequences a SeqResult with a Seq, discarding the result of the first

func Filter added in v2.3.1

func Filter[A any](pred func(A) bool) Operator[A, A]

Filter returns a function that filters SeqResult elements based on a predicate. This is the curried version of MonadFilter, useful for creating reusable filter operations.

The returned function keeps only Ok values that satisfy the predicate, while passing all error values through unchanged. Ok values that fail the predicate are removed from the sequence.

Type Parameters:

  • A: The type of the Ok value (success type)

Parameters:

  • pred: A predicate function that tests Ok values

Returns:

  • An Operator that filters SeqResult sequences based on the predicate

Example:

import (
    R "github.com/IBM/fp-go/v2/result"
    "github.com/IBM/fp-go/v2/iterator/iter"
)

// Create a reusable filter for even numbers
evens := iterresult.Filter(func(x int) bool { return x%2 == 0 })

seq1 := iter.From(R.Of(1), R.Of(2), R.Of(3))
result1 := evens(seq1)
// yields: Ok(2)

seq2 := iter.From(R.Of(4), R.Error[int](errors.New("error")), R.Of(5))
result2 := evens(seq2)
// yields: Ok(4), Err(error)

See Also:

MonadFilter is the non-curried version. FilterOrElse converts failing values to errors instead of removing them.

func FilterOrElse

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

FilterOrElse filters a SeqResult value based on a predicate. If the predicate returns true for the Right value, it passes through unchanged. If the predicate returns false, it transforms the Right value into a Left using onFalse. Left values are passed through unchanged.

This is useful for adding validation or constraints to successful computations, converting values that don't meet certain criteria into errors.

Marble diagram:

Input:  ---R(5)---R(-3)---L(e)---R(10)---|
pred(x) = x > 0
onFalse(x) = "negative: " + x
Output: ---R(5)---L("negative: -3")---L(e)---R(10)---|

Where R(x) represents Right(x) and L(e) represents Left(e). Values that fail the predicate are converted to Left.

Parameters:

  • pred: A predicate function that tests the Right value
  • onFalse: A function that converts the failing value into an error of type E

Returns:

  • An Operator that filters SeqResult values based on the predicate

Example:

// Validate that a number is positive
isPositive := func(x int) bool { return x > 0 }
onNegative := func(x int) error { return fmt.Errorf("%d is not positive", x) }

validatePositive := FilterOrElse(isPositive, onNegative)

result1 := validatePositive(Right(42))  // Right(42)
result2 := validatePositive(Right(-5))  // Left(error: "-5 is not positive")
result3 := validatePositive(Left[int](errors.New("error"))) // Left(error: "error")

func Flap

func Flap[B, A any](a A) Operator[func(A) B, B]

Flap returns a function that applies a value to a function wrapped in a SeqResult

func Let

func Let[S1, S2, T any](
	setter func(T) func(S1) S2,
	f func(S1) T,
) Operator[S1, S2]

Let attaches the result of a computation to a context S1 to produce a context S2

func LetL

func LetL[S, T any](
	lens L.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 SeqResult).

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 := func(v int) int { return v * 2 }

result := F.Pipe1(
    Of(Counter{Value: 21}),
    LetL(valueLens, double),
)

func LetTo

func LetTo[S1, S2, T any](
	setter func(T) func(S1) S2,
	b T,
) Operator[S1, S2]

LetTo attaches a value to a context S1 to produce a context S2

func LetToL

func LetToL[S, T any](
	lens L.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.

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(
    Of(Config{Debug: true, Timeout: 30}),
    LetToL(debugLens, false),
)

func Map

func Map[A, B any](f func(A) B) Operator[A, B]

Map returns a function that applies a transformation to the value inside a successful SeqResult.

Marble diagram:

Input:  ---R(1)---R(2)---L(e)---R(3)---|
f(x) = x * 2
Output: ---R(2)---R(4)---L(e)---R(6)---|

Where R(x) represents Right(x) and L(e) represents Left(e).

func MapLeft

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

MapLeft returns a function that applies a transformation to the error value of a failed SeqResult

func MapTo

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

MapTo returns a function that replaces the value inside a successful SeqResult with a constant value

func MergeMap

func MergeMap[A, B any](f Kleisli[A, B]) Operator[A, B]

MergeMap returns a function that sequences two SeqResult computations

func MergeMapFirstEitherK

func MergeMapFirstEitherK[A, B any](f either.Kleisli[error, A, B]) Operator[A, A]

MergeMapFirstEitherK returns a function that executes a side-effecting Result computation but returns the original value

func MergeMapFirstResultK

func MergeMapFirstResultK[A, B any](f result.Kleisli[A, B]) Operator[A, A]

MergeMapFirstResultK returns a function that executes a side-effecting Result computation but returns the original value

func MergeMapSeqK

func MergeMapSeqK[A, B any](f iter.Kleisli[A, B]) Operator[A, B]

func OrElse

func OrElse[A any](onLeft Kleisli[error, A]) Operator[A, A]

OrElse recovers from a Left (error) by providing an alternative computation. If the SeqResult is Right, it returns the value unchanged. If the SeqResult is Left, it applies the provided function to the error value, which returns a new SeqResult that replaces the original.

Note: OrElse is identical to ChainLeft - both provide the same functionality for error recovery.

This is useful for error recovery, fallback logic, or chaining alternative IO computations. The error type can be widened from E1 to E2, allowing transformation of error types.

Example:

// Recover from specific errors with fallback operations
recover := OrElse(func(err error) SeqResult[int] {
    if err.Error() == "not found" {
        return Right(0) // default value
    }
    return Left[int](err) // propagate other errors
})
result := recover(Left[int](errors.New("not found"))) // Right(0)
result := recover(Right(42)) // Right(42) - unchanged

func Tap

func Tap[A, B any](f Kleisli[A, B]) Operator[A, A]

Tap is an alias for ChainFirst, executing a side effect while preserving the original value

func TapEitherK

func TapEitherK[A, B any](f either.Kleisli[error, A, B]) Operator[A, A]

TapEitherK is an alias for ChainFirstEitherK, executing a Result side effect while preserving the original value

func TapLeft

func TapLeft[A, B any](f Kleisli[error, B]) Operator[A, A]

func TapResultK

func TapResultK[A, B any](f result.Kleisli[A, B]) Operator[A, A]

TapResultK is an alias for ChainFirstEitherK, executing a Result side effect while preserving the original value

type Predicate

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

Predicate represents a function that tests a value of type A and returns a boolean. It's commonly used for filtering and conditional operations.

type Result

type Result[A any] = result.Result[A]

Result represents a value that can be either an error or a success value. It is used for computations that may fail, providing a type-safe alternative to error handling with multiple return values. The error type is always error.

Type Parameters:

  • A: The success type

type Semigroup

type Semigroup[A any] = itereither.Semigroup[error, A]

func AltSemigroup

func AltSemigroup[A any]() Semigroup[A]

AltSemigroup is a Semigroup that tries the first item and then the second one using an alternative

type Seq

type Seq[A any] = iter.Seq[A]

Seq is a single-value iterator sequence from Go 1.23+. It represents a lazy sequence of values that can be iterated using range.

Type Parameters:

  • A: The type of elements in the sequence

func MonadFold

func MonadFold[A, B any](ma SeqResult[A], onLeft iter.Kleisli[error, B], onRight iter.Kleisli[A, B]) Seq[B]

MonadFold eliminates a SeqResult by providing handlers for both error and success cases, returning a Seq

type SeqResult

type SeqResult[A any] = Seq[Result[A]]

SeqResult represents a lazy sequence of Result values. Each element in the sequence can be either an error or a success value. This combines the lazy evaluation of sequences with the error handling of Result.

Type Parameters:

  • A: The success type

Example:

seq := iter.From(
    result.Of(1),
    result.Of(2),
    result.Left(errors.New("error")),
)
// seq is a SeqResult[int]

func Bracket

func Bracket[A, B, ANY any](
	acquire SeqResult[A],
	use Kleisli[A, B],
	release func(A, Result[B]) SeqResult[ANY],
) SeqResult[B]

Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of whether the body action returns an error or not.

Marble diagram (successful case):

Acquire: ---R(resource)---|
Use:     ---R(result1)---R(result2)---|
Release: (called with resource and Right(result2))
Output:  ---R(result1)---R(result2)---|

Marble diagram (error case):

Acquire: ---R(resource)---|
Use:     ---R(result1)---L(error)---|
Release: (called with resource and Left(error))
Output:  ---R(result1)---L(error)---|

The release function is always called to clean up the resource, even when an error occurs during use.

func Do

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

Do creates an empty context of type S to be used with the Bind operation. This is the starting point for do-notation style composition.

Example:

type State struct {
    User  User
    Posts []Post
}
result := Do(State{})

func Flatten

func Flatten[A any](mma SeqResult[SeqResult[A]]) SeqResult[A]

Flatten removes one level of nesting from a nested SeqResult

func FromEither

func FromEither[A any](e Result[A]) SeqResult[A]

FromEither lifts a Result value into the SeqResult context

func FromIO added in v2.3.0

func FromIO[A any](mr IO[A]) SeqResult[A]

FromIO converts an IO computation into a single-element SeqResult containing a success value. The IO computation is executed when the sequence is consumed, and its result is wrapped in a success Result, creating a successful SeqResult.

This function bridges IO computations with SeqResult, allowing side effects that always succeed to be integrated into error-handling pipelines.

Type Parameters:

  • A: The type of value produced by the IO computation

Parameters:

  • mr: An IO computation that produces a value of type A

Returns:

  • SeqResult[A]: A sequence containing a single success Result with the IO result

Example:

getCurrentTime := func() time.Time { return time.Now() }
seq := FromIO(getCurrentTime)
// seq yields: Ok(current time) when consumed

See Also:

  • FromLazy: Converts a Lazy computation to SeqResult
  • FromIOResult: Converts an IOResult to SeqResult
  • Of: Creates a SeqResult from a pure value

func FromIOResult added in v2.3.0

func FromIOResult[A any](mr IOResult[A]) SeqResult[A]

FromIOResult converts an IOResult computation into a single-element SeqResult. The IOResult computation is executed when the sequence is consumed, and its result (either error or success) becomes the single element of the sequence.

This function bridges IOResult computations with SeqResult, allowing deferred I/O operations that may fail to be integrated into sequence-based error-handling pipelines.

Type Parameters:

  • A: The success type

Parameters:

  • mr: An IOResult computation that produces Result[A]

Returns:

  • SeqResult[A]: A sequence containing the single Result value from the deferred IOResult

Example:

readConfig := func() result.Result[Config] {
    data, err := os.ReadFile("config.json")
    if err != nil {
        return result.Left(err)
    }
    return result.Of(parseConfig(data))
}
seq := FromIOResult(readConfig)
// The IOResult is only executed when the sequence is iterated.

See Also:

  • FromIO: Converts an IO computation to SeqResult (always success)
  • FromLazy: Converts a Lazy computation to SeqResult (always success)
  • FromResult: Converts a pure Result to SeqResult

func FromLazy added in v2.3.0

func FromLazy[A any](mr Lazy[A]) SeqResult[A]

FromLazy converts a Lazy computation into a single-element SeqResult containing a success value. The Lazy computation is executed when the sequence is consumed, and its result is wrapped in a success Result, creating a successful SeqResult.

This is a convenience function that provides semantic clarity when working with lazy computations. It delegates to FromIO since Lazy is an alias for IO.

Type Parameters:

  • A: The type of value produced by the Lazy computation

Parameters:

  • mr: A Lazy computation that produces a value of type A

Returns:

  • SeqResult[A]: A sequence containing a single success Result with the Lazy result

Example:

expensiveCalc := func() int {
    // Expensive computation
    return 42
}
seq := FromLazy(expensiveCalc)
// Computation only runs when sequence is consumed
// seq yields: Ok(42)

See Also:

  • FromIO: Converts an IO computation to SeqResult
  • FromIOResult: Converts an IOResult to SeqResult
  • Of: Creates a SeqResult from a pure value

func FromSeq

func FromSeq[A any](mr Seq[A]) SeqResult[A]

FromSeq creates a SeqResult from a Seq instance, invoking Seq for each invocation of SeqResult

func Left

func Left[A any](l error) SeqResult[A]

Left constructs a SeqResult that represents a failure with an error value

func LeftSeq

func LeftSeq[A any](ml Seq[error]) SeqResult[A]

LeftSeq constructs a SeqResult from a Seq that produces an error value

func MonadAlt

func MonadAlt[A any](first SeqResult[A], second Lazy[SeqResult[A]]) SeqResult[A]

MonadAlt provides an alternative SeqResult computation if the first one fails.

Marble diagram:

First:  ---L(e1)---L(e2)---|
Second: ---R(1)---R(2)---|
Output: ---R(1)---R(2)---L(e2)---|

When a Left is encountered, it's replaced with values from the second sequence. Right values from the first sequence pass through unchanged.

func MonadAp

func MonadAp[B, A any](mab SeqResult[func(A) B], ma SeqResult[A]) SeqResult[B]

MonadAp applies a function wrapped in a SeqResult to a value wrapped in a SeqResult

func MonadApFirst

func MonadApFirst[A, B any](first SeqResult[A], second SeqResult[B]) SeqResult[A]

MonadApFirst combines two effectful actions, keeping only the result of the first.

Marble diagram:

First:  ---R(1)---R(2)---|
Second: ---R(10)---R(20)---|
Output: ---R(1)---R(2)---|

If either sequence contains a Left, the error is propagated:

First:  ---R(1)---L(e)---|
Second: ---R(10)---R(20)---|
Output: ---R(1)---L(e)---|

func MonadApSecond

func MonadApSecond[A, B any](first SeqResult[A], second SeqResult[B]) SeqResult[B]

MonadApSecond combines two effectful actions, keeping only the result of the second.

Marble diagram:

First:  ---R(1)---R(2)---|
Second: ---R(10)---R(20)---|
Output: ---R(10)---R(20)---|

If either sequence contains a Left, the error is propagated:

First:  ---R(1)---L(e)---|
Second: ---R(10)---R(20)---|
Output: ---R(10)---L(e)---|

func MonadBiMap

func MonadBiMap[A, B any](fa SeqResult[A], f Endomorphism[error], g func(A) B) SeqResult[B]

MonadBiMap applies one function to the error value and another to the success value of a SeqResult.

Marble diagram:

Input:  ---L(e1)---R(1)---L(e2)---R(2)---|
f(e) = len(e), g(x) = x * 2
Output: ---L(3)---R(2)---L(3)---R(4)---|

Both Left and Right values are transformed according to their respective functions.

func MonadChain

func MonadChain[A, B any](fa SeqResult[A], f Kleisli[A, B]) SeqResult[B]

MonadChain sequences two SeqResult computations, where the second depends on the result of the first.

Marble diagram:

Input:  ---R(1)-------R(2)---L(e)---|
f(1) -> ---R(10)---R(11)---|
f(2) -> ---R(20)---R(21)---|
Output: ---R(10)---R(11)---R(20)---R(21)---L(e)---|

Each Right value is transformed into a sequence, which is then flattened. Left values pass through unchanged and stop further processing.

func MonadChainEitherK

func MonadChainEitherK[A, B any](ma SeqResult[A], f result.Kleisli[A, B]) SeqResult[B]

func MonadChainFirst

func MonadChainFirst[A, B any](ma SeqResult[A], f Kleisli[A, B]) SeqResult[A]

MonadChainFirst executes a side-effecting SeqResult computation but returns the original value

func MonadChainFirstEitherK

func MonadChainFirstEitherK[A, B any](ma SeqResult[A], f either.Kleisli[error, A, B]) SeqResult[A]

MonadChainFirstEitherK executes a side-effecting Result computation but returns the original SeqResult value

func MonadChainFirstLeft

func MonadChainFirstLeft[A, B any](ma SeqResult[A], f Kleisli[error, B]) SeqResult[A]

MonadChainFirstLeft chains a computation on the left (error) side but always returns the original error. If the input is a Left value, it applies the function f to the error and executes the resulting computation, but always returns the original Left error regardless of what f returns (Left or Right). If the input is a Right value, it passes through unchanged without calling f.

This is useful for side effects on errors (like logging or metrics) where you want to perform an action when an error occurs but always propagate the original error, ensuring the error path is preserved.

Parameters:

  • ma: The input SeqResult that may contain an error of type EA
  • f: A function that takes an error of type EA and returns a SeqResult (typically for side effects)

Returns:

  • A SeqResult with the original error preserved if input was Left, or the original Right value

Example:

// Log errors but always preserve the original error
result := MonadChainFirstLeft(
    Left[int](errors.New("database error")),
    func(err error) SeqResult[int] {
        log.Printf("Error occurred: %s", err)
        return Right(0)
    },
)
// result will always be Left(error: "database error"), even though f returns Right

func MonadChainFirstResultK

func MonadChainFirstResultK[A, B any](ma SeqResult[A], f result.Kleisli[A, B]) SeqResult[A]

MonadChainFirstResultK executes a side-effecting Result computation but returns the original SeqResult value

func MonadChainLeft

func MonadChainLeft[A any](fa SeqResult[A], f Kleisli[error, A]) SeqResult[A]

MonadChainLeft chains a computation on the left (error) side of a SeqResult. If the input is a Left value, it applies the function f to transform the error and potentially change the error type from EA to EB. If the input is a Right value, it passes through unchanged.

Note: MonadChainLeft is identical to OrElse - both provide the same functionality for error recovery.

This is useful for error recovery or error transformation scenarios where you want to handle errors by performing another computation that may also fail.

Parameters:

  • fa: The input SeqResult that may contain an error of type EA
  • f: A function that takes an error of type EA and returns a SeqResult with error type EB

Returns:

  • A SeqResult with the potentially transformed error type EB

Example:

// Recover from a specific error by trying an alternative computation
result := MonadChainLeft(
    Left[int](errors.New("network error")),
    func(err error) SeqResult[int] {
        if err.Error() == "network error" {
            return Right(42) // recover with default value
        }
        return Left[int](fmt.Errorf("unrecoverable: %w", err))
    },
)

func MonadChainSeqK

func MonadChainSeqK[A, B any](ma SeqResult[A], f iter.Kleisli[A, B]) SeqResult[B]

func MonadChainTo

func MonadChainTo[A, B any](fa SeqResult[A], fb SeqResult[B]) SeqResult[B]

MonadChainTo sequences two SeqResult computations, discarding the result of the first

func MonadChainToSeq

func MonadChainToSeq[A, B any](fa SeqResult[A], fb Seq[B]) SeqResult[B]

MonadChainToSeq sequences a SeqResult with a Seq, discarding the result of the first

func MonadFilter added in v2.3.1

func MonadFilter[A any](as SeqResult[A], pred Predicate[A]) SeqResult[A]

MonadFilter filters a SeqResult sequence, keeping only Ok values that satisfy the predicate. Error values are always passed through unchanged, regardless of the predicate.

This function processes each element in the sequence:

  • If the element is an error, it passes through unchanged
  • If the element is Ok and satisfies the predicate, it passes through
  • If the element is Ok but fails the predicate, it is filtered out

Unlike FilterOrElse, which converts failing Ok values to errors, MonadFilter simply removes them from the sequence entirely.

Marble diagram:

Input:  --Ok(1)--Ok(2)--Err(e)--Ok(3)--Ok(4)--Ok(5)-->
pred(x) = x % 2 == 0
Output: ---------Ok(2)--Err(e)---------Ok(4)--------->

Where Ok(x) represents a successful result and Err(e) represents an error. Odd numbers are filtered out, even numbers and errors pass through.

Type Parameters:

  • A: The type of the Ok value (success type)

Parameters:

  • as: The input SeqResult sequence to filter
  • pred: A predicate function that tests Ok values

Returns:

  • A SeqResult containing only error values and Ok values that satisfy the predicate

Example:

import (
    R "github.com/IBM/fp-go/v2/result"
    "github.com/IBM/fp-go/v2/iterator/iter"
)

seq := iter.From(
    R.Of(1),
    R.Of(2),
    R.Error[int](errors.New("error")),
    R.Of(3),
    R.Of(4),
)
isEven := func(x int) bool { return x%2 == 0 }
result := iterresult.MonadFilter(seq, isEven)
// yields: Ok(2), Err(error), Ok(4)

See Also:

Filter is the curried version of MonadFilter. FilterOrElse converts failing values to errors instead of removing them.

func MonadFlap

func MonadFlap[B, A any](fab SeqResult[func(A) B], a A) SeqResult[B]

MonadFlap applies a value to a function wrapped in a SeqResult

func MonadMap

func MonadMap[A, B any](fa SeqResult[A], f func(A) B) SeqResult[B]

MonadMap applies a function to the value inside a successful SeqResult, leaving errors unchanged.

Marble diagram:

Input:  ---R(1)---R(2)---L(e)---R(3)---|
f(x) = x * 2
Output: ---R(2)---R(4)---L(e)---R(6)---|

Where R(x) represents Right(x) and L(e) represents Left(e).

func MonadMapLeft

func MonadMapLeft[A any](fa SeqResult[A], f Endomorphism[error]) SeqResult[A]

MonadMapLeft applies a function to the error value of a failed SeqResult, leaving successful values unchanged.

Marble diagram:

Input:  ---L(e1)---R(1)---L(e2)---R(2)---|
f(e) = "error: " + e
Output: ---L("error: e1")---R(1)---L("error: e2")---R(2)---|

Where R(x) represents Right(x) and L(e) represents Left(e).

func MonadMapTo

func MonadMapTo[A, B any](fa SeqResult[A], b B) SeqResult[B]

MonadMapTo replaces the value inside a successful SeqResult with a constant value

func MonadMergeMap

func MonadMergeMap[A, B any](fa SeqResult[A], f Kleisli[A, B]) SeqResult[B]

MonadMergeMap sequences two SeqResult computations, where the second depends on the result of the first. Unlike MonadChain, MergeMap interleaves results from concurrent sequences.

Marble diagram:

Input:  ---R(1)-------R(2)---|
f(1) -> ---R(10)------R(11)---|
f(2) -> ------R(20)------R(21)---|
Output: ---R(10)---R(20)---R(11)---R(21)---|

Results are interleaved as they become available, rather than waiting for each sequence to complete.

func MonadMergeMapFirstEitherK

func MonadMergeMapFirstEitherK[A, B any](ma SeqResult[A], f either.Kleisli[error, A, B]) SeqResult[A]

MonadMergeMapFirstEitherK executes a side-effecting Result computation but returns the original SeqResult value

func MonadMergeMapFirstResultK

func MonadMergeMapFirstResultK[A, B any](ma SeqResult[A], f result.Kleisli[A, B]) SeqResult[A]

MonadMergeMapFirstResultK executes a side-effecting Result computation but returns the original SeqResult value

func MonadMergeMapSeqK

func MonadMergeMapSeqK[A, B any](ma SeqResult[A], f iter.Kleisli[A, B]) SeqResult[B]

func MonadOf

func MonadOf[A any](r A) SeqResult[A]

MonadOf is an alias for Of, provided for consistency with monad naming conventions

func MonadTap

func MonadTap[A, B any](ma SeqResult[A], f Kleisli[A, B]) SeqResult[A]

MonadTap is an alias for MonadChainFirst, executing a side effect while preserving the original value

func MonadTapEitherK

func MonadTapEitherK[A, B any](ma SeqResult[A], f either.Kleisli[error, A, B]) SeqResult[A]

MonadTapEitherK is an alias for MonadChainFirstEitherK, executing a Result side effect while preserving the original value

func MonadTapLeft

func MonadTapLeft[A, B any](ma SeqResult[A], f Kleisli[error, B]) SeqResult[A]

func MonadTapResultK

func MonadTapResultK[A, B any](ma SeqResult[A], f result.Kleisli[A, B]) SeqResult[A]

MonadTapResultK is an alias for MonadChainFirstEitherK, executing a Result side effect while preserving the original value

func Of

func Of[A any](r A) SeqResult[A]

Of constructs a SeqResult that represents a successful computation with a value of type A. This is an alias for Right and is the canonical way to lift a pure value into the SeqResult context.

func Right[A any](r A) SeqResult[A]

Right constructs a SeqResult that represents a successful computation with a value of type A

func RightSeq

func RightSeq[A any](mr Seq[A]) SeqResult[A]

RightSeq constructs a SeqResult from a Seq that produces a success value

func SequenceArray

func SequenceArray[A any](ma []SeqResult[A]) SeqResult[[]A]

SequenceArray converts a homogeneous sequence of either into an either of sequence

func SequenceParT1

func SequenceParT1[T1 any](
	t1 SeqResult[T1],
) SeqResult[tuple.Tuple1[T1]]

SequenceParT1 converts 1 [SeqResult[T]] into a [SeqResult[tuple.Tuple1[T1]]]

func SequenceParTuple1

func SequenceParTuple1[T1 any](t tuple.Tuple1[SeqResult[T1]]) SeqResult[tuple.Tuple1[T1]]

SequenceParTuple1 converts a [tuple.Tuple1[SeqResult[T]]] into a [SeqResult[tuple.Tuple1[T1]]]

func SequenceRecord

func SequenceRecord[K comparable, A any](ma map[K]SeqResult[A]) SeqResult[map[K]A]

SequenceRecord converts a homogeneous sequence of either into an either of sequence

func SequenceSeqT1

func SequenceSeqT1[T1 any](
	t1 SeqResult[T1],
) SeqResult[tuple.Tuple1[T1]]

SequenceSeqT1 converts 1 [SeqResult[T]] into a [SeqResult[tuple.Tuple1[T1]]]

func SequenceSeqTuple1

func SequenceSeqTuple1[T1 any](t tuple.Tuple1[SeqResult[T1]]) SeqResult[tuple.Tuple1[T1]]

SequenceSeqTuple1 converts a [tuple.Tuple1[SeqResult[T]]] into a [SeqResult[tuple.Tuple1[T1]]]

func SequenceT1

func SequenceT1[T1 any](
	t1 SeqResult[T1],
) SeqResult[tuple.Tuple1[T1]]

SequenceT1 converts 1 [SeqResult[T]] into a [SeqResult[tuple.Tuple1[T1]]]

func SequenceT2

func SequenceT2[T1, T2 any](
	t1 SeqResult[T1],
	t2 SeqResult[T2],
) SeqResult[tuple.Tuple2[T1, T2]]

SequenceT2 converts 2 [SeqResult[T]] into a [SeqResult[tuple.Tuple2[T1, T2]]]

func SequenceT3

func SequenceT3[T1, T2, T3 any](
	t1 SeqResult[T1],
	t2 SeqResult[T2],
	t3 SeqResult[T3],
) SeqResult[tuple.Tuple3[T1, T2, T3]]

SequenceT3 converts 3 [SeqResult[T]] into a [SeqResult[tuple.Tuple3[T1, T2, T3]]]

func SequenceT4

func SequenceT4[T1, T2, T3, T4 any](
	t1 SeqResult[T1],
	t2 SeqResult[T2],
	t3 SeqResult[T3],
	t4 SeqResult[T4],
) SeqResult[tuple.Tuple4[T1, T2, T3, T4]]

SequenceT4 converts 4 [SeqResult[T]] into a [SeqResult[tuple.Tuple4[T1, T2, T3, T4]]]

func SequenceT5

func SequenceT5[T1, T2, T3, T4, T5 any](
	t1 SeqResult[T1],
	t2 SeqResult[T2],
	t3 SeqResult[T3],
	t4 SeqResult[T4],
	t5 SeqResult[T5],
) SeqResult[tuple.Tuple5[T1, T2, T3, T4, T5]]

SequenceT5 converts 5 [SeqResult[T]] into a [SeqResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]

func SequenceT6

func SequenceT6[T1, T2, T3, T4, T5, T6 any](
	t1 SeqResult[T1],
	t2 SeqResult[T2],
	t3 SeqResult[T3],
	t4 SeqResult[T4],
	t5 SeqResult[T5],
	t6 SeqResult[T6],
) SeqResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]

SequenceT6 converts 6 [SeqResult[T]] into a [SeqResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]

func SequenceT7

func SequenceT7[T1, T2, T3, T4, T5, T6, T7 any](
	t1 SeqResult[T1],
	t2 SeqResult[T2],
	t3 SeqResult[T3],
	t4 SeqResult[T4],
	t5 SeqResult[T5],
	t6 SeqResult[T6],
	t7 SeqResult[T7],
) SeqResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]

SequenceT7 converts 7 [SeqResult[T]] into a [SeqResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]

func SequenceT8

func SequenceT8[T1, T2, T3, T4, T5, T6, T7, T8 any](
	t1 SeqResult[T1],
	t2 SeqResult[T2],
	t3 SeqResult[T3],
	t4 SeqResult[T4],
	t5 SeqResult[T5],
	t6 SeqResult[T6],
	t7 SeqResult[T7],
	t8 SeqResult[T8],
) SeqResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]

SequenceT8 converts 8 [SeqResult[T]] into a [SeqResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]

func SequenceT9

func SequenceT9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](
	t1 SeqResult[T1],
	t2 SeqResult[T2],
	t3 SeqResult[T3],
	t4 SeqResult[T4],
	t5 SeqResult[T5],
	t6 SeqResult[T6],
	t7 SeqResult[T7],
	t8 SeqResult[T8],
	t9 SeqResult[T9],
) SeqResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]

SequenceT9 converts 9 [SeqResult[T]] into a [SeqResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]

func SequenceT10

func SequenceT10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](
	t1 SeqResult[T1],
	t2 SeqResult[T2],
	t3 SeqResult[T3],
	t4 SeqResult[T4],
	t5 SeqResult[T5],
	t6 SeqResult[T6],
	t7 SeqResult[T7],
	t8 SeqResult[T8],
	t9 SeqResult[T9],
	t10 SeqResult[T10],
) SeqResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]

SequenceT10 converts 10 [SeqResult[T]] into a [SeqResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]

func SequenceTuple1

func SequenceTuple1[T1 any](t tuple.Tuple1[SeqResult[T1]]) SeqResult[tuple.Tuple1[T1]]

SequenceTuple1 converts a [tuple.Tuple1[SeqResult[T]]] into a [SeqResult[tuple.Tuple1[T1]]]

func SequenceTuple2

func SequenceTuple2[T1, T2 any](t tuple.Tuple2[SeqResult[T1], SeqResult[T2]]) SeqResult[tuple.Tuple2[T1, T2]]

SequenceTuple2 converts a [tuple.Tuple2[SeqResult[T]]] into a [SeqResult[tuple.Tuple2[T1, T2]]]

func SequenceTuple3

func SequenceTuple3[T1, T2, T3 any](t tuple.Tuple3[SeqResult[T1], SeqResult[T2], SeqResult[T3]]) SeqResult[tuple.Tuple3[T1, T2, T3]]

SequenceTuple3 converts a [tuple.Tuple3[SeqResult[T]]] into a [SeqResult[tuple.Tuple3[T1, T2, T3]]]

func SequenceTuple4

func SequenceTuple4[T1, T2, T3, T4 any](t tuple.Tuple4[SeqResult[T1], SeqResult[T2], SeqResult[T3], SeqResult[T4]]) SeqResult[tuple.Tuple4[T1, T2, T3, T4]]

SequenceTuple4 converts a [tuple.Tuple4[SeqResult[T]]] into a [SeqResult[tuple.Tuple4[T1, T2, T3, T4]]]

func SequenceTuple5

func SequenceTuple5[T1, T2, T3, T4, T5 any](t tuple.Tuple5[SeqResult[T1], SeqResult[T2], SeqResult[T3], SeqResult[T4], SeqResult[T5]]) SeqResult[tuple.Tuple5[T1, T2, T3, T4, T5]]

SequenceTuple5 converts a [tuple.Tuple5[SeqResult[T]]] into a [SeqResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]

func SequenceTuple6

func SequenceTuple6[T1, T2, T3, T4, T5, T6 any](t tuple.Tuple6[SeqResult[T1], SeqResult[T2], SeqResult[T3], SeqResult[T4], SeqResult[T5], SeqResult[T6]]) SeqResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]

SequenceTuple6 converts a [tuple.Tuple6[SeqResult[T]]] into a [SeqResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]

func SequenceTuple7

func SequenceTuple7[T1, T2, T3, T4, T5, T6, T7 any](t tuple.Tuple7[SeqResult[T1], SeqResult[T2], SeqResult[T3], SeqResult[T4], SeqResult[T5], SeqResult[T6], SeqResult[T7]]) SeqResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]

SequenceTuple7 converts a [tuple.Tuple7[SeqResult[T]]] into a [SeqResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]

func SequenceTuple8

func SequenceTuple8[T1, T2, T3, T4, T5, T6, T7, T8 any](t tuple.Tuple8[SeqResult[T1], SeqResult[T2], SeqResult[T3], SeqResult[T4], SeqResult[T5], SeqResult[T6], SeqResult[T7], SeqResult[T8]]) SeqResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]

SequenceTuple8 converts a [tuple.Tuple8[SeqResult[T]]] into a [SeqResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]

func SequenceTuple9

func SequenceTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](t tuple.Tuple9[SeqResult[T1], SeqResult[T2], SeqResult[T3], SeqResult[T4], SeqResult[T5], SeqResult[T6], SeqResult[T7], SeqResult[T8], SeqResult[T9]]) SeqResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]

SequenceTuple9 converts a [tuple.Tuple9[SeqResult[T]]] into a [SeqResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]

func SequenceTuple10

func SequenceTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](t tuple.Tuple10[SeqResult[T1], SeqResult[T2], SeqResult[T3], SeqResult[T4], SeqResult[T5], SeqResult[T6], SeqResult[T7], SeqResult[T8], SeqResult[T9], SeqResult[T10]]) SeqResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]

SequenceTuple10 converts a [tuple.Tuple10[SeqResult[T]]] into a [SeqResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]

func StopOnError added in v2.3.0

func StopOnError[T any](s SeqResult[T]) SeqResult[T]

StopOnError is an alias for TakeUntilError. It takes elements from a SeqResult until the first error is encountered, including that error.

This function provides a more descriptive name for the same operation as TakeUntilError, emphasizing that the sequence stops when an error occurs.

Type Parameters:

  • T: The success type

Parameters:

  • s: The input SeqResult to process

Returns:

  • SeqResult[T]: A sequence containing all success values up to and including the first error

Example:

seq := iter.From(
    result.Of(1),
    result.Of(2),
    result.Left(errors.New("error")),
    result.Of(3),
)
result := StopOnError(seq)
// yields: Ok(1), Ok(2), Err("error")

See Also:

  • TakeUntilError: The primary function this aliases

func TakeUntilError added in v2.3.0

func TakeUntilError[T any](s SeqResult[T]) SeqResult[T]

TakeUntilError takes elements from a SeqResult until the first error is encountered, including that error.

This function creates a transformation that yields all success values from the source sequence until an error is encountered. When an error is found, it is included in the output and the sequence terminates immediately. This is useful for processing sequences that should stop at the first error while still capturing that error.

The operation is lazy and only consumes elements from the source sequence as needed. Once an error is encountered, iteration stops immediately without consuming the remaining elements from the source.

Marble Diagram:

Input:  --Ok(1)--Ok(2)--Ok(3)--Err(e)--Ok(4)--Ok(5)-->
TakeUntilError
Output: --Ok(1)--Ok(2)--Ok(3)--Err(e)|
                                (includes error, then stops)

Where Ok(x) represents a success Result and Err(e) represents an error Result.

Type Parameters:

  • T: The success type

Parameters:

  • s: The input SeqResult to process

Returns:

  • SeqResult[T]: A sequence containing all success values up to and including the first error

Example - Stop at first error:

seq := iter.From(
    result.Of(1),
    result.Of(2),
    result.Left(errors.New("error")),
    result.Of(3),
)
result := TakeUntilError(seq)
// yields: Ok(1), Ok(2), Err("error")
// Note: Ok(3) is not processed

Example - All success values:

seq := iter.From(
    result.Of(1),
    result.Of(2),
    result.Of(3),
)
result := TakeUntilError(seq)
// yields: Ok(1), Ok(2), Ok(3)
// All elements pass through since there's no error

Example - First element is error:

seq := iter.From(
    result.Left(errors.New("immediate error")),
    result.Of(1),
    result.Of(2),
)
result := TakeUntilError(seq)
// yields: Err("immediate error")
// Stops immediately after the first error

Example - Processing with error handling:

parseNumbers := func(inputs []string) SeqResult[int] {
    seq := iter.MonadMap(
        iter.From(inputs...),
        result.Eitherize1(strconv.Atoi),
    )
    return TakeUntilError(seq)
}
// Processes strings until first parse error, including the error

See Also:

  • itereither.TakeUntilLeft: The underlying function used
  • StopOnError: Alias for TakeUntilError

type Trampoline

type Trampoline[B, L any] = tailrec.Trampoline[B, L]

Trampoline represents a tail-recursive computation that can be evaluated safely without stack overflow. It's used for implementing stack-safe recursive algorithms.

type Void

type Void = function.Void

Void represents the absence of a value, similar to void in other languages. It's used in functions that perform side effects but don't return meaningful values. The zero value is function.VOID.

Example:

logMessage := func() Void {
    fmt.Println("Logging...")
    return function.VOID
}

Jump to

Keyboard shortcuts

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