option

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: 12 Imported by: 0

Documentation

Overview

Package option implements the Option monad using idiomatic Go tuple signatures.

Unlike the standard option package which uses wrapper structs, this package represents Options as tuples (value, bool) where the boolean indicates presence (true) or absence (false). This approach is more idiomatic in Go and has better performance characteristics.

Type Signatures

The core types used in this package are:

Operator[A, B any] = func(A, bool) (B, bool)  // Transforms an Option[A] to Option[B]
Kleisli[A, B any]  = func(A) (B, bool)        // Monadic function from A to Option[B]

Basic Usage

Create an Option with Some or None:

some := Some(42)           // (42, true)
none := None[int]()        // (0, false)
opt := Of(42)              // Alternative to Some: (42, true)

Check if an Option contains a value:

value, ok := Some(42)
if ok {
    // value == 42
}

if IsSome(Some(42)) {
    // Option contains a value
}
if IsNone(None[int]()) {
    // Option is empty
}

Extract values:

value, ok := Some(42)      // Direct tuple unpacking: value == 42, ok == true
value := GetOrElse(func() int { return 0 })(Some(42))  // Returns 42
value := GetOrElse(func() int { return 0 })(None[int]())  // Returns 0

Transformations

Map transforms the contained value:

double := Map(N.Mul(2))
result := double(Some(21))  // (42, true)
result := double(None[int]())  // (0, false)

Chain sequences operations that may fail:

validate := Chain(func(x int) (int, bool) {
    if x > 0 { return x * 2, true }
    return 0, false
})
result := validate(Some(5))  // (10, true)
result := validate(Some(-1))  // (0, false)

Filter keeps values that satisfy a predicate:

isPositive := Filter(N.MoreThan(0))
result := isPositive(Some(5))  // (5, true)
result := isPositive(Some(-1))  // (0, false)

Working with Collections

Transform arrays using TraverseArray:

doublePositive := func(x int) (int, bool) {
    if x > 0 { return x * 2, true }
    return 0, false
}
result := TraverseArray(doublePositive)([]int{1, 2, 3})  // ([2, 4, 6], true)
result := TraverseArray(doublePositive)([]int{1, -2, 3})  // ([], false)

Transform with indexes:

f := func(i int, x int) (int, bool) {
    if x > i { return x, true }
    return 0, false
}
result := TraverseArrayWithIndex(f)([]int{1, 2, 3})  // ([1, 2, 3], true)

Transform records (maps):

double := func(x int) (int, bool) { return x * 2, true }
result := TraverseRecord(double)(map[string]int{"a": 1, "b": 2})
// (map[string]int{"a": 2, "b": 4}, true)

Algebraic Operations

Option supports various algebraic structures:

  • Functor: Map operations for transforming values
  • Applicative: Ap operations for applying wrapped functions
  • Monad: Chain operations for sequencing computations
  • Alternative: Alt operations for providing fallbacks

Applicative example:

fab := Some(N.Mul(2))
fa := Some(21)
result := Ap[int](fa)(fab)  // (42, true)

Alternative example:

withDefault := Alt(func() (int, bool) { return 100, true })
result := withDefault(Some(42))  // (42, true)
result := withDefault(None[int]())  // (100, true)

Conversion Functions

Convert predicates to Options:

isPositive := FromPredicate(N.MoreThan(0))
result := isPositive(5)  // (5, true)
result := isPositive(-1)  // (0, false)

Convert nullable pointers to Options:

var ptr *int = nil
result := FromNillable(ptr)  // (nil, false)
val := 42
result := FromNillable(&val)  // (&val, true)

Convert zero/non-zero values to Options:

result := FromZero[int]()(0)  // (0, true)
result := FromZero[int]()(5)  // (0, false)
result := FromNonZero[int]()(5)  // (5, true)
result := FromNonZero[int]()(0)  // (0, false)

Use equality-based conversion:

import "github.com/IBM/fp-go/v2/eq"
equals42 := FromEq(eq.FromStrictEquals[int]())(42)
result := equals42(42)  // (42, true)
result := equals42(10)  // (0, false)

Do-Notation Style

Build complex computations using do-notation:

type Result struct {
    x int
    y int
    sum int
}

result := F.Pipe3(
    Do(Result{}),
    Bind(func(x int) func(Result) Result {
        return func(r Result) Result { r.x = x; return r }
    }, func(r Result) (int, bool) { return Some(10) }),
    Bind(func(y int) func(Result) Result {
        return func(r Result) Result { r.y = y; return r }
    }, func(r Result) (int, bool) { return Some(20) }),
    Let(func(sum int) func(Result) Result {
        return func(r Result) Result { r.sum = sum; return r }
    }, func(r Result) int { return r.x + r.y }),
)  // (Result{x: 10, y: 20, sum: 30}, true)

Lens-Based Operations

Use lenses for cleaner field updates:

