either

package
v0.27.0 Latest Latest
Warning

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

Go to latest
Published: Mar 1, 2026 License: MIT Imports: 0 Imported by: 0

README

either

Typed alternatives with compiler-enforced exhaustive handling.

Left = failure, Right = success. Mnemonic: "right is right."

// Before: interface switch can silently miss a case
switch u := user.(type) {
case Admin:
    return u.Dashboard()
case Guest:
    return u.Landing()
}
// add SuperUser later? Nothing breaks. It just falls through.

// After: Fold requires both handlers — can't compile without them
view := either.Fold(user, Admin.Dashboard, Guest.Landing)

Six lines become one.

What It Looks Like

// Mode dispatch — either isn't just for errors
timeout := either.Fold(config,
    func(l LocalConfig) int { return l.Timeout },
    func(r RemoteConfig) int { return r.Timeout },
)
// Comma-ok extraction
if cfg, ok := result.Get(); ok {
    fmt.Println("loaded:", cfg.Name)
}
// Default value
cfg := result.GetOr(fallbackConfig)
// Side effect — fires only if Right
result.IfRight(Repo.Save)

Exhaustive by Construction

Fold is a compile-time exhaustive match — the parse, don't validate pattern for Go:

  • Both handler functions are required parameters — you can't forget a case
  • Both must return the same type — the result is always well-typed
  • No default/fallback branch — every state is explicitly handled

Go's control flow doesn't enforce that all variants are handled. Fold does.

Either as Architecture

A single Either[L, R] type can flow through multiple dispatch sites. Each Fold handles both cases — every new dispatch site must account for both. Change either type's interface and the compiler catches every site that needs updating.

Consider an application with two modes — setup and running. The mode flows through the entire render path:

type AppState = either.Either[Setup, Running]

// Multiple sites, all exhaustive
title   := either.Fold(state, Setup.Title, Running.Title)
canEdit := either.Fold(state, Setup.CanEdit, Running.CanEdit)
view    := either.Fold(state, Setup.Render, Running.Render)

Every site that touches AppState must handle both cases. The compiler enforces this everywhere Fold appears.

Operations

Either[L, R] holds exactly one of two types. Fold, Map, and MapLeft are package-level functions — Go methods can't introduce new type parameters.

  • Create: Left, Right
  • Extract: Get, GetLeft, IsLeft, IsRight, MustGet, MustGetLeft, GetOr, LeftOr, GetOrCall, LeftOrCall
  • Transform: .Map, Map, MapLeft, Fold
  • Side effects: IfRight, IfLeft

See pkg.go.dev for complete API documentation, the main README for installation, and option for absent values without failure context.

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, IfRight, GetOr operate on the Right value. Use MapLeft, MustGetLeft, IfLeft, 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]) 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]) IfLeft added in v0.23.0

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

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

func (Either[L, R]) IfRight added in v0.23.0

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

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

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