either

package
v0.19.0 Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2026 License: MIT Imports: 0 Imported by: 0

README

either: sum types for Go

A value that is one of two types: Left or Right. Convention: Left = failure, Right = success. Mnemonic: "Right is right."

A sum type holds exactly one of two possible types—here, either L or R.

result := ParseConfig(input)  // Either[ParseError, Config]
if cfg, ok := result.Get(); ok {
    fmt.Println("loaded:", cfg.Name)
}

See pkg.go.dev for complete API documentation. For function naming patterns, see Naming Functions for Higher-Order Functions.

Quick Start

import "github.com/binaryphile/fluentfp/either"

// Create values
fail := either.Left[string, int]("fail")
ok42 := either.Right[string, int](42)

// Extract with comma-ok
if fortyTwo, ok := ok42.Get(); ok {
    fmt.Println(fortyTwo)  // 42
}

// Get with default
fortyTwo := ok42.GetOr(0)

// Fold: handle both cases exhaustively
// onError returns -1 for any error.
onError := func(err string) int { return -1 }
// useValue returns the value unchanged.
useValue := func(n int) int { return n }
result := either.Fold(ok42, onError, useValue)   // 42
result = either.Fold(fail, onError, useValue)    // -1

Types

Either[L,R] holds exactly one value—a Left of type L, or a Right of type R:

success := either.Right[ParseError, Config](cfg)  // Either[ParseError, Config]
failure := either.Left[ParseError, Config](err)   // Either[ParseError, Config]

API Reference

Constructors
Function Signature Purpose Example
Left Left[L,R](L) Either[L,R] Create Left variant either.Left[Error, User](err)
Right Right[L,R](R) Either[L,R] Create Right variant either.Right[Error, User](user)
Methods
Method Signature Purpose Example
.IsLeft .IsLeft() bool Check if Left if result.IsLeft()
.IsRight .IsRight() bool Check if Right if result.IsRight()
.Get .Get() (R, bool) Get Right (comma-ok) user, ok := result.Get()
.GetLeft .GetLeft() (L, bool) Get Left (comma-ok) err, ok := result.GetLeft()
.GetOr .GetOr(R) R Right or default user = result.GetOr(fallback)
.LeftOr .LeftOr(L) L Left or default err = result.LeftOr(fallback)
.Map .Map(func(R) R) Either[L,R] Transform Right normalized = result.Map(User.Normalize)
Standalone Functions
Function Signature Purpose Example
Fold Fold[L,R,T](Either, func(L)T, func(R)T) T Handle both cases, return one result See Exhaustive Handling
Map Map[L,R,R2](Either, func(R)R2) Either[L,R2] Transform to new type name = either.Map(result, User.Name)

Note: Fold and Map are functions (not methods) due to Go's generics limitation—methods cannot introduce new type parameters.

Either vs Option

Type Use Case Example
option.Basic[T] Value may be absent Database nullable field
either.Either[L, R] One of two distinct states Success OR failure with reason

Option is for "maybe nothing." Either is for "definitely something, but which one?"

Patterns

Parse, Don't Validate

Return structured failure information instead of just bool or error:

type ParseError struct {
    Line   int
    Reason string
}

func ParseConfig(input string) either.Either[ParseError, Config]

// Caller gets actionable failure context
result := ParseConfig(raw)
if cfg, ok := result.Get(); ok {
    return cfg
}
if err, ok := result.GetLeft(); ok {
    log.Printf("Parse failed at line %d: %s", err.Line, err.Reason)
}
Exhaustive Handling

Fold takes two functions—one for Left, one for Right—and returns a single result. Both functions must return the same type, forcing you to handle both cases:

// formatError returns a user-friendly error message.
formatError := func(err ParseError) string {
    return fmt.Sprintf("line %d: %s", err.Line, err.Reason)
}

// formatSuccess returns a success message with the config name.
formatSuccess := func(cfg Config) string {
    return fmt.Sprintf("loaded: %s", cfg.Name)
}

message := either.Fold(result, formatError, formatSuccess)
Two-State Structs

Replace pairs of nullable fields with explicit Either:

// Before: which field is set? nil checks scattered everywhere
type Handler struct {
    syncFn  *func()
    asyncFn *func() <-chan Result
}