type Person struct {
    Name string
    Age  int
}

ageLens := lens.MakeLens(
    func(p Person) int { return p.Age },
    func(p Person, age int) Person { p.Age = age; return p },
)

// Update using a lens
incrementAge := BindL(ageLens, func(age int) (int, bool) {
    if age < 120 { return age + 1, true }
    return 0, false
})
result := incrementAge(Some(Person{Name: "Alice", Age: 30}))
// (Person{Name: "Alice", Age: 31}, true)

// Set using a lens
setAge := LetToL(ageLens, 25)
result := setAge(Some(Person{Name: "Bob", Age: 30}))
// (Person{Name: "Bob", Age: 25}, true)

Folding and Reducing

Fold provides a way to handle both Some and None cases:

handler := Fold(
    func() string { return "no value" },
    func(x int) string { return fmt.Sprintf("value: %d", x) },
)
result := handler(Some(42))  // "value: 42"
result := handler(None[int]())  // "no value"

Reduce folds an Option into a single value:

sum := Reduce(func(acc, val int) int { return acc + val }, 0)
result := sum(Some(5))  // 5
result := sum(None[int]())  // 0

Debugging

Convert Options to strings for debugging:

str := ToString(Some(42))  // "Some[int](42)"
str := ToString(None[int]())  // "None[int]"

Subpackages

  • option/number: Number conversion utilities for working with Options

Package option implements the Option monad using idiomatic Go data types.

Unlike the standard option package which uses wrapper structs, this package represents Options as tuples (value, bool) where the boolean indicates presence (true) or absence (false). This approach is more idiomatic in Go and has better performance characteristics.

Example:

// Creating Options
some := Some(42)           // (42, true)
none := None[int]()        // (0, false)

// Using Options
result, ok := some         // ok == true, result == 42
result, ok := none         // ok == false, result == 0

// Transforming Options
doubled := Map(N.Mul(2))(some)  // (84, true)

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, bool) Operator[S1, S2]

ApS attaches a value to a context S1 to produce a context S2 by considering the context and the value concurrently. This uses the applicative functor pattern, allowing parallel composition.

Parameters:

  • setter: A function that takes a value and returns a function to update the context

Returns a function that takes an Option (value, bool) and returns an Operator.

Example:

type State struct { x int; y int }
result := F.Pipe2(
    Do(State{}),
    ApS(func(x int) func(State) State {
        return func(s State) State { s.x = x; return s }
    }, Some(42)),
)

func ApSL

func ApSL[S, T any](
	lens L.Lens[S, T],
) func(T, bool) 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 Address struct {
    Street string
    City   string
}

type Person struct {
    Name    string
    Address Address
}

// Create a lens for the Address field
addressLens := lens.MakeLens(
    func(p Person) Address { return p.Address },
    func(p Person, a Address) Person { p.Address = a; return p },
)

// Use ApSL to update the address
result := F.Pipe2(
    option.Some(Person{Name: "Alice"}),
    option.ApSL(
        addressLens,
        option.Some(Address{Street: "Main St", City: "NYC"}),
    ),
)

Parameters:

  • lens: A lens that focuses on a field within the structure S

Returns a function that takes an Option (value, bool) and returns an Operator.

func Do

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

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

Parameters:

  • empty: The initial empty context value

Example:

type Result struct {
    x int
    y string
}
result := Do(Result{})

func Eq

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

Eq constructs an equality predicate for Option[A] given an equality predicate for A. Two Options are equal if:

  • Both are None, or
  • Both are Some and their contained values are equal according to the provided Eq

Parameters:

  • eq: An equality predicate for the contained type A

Returns a curried function that takes two Options (as tuples) and returns true if they are equal.

Example:

intEq := eq.FromStrictEquals[int]()
optEq := Eq(intEq)

opt1 := Some(42)  // (42, true)
opt2 := Some(42)  // (42, true)
optEq(opt1)(opt2) // true

opt3 := Some(43)  // (43, true)
optEq(opt1)(opt3) // false

none1 := None[int]()  // (0, false)
none2 := None[int]()  // (0, false)
optEq(none1)(none2) // true

optEq(opt1)(none1) // false

func Flow1

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

Flow1 creates a function that 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:

double := Flow1(func(x int, ok bool) (int, bool) { return x * 2, ok })
result := double(42, true) // (84, true)

func Flow2

func Flow2[F1 ~func(T0, bool) (T1, bool), F2 ~func(T1, bool) (T2, bool), T0, T1, T2 any](f1 F1, f2 F2) func(T0, bool) (T2, bool)

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, bool) (T1, bool), F2 ~func(T1, bool) (T2, bool), F3 ~func(T2, bool) (T3, bool), T0, T1, T2, T3 any](f1 F1, f2 F2, f3 F3) func(T0, bool) (T3, bool)

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, bool) (T1, bool), F2 ~func(T1, bool) (T2, bool), F3 ~func(T2, bool) (T3, bool), F4 ~func(T3, bool) (T4, bool), T0, T1, T2, T3, T4 any](f1 F1, f2 F2, f3 F3, f4 F4) func(T0, bool) (T4, bool)

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, bool) (T1, bool), F2 ~func(T1, bool) (T2, bool), F3 ~func(T2, bool) (T3, bool), F4 ~func(T3, bool) (T4, bool), F5 ~func(T4, bool) (T5, bool), T0, T1, T2, T3, T4, T5 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(T0, bool) (T5, bool)

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](onNone func() B, onSome func(A) B) func(A, bool) B

Fold provides a way to handle both Some and None cases of an Option. Returns a function that applies onNone if the Option is None, or onSome if it's Some.

Parameters:

  • onNone: Function to call when the Option is None
  • onSome: Function to call when the Option is Some, receives the wrapped value

Example:

handler := Fold(
    func() string { return "no value" },
    func(x int) string { return fmt.Sprintf("value: %d", x) },
)
result := handler(Some(42)) // "value: 42"
result := handler(None[int]()) // "no value"

func FromEq

func FromEq[A any](pred eq.Eq[A]) func(A) Kleisli[A, A]

FromEq returns a function that creates an Option based on equality with a given value. The returned function takes a value to compare against and returns a Kleisli function.

Parameters:

  • pred: An equality predicate

Example:

import "github.com/IBM/fp-go/v2/eq"
equals42 := FromEq(eq.FromStrictEquals[int]())(42)
result := equals42(42)  // Some(42)
result := equals42(10)  // None

func FromNillable

func FromNillable[A any](a *A) (*A, bool)

FromNillable converts a pointer to an Option. Returns Some if the pointer is non-nil, None otherwise.

Parameters:

  • a: A pointer that may be nil

Example:

var ptr *int = nil
result := FromNillable(ptr) // None
val := 42
result := FromNillable(&val) // Some(&val)

func FromStrictCompare

func FromStrictCompare[A C.Ordered]() func(A, bool) func(A, bool) int

FromStrictCompare constructs an Ord for Option[A] using Go's built-in comparison operators for type A. This is a convenience function for ordered types (types that support <, >, ==).

Example:

optOrd := FromStrictCompare[int]()
optOrd.Compare(Some(5), Some(10)) // -1
optOrd.Compare(None[int](), Some(5)) // -1

func FromStrictEquals

func FromStrictEquals[A comparable]() func(A, bool) func(A, bool) bool

FromStrictEquals constructs an Eq for Option[A] using Go's built-in equality (==) for type A. This is a convenience function for comparable types.

Returns a curried function that takes two Options (as tuples) and returns true if they are equal.

Example:

optEq := FromStrictEquals[int]()

opt1 := Some(42)  // (42, true)
opt2 := Some(42)  // (42, true)
optEq(opt1)(opt2) // true

none1 := None[int]()  // (0, false)
none2 := None[int]()  // (0, false)
optEq(none1)(none2) // true

opt3 := Some(43)  // (43, true)
optEq(opt1)(opt3) // false

func GetOrElse

func GetOrElse[A any](onNone func() A) func(A, bool) A

GetOrElse returns a function that extracts the value from an Option or returns a default.

Parameters:

  • onNone: Function that provides the default value when the Option is None

Example:

getOrZero := GetOrElse(func() int { return 0 })
result := getOrZero(Some(42)) // 42
result := getOrZero(None[int]()) // 0

func IsNone

func IsNone[T any](t T, tok bool) bool

IsNone checks if an Option is None (contains no value).

Parameters:

  • t: The value of the Option
  • tok: Whether the Option contains a value (true for Some, false for None)

Example:

opt := None[int]()
IsNone(opt) // true
opt := Some(42)
IsNone(opt) // false

func IsSome

func IsSome[T any](t T, tok bool) bool

IsSome checks if an Option contains a value.

Parameters:

  • t: The value of the Option
  • tok: Whether the Option contains a value (true for Some, false for None)

Example:

opt := Some(42)
IsSome(opt) // true
opt := None[int]()
IsSome(opt) // false

func Logger

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

Logger creates a logging function for Options that logs the state (None or Some with value) and returns the original Option unchanged. This is useful for debugging pipelines.

Parameters:

  • loggers: optional log.Logger instances to use for logging (defaults to standard logger)

Returns a function that takes a prefix string and returns a function that logs and passes through an Option.

Example:

logger := Logger[int]()
result := F.Pipe2(
    Some(42),
    logger("step1"), // logs "step1: 42"
    Map(N.Mul(2)),
) // Some(84)

result := F.Pipe1(
    None[int](),
    logger("step1"), // logs "step1"
) // None

func None

func None[T any]() (t T, tok bool)

None creates an Option that contains no value.

Example:

opt := None[int]() // Empty Option of type int
opt := None[string]() // Empty Option of type string