// After: exactly one mode, exhaustively handled
type Handler struct {
    mode either.Either[func(), func() <-chan Result]
}

When NOT to Use either

  • Error handling — Use (T, error) for Go idiom; Either is for typed alternatives
  • Optional values — Use option.Basic[T] when one side is "absent"
  • More than two variants — Either is binary; use interface + types for 3+
  • Simple boolean checks — Don't use Either[FalseReason, TrueReason] for simple yes/no
  • When Go idioms suffice — If comma-ok or (T, error) is clear, don't over-engineer

See Also

For simple absent values without failure info, see option.

Documentation

Overview

Package either provides a sum type representing a value of one of two types.

Convention: Left represents failure/error, Right represents success. Mnemonic: "Right is right" (correct).

Either is right-biased: Map, MustGet, Call, GetOr operate on the Right value. Use MapLeft, MustGetLeft, CallLeft, LeftOr for Left-side operations.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Fold

func Fold[L, R, T any](e Either[L, R], onLeft func(L) T, onRight func(R) T) T

Fold applies onLeft if e is Left, or onRight if e is Right.

Types

type Either

type Either[L, R any] struct {
	// contains filtered or unexported fields
}

Either represents a value of one of two types. Convention: Left for failure, Right for success.

func Left

func Left[L, R any](l L) Either[L, R]

Left returns a Left Either containing l.

func Map added in v0.8.1

func Map[L, R, R2 any](e Either[L, R], fn func(R) R2) Either[L, R2]

Map applies fn to the Right value and returns a new Either with a different Right type. If e is Left, returns the Left value unchanged.

func MapLeft added in v0.8.1

func MapLeft[L, R, L2 any](e Either[L, R], fn func(L) L2) Either[L2, R]

MapLeft applies fn to the Left value and returns a new Either with a different Left type. If e is Right, returns the Right value unchanged.

func Right[L, R any](r R) Either[L, R]

Right returns a Right Either containing r.

func (Either[L, R]) Call added in v0.8.1

func (e Either[L, R]) Call(fn func(R))

Call applies fn to the Right value if e is Right. If e is Left, does nothing.

func (Either[L, R]) CallLeft added in v0.8.1

func (e Either[L, R]) CallLeft(fn func(L))

CallLeft applies fn to the Left value if e is Left. If e is Right, does nothing.

func (Either[L, R]) Get

func (e Either[L, R]) Get() (_ R, _ bool)

Get returns the Right value and true, or zero and false if Left.

func (Either[L, R]) GetLeft

func (e Either[L, R]) GetLeft() (_ L, _ bool)

GetLeft returns the Left value and true, or zero and false if Right.

func (Either[L, R]) GetOr added in v0.11.0

func (e Either[L, R]) GetOr(defaultVal R) R

GetOr returns the Right value, or defaultVal if Left.

func (Either[L, R]) GetOrCall added in v0.8.1

func (e Either[L, R]) GetOrCall(fn func() R) R

GetOrCall returns the Right value, or the result of calling fn if e is Left.

func (Either[L, R]) IsLeft

func (e Either[L, R]) IsLeft() bool

IsLeft reports whether e is a Left.

func (Either[L, R]) IsRight

func (e Either[L, R]) IsRight() bool

IsRight reports whether e is a Right.

func (Either[L, R]) LeftOr added in v0.11.0

func (e Either[L, R]) LeftOr(defaultVal L) L

LeftOr returns the Left value, or defaultVal if Right.

func (Either[L, R]) LeftOrCall added in v0.8.1

func (e Either[L, R]) LeftOrCall(fn func() L) L

LeftOrCall returns the Left value, or the result of calling fn if e is Right.

func (Either[L, R]) Map

func (e Either[L, R]) Map(fn func(R) R) Either[L, R]

Map applies fn to the Right value and returns a new Either. If e is Left, returns e unchanged.

func (Either[L, R]) MustGet added in v0.8.1

func (e Either[L, R]) MustGet() R

MustGet returns the Right value or panics if e is Left.

func (Either[L, R]) MustGetLeft added in v0.8.1

func (e Either[L, R]) MustGetLeft() L

MustGetLeft returns the Left value or panics if e is Right.

Jump to

Keyboard shortcuts

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