func Of

func Of[T any](value T) (T, bool)

Of creates an Option that contains a value. This is an alias for Some and is used in monadic contexts.

Parameters:

  • value: The value to wrap in Some

Example:

opt := Of(42) // Option containing 42

func Ord

func Ord[A any](o ord.Ord[A]) func(A, bool) func(A, bool) int

Ord constructs an ordering for Option[A] given an ordering for A. The ordering follows these rules:

  • None is considered less than any Some value
  • Two None values are equal
  • Two Some values are compared using the provided Ord for A

Example:

intOrd := ord.FromStrictCompare[int]()
optOrd := Ord(intOrd)
optOrd.Compare(None[int](), Some(5)) // -1 (None < Some)
optOrd.Compare(Some(3), Some(5)) // -1 (3 < 5)
optOrd.Compare(Some(5), Some(3)) // 1 (5 > 3)
optOrd.Compare(None[int](), None[int]()) // 0 (equal)

func Pipe1

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

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 := Pipe1(42, func(x int) (int, bool) { return x * 2, true }) // (84, true)

func Pipe2

func Pipe2[F1 ~func(T0) (T1, bool), F2 ~func(T1, bool) (T2, bool), T0, T1, T2 any](t0 T0, f1 F1, f2 F2) (T2, bool)

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, bool), F2 ~func(T1, bool) (T2, bool), F3 ~func(T2, bool) (T3, bool), T0, T1, T2, T3 any](t0 T0, f1 F1, f2 F2, f3 F3) (T3, bool)

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, bool), F2 ~func(T1, bool) (T2, bool), F3 ~func(T2, bool) (T3, bool), F4 ~func(T3, bool) (T4, bool), T0, T1, T2, T3, T4 any](t0 T0, f1 F1, f2 F2, f3 F3, f4 F4) (T4, bool)

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, bool), F2 ~func(T1, bool) (T2, bool), F3 ~func(T2, bool) (T3, bool), F4 ~func(T3, bool) (T4, bool), F5 ~func(T4, bool) (T5, bool), T0, T1, T2, T3, T4, T5 any](t0 T0, f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) (T5, bool)

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, bool) B

Reduce folds an Option into a single value using a reducer function. If the Option is None, returns the initial value.

Parameters:

  • f: A reducer function that combines the accumulator with the Option value
  • initial: The initial/default value to use

Example:

sum := Reduce(func(acc, val int) int { return acc + val }, 0)
result := sum(Some(5)) // 5
result := sum(None[int]()) // 0

func Some

func Some[T any](value T) (T, bool)

Some creates an Option that contains a value.

Parameters:

  • value: The value to wrap in Some

Example:

opt := Some(42) // Option containing 42
opt := Some("hello") // Option containing "hello"
Example (Creation)
// Build an Option
none1, none1ok := None[int]()
some1, some1ok := Some("value")

// Build from a value
fromNillable := FromNillable[string]
nonFromNil, nonFromNilok := fromNillable(nil) // None[*string]
value := "value"
someFromPointer, someFromPointerok := fromNillable(&value) // Some[*string](xxx)

// some predicate
isEven := func(num int) bool {
	return num%2 == 0
}

fromEven := FromPredicate(isEven)
noneFromPred, noneFromPredok := fromEven(3) // None[int]
someFromPred, someFromPredok := fromEven(4) // Some[int](4)

fmt.Println(ToString(none1, none1ok))
fmt.Println(ToString(some1, some1ok))
fmt.Println(ToString(nonFromNil, nonFromNilok))
fmt.Println(IsSome(someFromPointer, someFromPointerok))
fmt.Println(ToString(noneFromPred, noneFromPredok))
fmt.Println(ToString(someFromPred, someFromPredok))
Output:

None[int]
Some[string](value)
None[*string]
true
None[int]
Some[int](4)
Example (Extraction)
noneValue, okFromNone := None[int]()
someValue, okFromSome := Of(42)

// Convert Option[T] with a default value
noneWithDefault := GetOrElse(F.Constant(0))(noneValue, okFromNone) // 0
someWithDefault := GetOrElse(F.Constant(0))(someValue, okFromSome) // 42

// Apply a different function on None/Some(...)
doubleOrZero := Fold(
	F.Constant(0), // none case
	N.Mul(2),      // some case
) // func(ma Option[int]) int

doubleFromNone := doubleOrZero(noneValue, okFromNone) // 0
doubleFromSome := doubleOrZero(someValue, okFromSome) // 84

fmt.Printf("%d, %t\n", noneValue, okFromNone)
fmt.Printf("%d, %t\n", someValue, okFromSome)
fmt.Println(noneWithDefault)
fmt.Println(someWithDefault)
fmt.Println(doubleFromNone)
fmt.Println(doubleFromSome)
Output:

0, false
42, true
0
42
0
84

func ToAny

func ToAny[T any](src T) (any, bool)

ToAny converts a value of any type to Option[any]. This always succeeds and returns Some containing the value as any.

Example:

result := ToAny(42) // Some(any(42))
result := ToAny("hello") // Some(any("hello"))

func ToString

func ToString[T any](t T, tok bool) string

ToString converts an Option to a string representation for debugging.

Parameters:

  • t: The value of the Option
  • tok: Whether the Option contains a value (true for Some, false for None)

func ToType

func ToType[T any](src any) (T, bool)

ToType attempts to convert a value of type any to a specific type T using type assertion. Returns Some(value) if the type assertion succeeds, None if it fails.

Example:

var x any = 42
result := ToType[int](x) // Some(42)

var y any = "hello"
result := ToType[int](y) // None (wrong type)

func TraverseTuple1

func TraverseTuple1[F1 ~Kleisli[A1, T1], A1, T1 any](f1 F1) func(A1) (T1, bool)

TraverseTuple1 converts a [Tuple1] of [A] via transformation functions transforming [A] to [Option[A]] into a [Option[Tuple1]].

func TraverseTuple10

func TraverseTuple10[F1 ~Kleisli[A1, T1], F2 ~Kleisli[A2, T2], F3 ~Kleisli[A3, T3], F4 ~Kleisli[A4, T4], F5 ~Kleisli[A5, T5], F6 ~Kleisli[A6, T6], F7 ~Kleisli[A7, T7], F8 ~Kleisli[A8, T8], F9 ~Kleisli[A9, T9], F10 ~Kleisli[A10, T10], 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, bool)

TraverseTuple10 converts a [Tuple10] of [A] via transformation functions transforming [A] to [Option[A]] into a [Option[Tuple10]].

func TraverseTuple2

func TraverseTuple2[F1 ~Kleisli[A1, T1], F2 ~Kleisli[A2, T2], A1, T1, A2, T2 any](f1 F1, f2 F2) func(A1, A2) (T1, T2, bool)

TraverseTuple2 converts a [Tuple2] of [A] via transformation functions transforming [A] to [Option[A]] into a [Option[Tuple2]].

func TraverseTuple3

func TraverseTuple3[F1 ~Kleisli[A1, T1], F2 ~Kleisli[A2, T2], F3 ~Kleisli[A3, T3], A1, T1, A2, T2, A3, T3 any](f1 F1, f2 F2, f3 F3) func(A1, A2, A3) (T1, T2, T3, bool)

TraverseTuple3 converts a [Tuple3] of [A] via transformation functions transforming [A] to [Option[A]] into a [Option[Tuple3]].

func TraverseTuple4

func TraverseTuple4[F1 ~Kleisli[A1, T1], F2 ~Kleisli[A2, T2], F3 ~Kleisli[A3, T3], F4 ~Kleisli[A4, T4], 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, bool)

TraverseTuple4 converts a [Tuple4] of [A] via transformation functions transforming [A] to [Option[A]] into a [Option[Tuple4]].

func TraverseTuple5

func TraverseTuple5[F1 ~Kleisli[A1, T1], F2 ~Kleisli[A2, T2], F3 ~Kleisli[A3, T3], F4 ~Kleisli[A4, T4], F5 ~Kleisli[A5, T5], 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, bool)

TraverseTuple5 converts a [Tuple5] of [A] via transformation functions transforming [A] to [Option[A]] into a [Option[Tuple5]].

func TraverseTuple6

func TraverseTuple6[F1 ~Kleisli[A1, T1], F2 ~Kleisli[A2, T2], F3 ~Kleisli[A3, T3], F4 ~Kleisli[A4, T4], F5 ~Kleisli[A5, T5], F6 ~Kleisli[A6, T6], 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, bool)

TraverseTuple6 converts a [Tuple6] of [A] via transformation functions transforming [A] to [Option[A]] into a [Option[Tuple6]].

func TraverseTuple7

func TraverseTuple7[F1 ~Kleisli[A1, T1], F2 ~Kleisli[A2, T2], F3 ~Kleisli[A3, T3], F4 ~Kleisli[A4, T4], F5 ~Kleisli[A5, T5], F6 ~Kleisli[A6, T6], F7 ~Kleisli[A7, T7], 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, bool)

TraverseTuple7 converts a [Tuple7] of [A] via transformation functions transforming [A] to [Option[A]] into a [Option[Tuple7]].

func TraverseTuple8

func TraverseTuple8[F1 ~Kleisli[A1, T1], F2 ~Kleisli[A2, T2], F3 ~Kleisli[A3, T3], F4 ~Kleisli[A4, T4], F5 ~Kleisli[A5, T5], F6 ~Kleisli[A6, T6], F7 ~Kleisli[A7, T7], F8 ~Kleisli[A8, T8], 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, bool)

TraverseTuple8 converts a [Tuple8] of [A] via transformation functions transforming [A] to [Option[A]] into a [Option[Tuple8]].

func TraverseTuple9

func TraverseTuple9[F1 ~Kleisli[A1, T1], F2 ~Kleisli[A2, T2], F3 ~Kleisli[A3, T3], F4 ~Kleisli[A4, T4], F5 ~Kleisli[A5, T5], F6 ~Kleisli[A6, T6], F7 ~Kleisli[A7, T7], F8 ~Kleisli[A8, T8], F9 ~Kleisli[A9, T9], 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, bool)

TraverseTuple9 converts a [Tuple9] of [A] via transformation functions transforming [A] to [Option[A]] into a [Option[Tuple9]].

Types

type Endomorphism

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

Endomorphism represents a function from type T to type T. It is commonly used for transformations that preserve the type.

type Functor

type Functor[A, B any] interface {
	Map(func(A) B) func(A, bool) (B, bool)
}

func MakeFunctor

func MakeFunctor[A, B any]() Functor[A, B]

Functor implements the functoric operations for Option. A functor is a type that can be mapped over, transforming the contained value while preserving the structure.

Example:

f := Functor[int, string]()
mapper := f.Map(strconv.Itoa)
result := mapper(Some(42)) // Some("42")

type Kleisli

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

func FromNonZero

func FromNonZero[A comparable]() Kleisli[A, A]

FromNonZero returns a function that creates an Option based on whether a value is non-zero. Returns Some if the value is non-zero, None otherwise.

Example:

checkNonZero := FromNonZero[int]()
result := checkNonZero(5)  // Some(5)
result := checkNonZero(0)  // None

func FromPredicate

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

FromPredicate returns a function that creates an Option based on a predicate. The returned function will wrap a value in Some if the predicate is satisfied, otherwise None.

Parameters:

  • pred: A predicate function that determines if a value should be wrapped in Some

Example:

isPositive := FromPredicate(N.MoreThan(0))
result := isPositive(5)  // Some(5)
result := isPositive(-1) // None

func FromZero

func FromZero[A comparable]() Kleisli[A, A]

FromZero returns a function that creates an Option based on whether a value is the zero value. Returns Some if the value is the zero value, None otherwise.

Example:

checkZero := FromZero[int]()
result := checkZero(0)  // Some(0)
result := checkZero(5)  // None

func TraverseArray

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

TraverseArray transforms an array by applying a function that returns an Option to each element. Returns Some containing the array of results if all operations succeed, None if any fails.

Example:

validate := func(x int) Option[int] {
    if x > 0 { return Some(x * 2) }
    return None[int]()
}
result := TraverseArray(validate)([]int{1, 2, 3}) // Some([2, 4, 6])
result := TraverseArray(validate)([]int{1, -1, 3}) // None

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 an Option to each element. Returns Some containing the array of results if all operations succeed, None if any fails. This is the generic version that works with custom slice types.

Example:

parse := func(s string) Option[int] {
    n, err := strconv.Atoi(s)
    if err != nil { return None[int]() }
    return Some(n)
}
result := TraverseArrayG[[]string, []int](parse)([]string{"1", "2", "3"}) // Some([1, 2, 3])
result := TraverseArrayG[[]string, []int](parse)([]string{"1", "x", "3"}) // None

func TraverseArrayWithIndex

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

TraverseArrayWithIndex transforms an array by applying an indexed function that returns an Option. The function receives both the index and the element.

Example:

f := func(i int, x int) Option[int] {
    if x > i { return Some(x) }
    return None[int]()
}
result := TraverseArrayWithIndex(f)([]int{1, 2, 3}) // Some([1, 2, 3])

func TraverseArrayWithIndexG

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

TraverseArrayWithIndexG transforms an array by applying an indexed function that returns an Option. The function receives both the index and the element. This is the generic version that works with custom slice types.

Example:

f := func(i int, s string) Option[string] {
    return Some(fmt.Sprintf("%d:%s", i, s))
}
result := TraverseArrayWithIndexG[[]string, []string](f)([]string{"a", "b"}) // Some(["0:a", "1:b"])

func TraverseIter

func TraverseIter[A, B any](f Kleisli[A, B]) Kleisli[Seq[A], Seq[B]]

TraverseIter transforms a sequence by applying a function that returns an Option to each element. Returns Some containing a sequence of results if all operations succeed, None if any fails. This function is useful for processing sequences where each element may fail validation or transformation.

The traversal short-circuits on the first None encountered, making it efficient for validation pipelines. The resulting sequence is lazy and will only be evaluated when iterated.

Example:

// Parse a sequence of strings to integers
parse := func(s string) Option[int] {
    n, err := strconv.Atoi(s)
    if err != nil { return None[int]() }
    return Some(n)
}

// Create a sequence of strings
strings := func(yield func(string) bool) {
    for _, s := range []string{"1", "2", "3"} {
        if !yield(s) { return }
    }
}

result := TraverseIter(parse)(strings)
// result is Some(sequence of [1, 2, 3])

// With invalid input
invalidStrings := func(yield func(string) bool) {
    for _, s := range []string{"1", "invalid", "3"} {
        if !yield(s) { return }
    }
}

result := TraverseIter(parse)(invalidStrings)
// result is None because "invalid" cannot be parsed
Example

Example test demonstrating usage

// Parse a sequence of strings to integers
parse := func(s string) (int, bool) {
	n, err := strconv.Atoi(s)
	if err != nil {
		return None[int]()
	}
	return Some(n)
}

// Create a sequence of valid strings
validStrings := seqFromSlice([]string{"1", "2", "3"})
result, resultok := TraverseIter(parse)(validStrings)

if IsSome(result, resultok) {
	numbers := collectSeq(result)
	fmt.Println(numbers)
}

// Create a sequence with invalid string
invalidStrings := seqFromSlice([]string{"1", "invalid", "3"})
result2, result2ok := TraverseIter(parse)(invalidStrings)

if IsNone(result2, result2ok) {
	fmt.Println("Parsing failed")
}
Output:

[1 2 3]
Parsing failed

func TraverseRecord

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

TraverseRecord transforms a record (map) by applying a function that returns an Option to each value. Returns Some containing the map of results if all operations succeed, None if any fails.

Example:

validate := func(x int) Option[string] {
    if x > 0 { return Some(fmt.Sprintf("%d", x)) }
    return None[string]()
}
input := map[string]int{"a": 1, "b": 2}
result := TraverseRecord(validate)(input) // Some(map[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 record (map) by applying a function that returns an Option to each value. Returns Some containing the map of results if all operations succeed, None if any fails. This is the generic version that works with custom map types.

Example:

validate := func(x int) Option[int] {
    if x > 0 { return Some(x * 2) }
    return None[int]()
}
input := map[string]int{"a": 1, "b": 2}
result := TraverseRecordG[map[string]int, map[string]int](validate)(input) // Some(map[a:2 b:4])

func TraverseRecordWithIndex

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

TraverseRecordWithIndex transforms a record by applying a function that receives both key and value. Returns Some containing the map of results if all operations succeed, None if any fails.

Example:

f := func(k string, v int) Option[int] {
    if v > 0 { return Some(v) }
    return None[int]()
}
input := map[string]int{"a": 1, "b": 2}
result := TraverseRecordWithIndex(f)(input) // Some(map[a:1 b:2])

func TraverseRecordWithIndexG

func TraverseRecordWithIndexG[GA ~map[K]A, GB ~map[K]B, K comparable, A, B any](f func(K, A) (B, bool)) Kleisli[GA, GB]

TraverseRecordWithIndexG transforms a record by applying a function that receives both key and value. Returns Some containing the map of results if all operations succeed, None if any fails. This is the generic version that works with custom map types.

Example:

f := func(k string, v int) Option[string] {
    return Some(fmt.Sprintf("%s:%d", k, v))
}
input := map[string]int{"a": 1, "b": 2}
result := TraverseRecordWithIndexG[map[string]int, map[string]string](f)(input) // Some(map[a:"a:1" b:"b:2"])

type Operator

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

func Alt

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

Alt returns a function that provides an alternative Option if the input is None.

Parameters:

  • that: A function that provides an alternative Option

Example:

withDefault := Alt(func() (int, bool) { return 0, true })
result := withDefault(Some(5)) // Some(5)
result := withDefault(None[int]()) // Some(0)

func Ap

func Ap[B, A any](fa A, faok bool) Operator[func(A) B, B]

Ap is the curried applicative functor for Option. Returns a function that applies an Option-wrapped function to the given Option value.

Parameters:

  • fa: The value of the Option
  • faok: Whether the Option contains a value (true for Some, false for None)

Example:

fa := Some(5)
applyTo5 := Ap[int](fa)
fab := Some(N.Mul(2))
result := applyTo5(fab) // Some(10)

func Bind

func Bind[S1, S2, A any](
	setter func(A) func(S1) S2,
	f Kleisli[S1, A],
) Operator[S1, S2]

Bind attaches the result of a computation to a context S1 to produce a context S2. This is used in do-notation style to sequentially build up a context.

Parameters:

  • setter: A function that takes a value and returns a function to update the context
  • f: A function that computes an Option value from the current context

Example:

type State struct { x int; y int }
result := F.Pipe2(
    Do(State{}),
    Bind(func(x int) func(State) State {
        return func(s State) State { s.x = x; return s }
    }, func(s State) (int, bool) { return 42, true }),
)

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 an Option 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.

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 return None if it would exceed 100
increment := func(v int) option.Option[int] {
    if v >= 100 {
        return option.None[int]()
    }
    return option.Some(v + 1)
}

result := F.Pipe1(
    option.Some(Counter{Value: 42}),
    option.BindL(valueLens, increment),
) // Some(Counter{Value: 43})

Parameters:

  • lens: A lens that focuses on a field within the structure S
  • f: A function that computes an Option value from the current field value

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 as the first operation after creating an Option value.

Parameters:

  • setter: A function that creates the initial context from a value

Example:

type State struct { value int }
result := F.Pipe1(
    Some(42),
    BindTo(func(x int) State { return State{value: x} }),
)

func Chain

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

Chain returns a function that applies an Option-returning function to an Option value. This is the curried form of the monadic bind operation.

Parameters:

  • f: A function that takes a value and returns an Option

Example:

validate := Chain(func(x int) (int, bool) {
    if x > 0 { return x * 2, true }
    return 0, false
})
result := validate(Some(5)) // Some(10)

func ChainFirst

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

ChainFirst returns a function that applies an Option-returning function but keeps the original value.

Parameters:

  • f: A function that takes a value and returns an Option (result is used only for success/failure)

Example:

logAndKeep := ChainFirst(func(x int) (string, bool) {
    fmt.Println(x)
    return "logged", true
})
result := logAndKeep(Some(5)) // Some(5)

func ChainTo

func ChainTo[A, B any](b B, bok bool) Operator[A, B]

ChainTo returns a function that ignores its input Option and returns a fixed Option.

Parameters:

  • b: The value of the replacement Option
  • bok: Whether the replacement Option contains a value

Example:

replaceWith := ChainTo(Some("hello"))
result := replaceWith(Some(42)) // Some("hello")

func Filter

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

Filter keeps the Option if it's Some and the predicate is satisfied, otherwise returns None.

Parameters:

  • pred: A predicate function to test the Option value

Example:

isPositive := Filter(N.MoreThan(0))
result := isPositive(Some(5)) // Some(5)
result := isPositive(Some(-1)) // None
result := isPositive(None[int]()) // None

func Flap

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

Flap returns a function that applies a value to an Option-wrapped function.

Parameters:

  • a: The value to apply to the function

Example:

applyFive := Flap[int](5)
fab := Some(N.Mul(2))
result := applyFive(fab) // Some(10)

func Let

func Let[S1, S2, B any](
	key func(B) func(S1) S2,
	f func(S1) B,
) Operator[S1, S2]

Let attaches the result of a pure computation to a context S1 to produce a context S2. Unlike Bind, the computation function returns a plain value, not an Option.

Parameters:

  • key: A function that takes a value and returns a function to update the context
  • f: A pure function that computes a value from the current context

Example:

type State struct { x int; computed int }
result := F.Pipe2(
    Do(State{x: 5}),
    Let(func(c int) func(State) State {
        return func(s State) State { s.computed = c; return s }
    }, func(s State) int { return s.x * 2 }),
)

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 Option).

This is useful for pure transformations that cannot fail, such as mathematical operations, string manipulations, or other deterministic updates.

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(
    option.Some(Counter{Value: 21}),
    option.LetL(valueLens, double),
) // Some(Counter{Value: 42})

Parameters:

  • lens: A lens that focuses on a field within the structure S
  • f: A pure transformation function for the field value

func LetTo

func LetTo[S1, S2, B any](
	key func(B) func(S1) S2,
	b B,
) Operator[S1, S2]

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

Parameters:

  • key: A function that takes a value and returns a function to update the context
  • b: The constant value to attach to the context

Example:

type State struct { x int; name string }
result := F.Pipe2(
    Do(State{x: 5}),
    LetTo(func(n string) func(State) State {
        return func(s State) State { s.name = n; return s }
    }, "example"),
)

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.

This is useful for resetting fields, initializing values, or setting fields to predetermined constants.

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

Parameters:

  • lens: A lens that focuses on a field within the structure S
  • b: The constant value to set the field to

func Map

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

Map returns a function that applies a transformation to the value inside an Option. If the Option is None, returns None.

Parameters:

  • f: A transformation function to apply to the Option value

Example:

double := Map(N.Mul(2))
result := double(Some(5)) // Some(10)
result := double(None[int]()) // None

func MapTo

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

MapTo returns a function that replaces the value inside an Option with a constant.

Parameters:

  • b: The constant value to replace with

Example:

replaceWith42 := MapTo[string, int](42)
result := replaceWith42(Some("hello")) // Some(42)

type Pointed

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

func MakePointed

func MakePointed[A any]() Pointed[A]

Pointed implements the Pointed operations for Option. A pointed functor is a functor with an Of operation that wraps a value.

Example:

p := Pointed[int]()
result := p.Of(42) // Some(42)

type Seq

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

Seq is an iterator sequence type alias for working with Go 1.23+ iterators.

Directories

Path Synopsis
Package number provides Option-based utilities for number conversions.
Package number provides Option-based utilities for number conversions.

Jump to

Keyboard shortcuts

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