Documentation
¶
Overview ¶
package either implements the Either monad
A data type that can be of either of two types but not both. This is typically used to carry an error or a return value
Package either provides implementations of the Either type and related operations.
This package implements several Fantasy Land algebraic structures:
The Filterable specification defines operations for filtering and partitioning data structures based on predicates and mapping functions.
package option implements the Option monad, a data type that can have a defined value or none
Package optional provides an optic for focusing on values that may not exist.
Overview ¶
Optional is an optic used to zoom inside a product. Unlike the Lens, the element that the Optional focuses on may not exist. An Optional[S, A] represents a relationship between a source type S and a focus type A, where the focus may or may not be present.
Optional Laws ¶
An Optional must satisfy the following laws, which are consistent with other functional programming libraries such as monocle-ts (https://gcanti.github.io/monocle-ts/modules/Optional.ts.html) and the Haskell lens library (https://hackage.haskell.org/package/lens):
GetSet Law (No-op on None): If GetOption(s) returns None, then Set(a)(s) must return s unchanged (no-op). This ensures that attempting to update a value that doesn't exist has no effect.
Formally: GetOption(s) = None => Set(a)(s) = s
SetGet Law (Get what you Set): If GetOption(s) returns Some(_), then GetOption(Set(a)(s)) must return Some(a). This ensures that after setting a value, you can retrieve it.
Formally: GetOption(s) = Some(_) => GetOption(Set(a)(s)) = Some(a)
SetSet Law (Last Set Wins): Setting twice is the same as setting once with the final value.
Formally: Set(b)(Set(a)(s)) = Set(b)(s)
No-op Behavior ¶
A key property of Optional is that updating a value for which GetOption returns None is a no-op. This behavior is implemented through the optionalModify function, which only applies the modification if the optional value exists. When GetOption returns None, the original structure is returned unchanged.
This is consistent with the behavior in:
- monocle-ts: Optional.modify returns the original value when the optional doesn't match
- Haskell lens: over and set operations are no-ops when the traversal finds no targets
Example ¶
type Person struct {
Name string
Age int
}
// Create an optional that focuses on non-empty names
nameOptional := MakeOptional(
func(p Person) option.Option[string] {
if p.Name != "" {
return option.Some(p.Name)
}
return option.None[string]()
},
func(p Person, name string) Person {
p.Name = name
return p
},
)
// When the optional matches, Set updates the value
person1 := Person{Name: "Alice", Age: 30}
updated1 := nameOptional.Set("Bob")(person1)
// updated1.Name == "Bob"
// When the optional doesn't match (Name is empty), Set is a no-op
person2 := Person{Name: "", Age: 30}
updated2 := nameOptional.Set("Bob")(person2)
// updated2 == person2 (unchanged)
Package prism provides utilities for converting prisms to optionals and working with Option types.
This package bridges the gap between prisms (which focus on sum types) and optionals (which focus on values that may not exist). The key functions allow you to:
- Convert any prism into an optional using AsOptional
- Focus on the Some variant of Option types using Some
These conversions maintain the optional laws, ensuring that the resulting optionals behave correctly with respect to GetOption and Set operations.
Index ¶
- func EitherApV[B, A, E any](sg S.Semigroup[E]) func(Either[E, A]) EitherOperator[E, func(A) B, B]
- func EitherBiMap[E1, E2, A, B any](f func(E1) E2, g func(a A) B) func(Either[E1, A]) Either[E2, B]
- func EitherChainOptionK[A, B, E any](onNone func() E) func(func(A) Option[B]) EitherOperator[E, A, B]
- func EitherCompactArray[E, A any](fa []Either[E, A]) []A
- func EitherCompactArrayG[A1 ~[]Either[E, A], A2 ~[]A, E, A any](fa A1) A2
- func EitherCompactRecord[K comparable, E, A any](m map[K]Either[E, A]) map[K]A
- func EitherCompactRecordG[M1 ~map[K]Either[E, A], M2 ~map[K]A, K comparable, E, A any](m M1) M2
- func EitherFold[E, A, B any](onLeft func(E) B, onRight func(A) B) func(Either[E, A]) B
- func EitherFromError[A any](f func(a A) error) func(A) Either[error, A]
- func EitherFromOption[A, E any](onNone func() E) func(Option[A]) Either[E, A]
- func EitherGetOrElse[E, A any](onLeft func(E) A) func(Either[E, A]) A
- func EitherIsLeft[E, A any](val Either[E, A]) bool
- func EitherIsRight[E, A any](val Either[E, A]) bool
- func EitherMapLeft[A, E1, E2 any](f func(E1) E2) func(fa Either[E1, A]) Either[E2, A]
- func EitherMonadApV[B, A, E any](sg S.Semigroup[E]) func(fab Either[E, func(a A) B], fa Either[E, A]) Either[E, B]
- func EitherMonadFold[E, A, B any](ma Either[E, A], onLeft func(e E) B, onRight func(a A) B) B
- func EitherPartition[E, A any](p Predicate[A], empty E) func(Either[E, A]) Pair[Either[E, A], Either[E, A]]
- func EitherPartitionMap[E, A, B, C any](f EitherKleisli[B, A, C], empty E) func(Either[E, A]) Pair[Either[E, B], Either[E, C]]
- func EitherReduce[E, A, B any](f func(B, A) B, initial B) func(Either[E, A]) B
- func EitherSequence2[E, T1, T2, R any](f func(T1, T2) Either[E, R]) func(Either[E, T1], Either[E, T2]) Either[E, R]
- func EitherSequence3[E, T1, T2, T3, R any](f func(T1, T2, T3) Either[E, R]) func(Either[E, T1], Either[E, T2], Either[E, T3]) Either[E, R]
- func EitherToError[A any](e Either[error, A]) error
- func EitherToType[A, E any](onError func(any) E) func(any) Either[E, A]
- func EitherUnwrap[E, A any](ma Either[E, A]) (A, E)
- func EitherUnwrapError[A any](ma Either[error, A]) (A, error)
- func IsoComposeIso[S, A, B any](ab Iso[A, B]) func(Iso[S, A]) Iso[S, B]
- func IsoComposeLens[S, A, B any](ab Lens[A, B]) func(Iso[S, A]) Lens[S, B]
- func IsoFrom[S, A any](a A) func(Iso[S, A]) S
- func IsoIMap[S, A, B any](ab func(A) B, ba func(B) A) func(Iso[S, A]) Iso[S, B]
- func IsoModify[S any, FCT ~func(A) A, A any](f FCT) func(Iso[S, A]) Endomorphism[S]
- func IsoTo[A, S any](s S) func(Iso[S, A]) A
- func IsoUnwrap[A, S any](s S) func(Iso[S, A]) A
- func IsoWrap[S, A any](a A) func(Iso[S, A]) S
- func LensComposePrism[S, A, B any](p Prism[A, B]) func(Lens[S, A]) Optional[S, B]
- func LensComposePrismRef[S, A, B any](p Prism[A, B]) func(Lens[*S, A]) Optional[*S, B]
- func LensModify[S any, FCT ~func(A) A, A any](f FCT) func(Lens[S, A]) Endomorphism[S]
- func LensModifyF[S, A, HKTA, HKTS any](fmap functor.MapType[A, S, HKTA, HKTS]) func(func(A) HKTA) func(Lens[S, A]) func(S) HKTS
- func LensSet[S any, A any](a A) func(Lens[S, A]) Endomorphism[S]
- func OptionCompactArray[A any](fa []Option[A]) []A
- func OptionCompactArrayG[A1 ~[]Option[A], A2 ~[]A, A any](fa A1) A2
- func OptionFold[A, B any](onNone func() B, onSome func(a A) B) func(Option[A]) B
- func OptionFromEq[A any](pred eq.Eq[A]) func(A) OptionKleisli[A, A]
- func OptionFromStrictEq[A comparable]() func(A) OptionKleisli[A, A]
- func OptionGetOrElse[A any](onNone func() A) func(Option[A]) A
- func OptionIsNone[T any](val Option[T]) bool
- func OptionIsSome[T any](val Option[T]) bool
- func OptionMonadFold[A, B any](ma Option[A], onNone func() B, onSome func(A) B) B
- func OptionMonadGetOrElse[A any](fa Option[A], onNone func() A) A
- func OptionReduce[A, B any](f func(B, A) B, initial B) func(Option[A]) B
- func OptionSequence2[T1, T2, R any](f func(T1, T2) Option[R]) func(Option[T1], Option[T2]) Option[R]
- func OptionToNillable2[A any](fa Option[A]) *A
- func OptionUnwrap[A any](ma Option[A]) (A, bool)
- func OptionalAsTraversal[R ~func(func(A) HKTA) func(S) HKTS, S, A, HKTS, HKTA any](fof pointed.OfType[S, HKTS], fmap functor.MapType[A, S, HKTA, HKTS]) func(Optional[S, A]) R
- func OptionalFromPredicate[S, A any](pred func(A) bool) func(func(S) A, func(S, A) S) Optional[S, A]
- func OptionalFromPredicateRef[S, A any](pred func(A) bool) func(func(*S) A, func(*S, A) *S) Optional[*S, A]
- func OptionalModifyOption[S, A any](f func(A) A) func(Optional[S, A]) OptionKleisli[S, S]
- func OptionalSetOption[S, A any](a A) func(Optional[S, A]) OptionKleisli[S, S]
- func PrismAsTraversal[R ~func(func(A) HKTA) func(S) HKTS, S, A, HKTS, HKTA any](fof pointed.OfType[S, HKTS], fmap functor.MapType[A, S, HKTA, HKTS]) func(Prism[S, A]) R
- func PrismSet[S, A any](a A) func(Prism[S, A]) Endomorphism[S]
- type Either
- func EitherFlatten[E, A any](mma Either[E, Either[E, A]]) Either[E, A]
- func EitherFromIO[E any, IO ~func() A, A any](f IO) Either[E, A]
- func EitherLeft[A, E any](value E) Either[E, A]
- func EitherMemoize[E, A any](val Either[E, A]) Either[E, A]
- func EitherMonadAlt[E, A any](fa Either[E, A], that func() Either[E, A]) Either[E, A]
- func EitherMonadAp[B, E, A any](fab Either[E, func(a A) B], fa Either[E, A]) Either[E, B]
- func EitherMonadBiMap[E1, E2, A, B any](fa Either[E1, A], f func(E1) E2, g func(a A) B) Either[E2, B]
- func EitherMonadChain[E, A, B any](fa Either[E, A], f EitherKleisli[E, A, B]) Either[E, B]
- func EitherMonadChainFirst[E, A, B any](ma Either[E, A], f EitherKleisli[E, A, B]) Either[E, A]
- func EitherMonadChainLeft[EA, EB, A any](fa Either[EA, A], f EitherKleisli[EB, EA, A]) Either[EB, A]
- func EitherMonadChainOptionK[A, B, E any](onNone func() E, ma Either[E, A], f func(A) Option[B]) Either[E, B]
- func EitherMonadChainTo[A, E, B any](_ Either[E, A], mb Either[E, B]) Either[E, B]
- func EitherMonadExtend[E, A, B any](fa Either[E, A], f func(Either[E, A]) B) Either[E, B]
- func EitherMonadFlap[E, B, A any](fab Either[E, func(A) B], a A) Either[E, B]
- func EitherMonadMap[E, A, B any](fa Either[E, A], f func(A) B) Either[E, B]
- func EitherMonadMapLeft[E1, A, E2 any](fa Either[E1, A], f func(E1) E2) Either[E2, A]
- func EitherMonadMapTo[E, A, B any](fa Either[E, A], b B) Either[E, B]
- func EitherMonadSequence2[E, T1, T2, R any](e1 Either[E, T1], e2 Either[E, T2], f func(T1, T2) Either[E, R]) Either[E, R]
- func EitherMonadSequence3[E, T1, T2, T3, R any](e1 Either[E, T1], e2 Either[E, T2], e3 Either[E, T3], ...) Either[E, R]
- func EitherOf[E, A any](value A) Either[E, A]
- func EitherRight[E, A any](value A) Either[E, A]
- func EitherSequenceArray[E, A any](ma []Either[E, A]) Either[E, []A]
- func EitherSequenceArrayG[GA ~[]A, GOA ~[]Either[E, A], E, A any](ma GOA) Either[E, GA]
- func EitherSequenceRecord[K comparable, E, A any](ma map[K]Either[E, A]) Either[E, map[K]A]
- func EitherSequenceRecordG[GA ~map[K]A, GOA ~map[K]Either[E, A], K comparable, E, A any](ma GOA) Either[E, GA]
- func EitherSequenceSeq[E, A any](ma iter.Seq[Either[E, A]]) Either[E, iter.Seq[A]]
- func EitherSwap[E, A any](val Either[E, A]) Either[A, E]
- func EitherTryCatch[FE func(error) E, E, A any](val A, err error, onThrow FE) Either[E, A]
- func EitherTryCatchError[A any](val A, err error) Either[error, A]
- func EitherZero[E, A any]() Either[E, A]
- type EitherKleisli
- func EitherAltAllArray[E, A any](startWith Either[E, A]) EitherKleisli[E, []Either[E, A], A]
- func EitherAltAllSeq[E, A any](startWith Either[E, A]) EitherKleisli[E, iter.Seq[Either[E, A]], A]
- func EitherAltW[E, E1, A any](that func() Either[E1, A]) EitherKleisli[E1, Either[E, A], A]
- func EitherChainLeft[EA, EB, A any](f EitherKleisli[EB, EA, A]) EitherKleisli[EB, Either[EA, A], A]
- func EitherFromNillable[A, E any](e E) EitherKleisli[E, *A, *A]
- func EitherFromPredicate[E, A any](pred Predicate[A], onFalse func(A) E) EitherKleisli[E, A, A]
- func EitherOrElse[E1, E2, A any](onLeft EitherKleisli[E2, E1, A]) EitherKleisli[E2, Either[E1, A], A]
- func EitherTraverseArray[E, A, B any](f EitherKleisli[E, A, B]) EitherKleisli[E, []A, []B]
- func EitherTraverseArrayG[GA ~[]A, GB ~[]B, E, A, B any](f EitherKleisli[E, A, B]) EitherKleisli[E, GA, GB]
- func EitherTraverseArrayWithIndex[E, A, B any](f func(int, A) Either[E, B]) EitherKleisli[E, []A, []B]
- func EitherTraverseArrayWithIndexG[GA ~[]A, GB ~[]B, E, A, B any](f func(int, A) Either[E, B]) EitherKleisli[E, GA, GB]
- func EitherTraverseRecord[K comparable, E, A, B any](f EitherKleisli[E, A, B]) EitherKleisli[E, map[K]A, map[K]B]
- func EitherTraverseRecordG[GA ~map[K]A, GB ~map[K]B, K comparable, E, A, B any](f EitherKleisli[E, A, B]) EitherKleisli[E, GA, GB]
- func EitherTraverseRecordWithIndex[K comparable, E, A, B any](f func(K, A) Either[E, B]) EitherKleisli[E, map[K]A, map[K]B]
- func EitherTraverseRecordWithIndexG[GA ~map[K]A, GB ~map[K]B, K comparable, E, A, B any](f func(K, A) Either[E, B]) EitherKleisli[E, GA, GB]
- func EitherTraverseSeq[E, A, B any](f EitherKleisli[E, A, B]) EitherKleisli[E, iter.Seq[A], iter.Seq[B]]
- func EitherWithResource[A, E, R, ANY any](onCreate func() Either[E, R], onRelease EitherKleisli[E, R, ANY]) EitherKleisli[E, EitherKleisli[E, R, A], A]
- type EitherOperator
- func EitherAlt[E, A any](that func() Either[E, A]) EitherOperator[E, A, A]
- func EitherAp[B, E, A any](fa Either[E, A]) EitherOperator[E, func(A) B, B]
- func EitherChain[E, A, B any](f EitherKleisli[E, A, B]) EitherOperator[E, A, B]
- func EitherChainFirst[E, A, B any](f EitherKleisli[E, A, B]) EitherOperator[E, A, A]
- func EitherChainTo[A, E, B any](mb Either[E, B]) EitherOperator[E, A, B]
- func EitherExtend[E, A, B any](f func(Either[E, A]) B) EitherOperator[E, A, B]
- func EitherFilter[E, A any](p Predicate[A], empty E) EitherOperator[E, A, A]
- func EitherFilterMap[E, A, B any](f OptionKleisli[A, B], empty E) EitherOperator[E, A, B]
- func EitherFlap[E, B, A any](a A) EitherOperator[E, func(A) B, B]
- func EitherMap[E, A, B any](f func(A) B) EitherOperator[E, A, B]
- func EitherMapTo[E, A, B any](b B) EitherOperator[E, A, B]
- type EitherTraversable
- type Endomorphism
- type Iso
- type Lens
- func IsoAsLens[S, A any](sa Iso[S, A]) Lens[S, A]
- func IsoAsLensRef[S, A any](sa Iso[*S, A]) Lens[*S, A]deprecated
- func LensId[S any]() Lens[S, S]
- func LensIdRef[S any]() Lens[*S, *S]
- func MakeLens[GET ~func(S) A, SET ~func(S, A) S, S, A any](get GET, set SET) Lens[S, A]
- func MakeLensCurried[GET ~func(S) A, SET ~func(A) Endomorphism[S], S, A any](get GET, set SET) Lens[S, A]
- func MakeLensCurriedRefWithName[GET ~func(*S) A, SET ~func(A) Endomorphism[*S], S, A any](get GET, set SET, name string) Lens[*S, A]
- func MakeLensCurriedWithName[GET ~func(S) A, SET ~func(A) Endomorphism[S], S, A any](get GET, set SET, name string) Lens[S, A]
- func MakeLensRef[GET ~func(*S) A, SET func(*S, A) *S, S, A any](get GET, set SET) Lens[*S, A]
- func MakeLensRefCurried[S, A any](get func(*S) A, set func(A) Endomorphism[*S]) Lens[*S, A]
- func MakeLensRefCurriedWithName[S, A any](get func(*S) A, set func(A) Endomorphism[*S], name string) Lens[*S, A]
- func MakeLensRefWithName[GET ~func(*S) A, SET func(*S, A) *S, S, A any](get GET, set SET, name string) Lens[*S, A]
- func MakeLensStrict[GET ~func(*S) A, SET func(*S, A) *S, S any, A comparable](get GET, set SET) Lens[*S, A]
- func MakeLensStrictWithName[GET ~func(*S) A, SET func(*S, A) *S, S any, A comparable](get GET, set SET, name string) Lens[*S, A]
- func MakeLensWithEq[GET ~func(*S) A, SET func(*S, A) *S, S, A any](pred EQ.Eq[A], get GET, set SET) Lens[*S, A]
- func MakeLensWithEqWithName[GET ~func(*S) A, SET func(*S, A) *S, S, A any](pred EQ.Eq[A], get GET, set SET, name string) Lens[*S, A]
- func MakeLensWithName[GET ~func(S) A, SET ~func(S, A) S, S, A any](get GET, set SET, name string) Lens[S, A]
- func (l Lens[S, A]) Compose[B any](ab Lens[A, B]) Lens[S, B]
- func (l Lens[S, A]) ComposeIso[B any](ab Iso[A, B]) Lens[S, B]
- func (l Lens[S, A]) ComposePrism[B any](ab Prism[A, B]) Optional[S, B]
- func (l Lens) Format(f fmt.State, c rune)
- func (l Lens) LogValue() slog.Value
- func (la Lens[S, A]) Modify(f Endomorphism[A]) Endomorphism[S]
- func (l Lens) String() string
- type LensKleisli
- type LensOperator
- func LensComposeIso[S, A, B any](ab Iso[A, B]) LensOperator[S, A, B]
- func LensComposeLens[S, A, B any](ab Lens[A, B]) LensOperator[S, A, B]
- func LensComposeLensRef[S, A, B any](ab Lens[A, B]) LensOperator[*S, A, B]deprecated
- func LensIMap[S any, AB ~func(A) B, BA ~func(B) A, A, B any](ab AB, ba BA) LensOperator[S, A, B]
- type Option
- func EitherToOption[E, A any](ma Either[E, A]) Option[A]
- func OptionFlatten[A any](mma Option[Option[A]]) Option[A]
- func OptionFromNillable[A any](a *A) Option[*A]deprecated
- func OptionFromNillable2[A any](a *A) Option[A]
- func OptionInstanceOf[T any](src any) Option[T]
- func OptionMonadAlt[A any](fa Option[A], that func() Option[A]) Option[A]
- func OptionMonadAp[B, A any](fab Option[func(A) B], fa Option[A]) Option[B]
- func OptionMonadChain[A, B any](fa Option[A], f OptionKleisli[A, B]) Option[B]
- func OptionMonadChainFirst[A, B any](ma Option[A], f OptionKleisli[A, B]) Option[A]
- func OptionMonadChainTo[A, B any](ma Option[A], mb Option[B]) Option[B]
- func OptionMonadFlap[B, A any](fab Option[func(A) B], a A) Option[B]
- func OptionMonadMap[A, B any](fa Option[A], f func(A) B) Option[B]
- func OptionMonadMapTo[A, B any](fa Option[A], b B) Option[B]
- func OptionMonadSequence2[T1, T2, R any](o1 Option[T1], o2 Option[T2], f func(T1, T2) Option[R]) Option[R]
- func OptionNone[T any]() Option[T]
- func OptionOf[T any](value T) Option[T]
- func OptionSequenceArray[A any](ma []Option[A]) Option[[]A]
- func OptionSequenceArrayG[GA ~[]A, GOA ~[]Option[A], A any](ma GOA) Option[GA]
- func OptionSome[T any](value T) Option[T]
- func OptionToAny[T any](src T) Option[any]
- func OptionTryCatch[A any](f func() (A, error)) Option[A]
- func OptionZero[A any]() Option[A]
- type OptionKleisli
- func OptionFromNonZero[A comparable]() OptionKleisli[A, A]
- func OptionFromPredicate[A any](pred Predicate[A]) OptionKleisli[A, A]
- func OptionFromValidation[A, B any](f func(A) (B, bool)) OptionKleisli[A, B]
- func OptionFromZero[A comparable]() OptionKleisli[A, A]
- func OptionOptionize1[F ~func(T0) (R, bool), T0, R any](f F) OptionKleisli[T0, R]
- func OptionTraverseArray[A, B any](f OptionKleisli[A, B]) OptionKleisli[[]A, []B]
- func OptionTraverseArrayG[GA ~[]A, GB ~[]B, A, B any](f OptionKleisli[A, B]) OptionKleisli[GA, GB]
- func OptionTraverseArrayWithIndex[A, B any](f func(int, A) Option[B]) OptionKleisli[[]A, []B]
- func OptionTraverseArrayWithIndexG[GA ~[]A, GB ~[]B, A, B any](f func(int, A) Option[B]) OptionKleisli[GA, GB]
- type OptionKleisliI
- type OptionOperator
- func OptionAlt[A any](that func() Option[A]) OptionOperator[A, A]
- func OptionAp[B, A any](fa Option[A]) OptionOperator[func(A) B, B]
- func OptionChain[A, B any](f OptionKleisli[A, B]) OptionOperator[A, B]
- func OptionChainFirst[A, B any](f OptionKleisli[A, B]) OptionOperator[A, A]
- func OptionChainOptionNone[A any](onNone func() Option[A]) OptionOperator[A, A]
- func OptionChainTo[A, B any](mb Option[B]) OptionOperator[A, B]
- func OptionFilter[A any](pred Predicate[A]) OptionOperator[A, A]
- func OptionFlap[B, A any](a A) OptionOperator[func(A) B, B]
- func OptionMap[A, B any](f func(a A) B) OptionOperator[A, B]
- func OptionMapTo[A, B any](b B) OptionOperator[A, B]
- type OptionTraversable
- type Optional
- func LensAsOptional[S, A any](sa Lens[S, A]) Optional[S, A]
- func MakeOptional[S, A any](get OptionKleisli[S, A], set func(S, A) S) Optional[S, A]
- func MakeOptionalCurried[S, A any](get OptionKleisli[S, A], set func(A) func(S) S) Optional[S, A]
- func MakeOptionalCurriedWithName[S, A any](get OptionKleisli[S, A], set func(A) func(S) S, name string) Optional[S, A]
- func MakeOptionalRef[S, A any](get OptionKleisli[*S, A], set func(*S, A) *S) Optional[*S, A]
- func MakeOptionalRefCurriedWithName[S, A any](get OptionKleisli[*S, A], set func(A) func(*S) *S, name string) Optional[*S, A]
- func MakeOptionalRefWithName[S, A any](get OptionKleisli[*S, A], set func(*S, A) *S, name string) Optional[*S, A]
- func MakeOptionalWithName[S, A any](get OptionKleisli[S, A], set func(S, A) S, name string) Optional[S, A]
- func OptionalId[S any]() Optional[S, S]
- func OptionalIdRef[S any]() Optional[*S, *S]
- func OptionalSome[S, A any](soa Optional[S, Option[A]]) Optional[S, A]
- func PrismAsOptional[S, A any](sa Prism[S, A]) Optional[S, A]
- func (p Optional[S, A]) Compose[B any](ab Optional[A, B]) Optional[S, B]
- func (l Optional[S, A]) ComposeLens[B any](ab Lens[A, B]) Optional[S, B]
- func (l Optional[S, A]) ComposePrism[B any](ab Prism[A, B]) Optional[S, B]
- func (o Optional) Format(f fmt.State, c rune)
- func (o Optional) LogValue() slog.Value
- func (o Optional) String() string
- type OptionalKleisli
- type OptionalOperator
- func OptionalComposeLens[S, A, B any](ab Lens[A, B]) OptionalOperator[S, A, B]
- func OptionalComposeOptional[S, A, B any](ab Optional[A, B]) OptionalOperator[S, A, B]
- func OptionalComposeOptionalRef[S, A, B any](ab Optional[A, B]) OptionalOperator[*S, A, B]
- func OptionalComposePrism[S, A, B any](ab Prism[A, B]) OptionalOperator[S, A, B]
- func OptionalIChain[S, A, B any](ab OptionKleisli[A, B], ba OptionKleisli[B, A]) OptionalOperator[S, A, B]
- func OptionalIChainAny[S, A any]() OptionalOperator[S, any, A]
- func OptionalIMap[S, A, B any](ab func(A) B, ba func(B) A) OptionalOperator[S, A, B]
- type Pair
- type Predicate
- func EitherExists[E, T any](p Predicate[T]) Predicate[Either[E, T]]
- func EitherExistsLeft[T, E any](p Predicate[E]) Predicate[Either[E, T]]
- func EitherForAll[E, T any](p Predicate[T]) Predicate[Either[E, T]]
- func OptionExists[T any](p Predicate[T]) Predicate[Option[T]]
- func OptionForAll[T any](p Predicate[T]) Predicate[Option[T]]
- type Prism
- func MakePrism[S, A any](get OptionKleisli[S, A], rev func(A) S) Prism[S, A]
- func MakePrismWithName[S, A any](get OptionKleisli[S, A], rev func(A) S, name string) Prism[S, A]
- func PrismFromOption[T any]() Prism[Option[T], T]
- func PrismFromPredicate[S any](pred func(S) bool) Prism[S, S]
- func PrismId[S any]() Prism[S, S]
- func PrismSome[S, A any](soa Prism[S, Option[A]]) Prism[S, A]
- type PrismKleisli
- type PrismOperator
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EitherApV ¶ added in v2.3.122
EitherApV is the curried version of EitherMonadApV that combines errors using a semigroup.
This function provides a more convenient API for validation scenarios by currying the arguments. It first takes the value to validate, then returns a function that takes the validation function. This allows for a more natural composition style.
Like EitherMonadApV, this accumulates all errors using the provided semigroup instead of short-circuiting on the first error. This is the key difference from the standard [Ap] function.
Type Parameters:
- B: The result type after applying the function
- E: The error type (must support the semigroup operation)
- A: The input type to the function
Parameters:
- sg: A semigroup that defines how to combine two error values
Returns:
- A function that takes a value Either[E, A] and returns an Operator that applies validation functions while accumulating errors
Example:
// Define a semigroup for combining validation errors
type ValidationError struct {
Errors []string
}
errorSemigroup := semigroup.MakeSemigroup(func(e1, e2 ValidationError) ValidationError {
return ValidationError{Errors: append(e1.Errors, e2.Errors...)}
})
// Create validators
validatePositive := func(x int) either.Either[ValidationError, int] {
if x > 0 {
return either.Right[ValidationError](x)
}
return either.EitherLeft[int](ValidationError{Errors: []string{"must be positive"}})
}
// Use EitherApV for validation
applyValidation := either.EitherApV[int](errorSemigroup)
value := either.EitherLeft[int](ValidationError{Errors: []string{"invalid input"}})
validator := either.EitherLeft[func(int) int](ValidationError{Errors: []string{"invalid validator"}})
result := applyValidation(value)(validator)
// Left(ValidationError{Errors: []string{"invalid validator", "invalid input"}})
func EitherBiMap ¶ added in v2.3.122
EitherBiMap is the curried version of EitherMonadBiMap. Maps a pair of functions over the two type arguments of the bifunctor.
func EitherChainOptionK ¶ added in v2.3.122
func EitherChainOptionK[A, B, E any](onNone func() E) func(func(A) Option[B]) EitherOperator[E, A, B]
EitherChainOptionK is the curried version of EitherMonadChainOptionK.
func EitherCompactArray ¶ added in v2.3.122
EitherCompactArray discards all Left values and keeps only the Right values.
Example:
eithers := A.From(
either.Right[error](1),
either.Left[int](errors.New("error")),
either.Right[error](3),
)
result := either.EitherCompactArray(eithers)
// result is []int{1, 3}
func EitherCompactArrayG ¶ added in v2.3.122
EitherCompactArrayG discards all Left values and keeps only the Right values. The G suffix indicates support for generic slice types.
Example:
eithers := A.From(
either.Right[error](1),
either.Left[int](errors.New("error")),
either.Right[error](3),
)
result := either.EitherCompactArrayG[[]either.Either[error, int], []int](eithers)
// result is []int{1, 3}
func EitherCompactRecord ¶ added in v2.3.122
func EitherCompactRecord[K comparable, E, A any](m map[K]Either[E, A]) map[K]A
EitherCompactRecord discards all Left values and keeps only the Right values.
Example:
eithers := map[string]either.Either[error, int]{
"a": either.Right[error](1),
"b": either.Left[int](errors.New("error")),
"c": either.Right[error](3),
}
result := either.EitherCompactRecord(eithers)
// result is map[string]int{"a": 1, "c": 3}
func EitherCompactRecordG ¶ added in v2.3.122
func EitherCompactRecordG[M1 ~map[K]Either[E, A], M2 ~map[K]A, K comparable, E, A any](m M1) M2
EitherCompactRecordG discards all Left values and keeps only the Right values. The G suffix indicates support for generic map types.
Example:
eithers := map[string]either.Either[error, int]{
"a": either.Right[error](1),
"b": either.Left[int](errors.New("error")),
"c": either.Right[error](3),
}
result := either.EitherCompactRecordG[map[string]either.Either[error, int], map[string]int](eithers)
// result is map[string]int{"a": 1, "c": 3}
func EitherFold ¶ added in v2.3.122
EitherFold is the curried version of EitherMonadFold. Extracts the value from an Either by providing handlers for both cases.
Example:
result := either.EitherFold(
func(err error) string { return "Error: " + err.Error() },
func(n int) string { return fmt.Sprintf("Value: %d", n) },
)(either.EitherRight[error](42)) // "Value: 42"
func EitherFromError ¶ added in v2.3.122
EitherFromError creates an Either from a function that may return an error.
Example:
validate := func(x int) error {
if x < 0 { return errors.New("negative") }
return nil
}
toEither := either.EitherFromError(validate)
result := toEither(42) // Right(42)
func EitherFromOption ¶ added in v2.3.122
EitherFromOption converts an Option to an Either, using the provided function to generate a Left value for None.
Example:
opt := option.Some(42)
result := either.EitherFromOption[int](func() error { return errors.New("none") })(opt) // Right(42)
func EitherGetOrElse ¶ added in v2.3.122
EitherGetOrElse extracts the Right value or computes a default from the Left value.
Example:
result := either.EitherGetOrElse(func(err error) int { return 0 })(either.EitherRight[error](42)) // 42
result := either.EitherGetOrElse(func(err error) int { return 0 })(either.EitherLeft[int](err)) // 0
func EitherIsLeft ¶ added in v2.3.122
EitherIsLeft tests if the Either is a Left value. Rather use EitherFold or EitherMonadFold if you need to access the values. Inverse is EitherIsRight.
Example:
either.EitherIsLeft(either.Left[int](errors.New("err"))) // true
either.EitherIsLeft(either.Right[error](42)) // false
func EitherIsRight ¶ added in v2.3.122
EitherIsRight tests if the Either is a Right value. Rather use EitherFold or EitherMonadFold if you need to access the values. Inverse is EitherIsLeft.
Example:
either.EitherIsRight(either.Right[error](42)) // true
either.EitherIsRight(either.Left[int](errors.New("err"))) // false
func EitherMapLeft ¶ added in v2.3.122
EitherMapLeft is the curried version of EitherMonadMapLeft. Applies a mapping function to the Left (error) channel.
func EitherMonadApV ¶ added in v2.3.122
func EitherMonadApV[B, A, E any](sg S.Semigroup[E]) func(fab Either[E, func(a A) B], fa Either[E, A]) Either[E, B]
EitherMonadApV is the applicative validation functor that combines errors using a semigroup.
Unlike the standard [MonadAp] which short-circuits on the first Left (error), EitherMonadApV accumulates all errors using the provided semigroup's Concat operation. This is particularly useful for validation scenarios where you want to collect all validation errors rather than stopping at the first one.
The function takes a semigroup for combining errors and returns a function that applies a wrapped function to a wrapped value, accumulating errors if both are Left.
Behavior:
- If both fab and fa are Left, combines their errors using sg.Concat
- If only fab is Left, returns Left with fab's error
- If only fa is Left, returns Left with fa's error
- If both are Right, applies the function and returns Right with the result
Type Parameters:
- B: The result type after applying the function
- E: The error type (must support the semigroup operation)
- A: The input type to the function
Parameters:
- sg: A semigroup that defines how to combine two error values
Returns:
- A function that takes a wrapped function and a wrapped value, returning Either[E, B] with accumulated errors or the computed result
Example:
// Define a semigroup that concatenates error messages
errorSemigroup := semigroup.MakeSemigroup(func(e1, e2 string) string {
return e1 + "; " + e2
})
// Create the validation applicative
applyV := either.EitherMonadApV[int](errorSemigroup)
// Both are errors - errors get combined
fab := either.EitherLeft[func(int) int]("error1")
fa := either.EitherLeft[int]("error2")
result := applyV(fab, fa) // Left("error1; error2")
// One error - returns that error
fab2 := either.Right[string](N.Mul(2))
fa2 := either.EitherLeft[int]("validation failed")
result2 := applyV(fab2, fa2) // Left("validation failed")
// Both success - applies function
fab3 := either.Right[string](N.Mul(2))
fa3 := either.Right[string](21)
result3 := applyV(fab3, fa3) // Right(42)
func EitherMonadFold ¶ added in v2.3.122
EitherMonadFold extracts the value from an Either by providing handlers for both cases. This is the fundamental pattern matching operation for Either.
Example:
result := either.EitherMonadFold(
either.Right[error](42),
func(err error) string { return "Error: " + err.Error() },
func(n int) string { return fmt.Sprintf("Value: %d", n) },
) // "Value: 42"
func EitherPartition ¶ added in v2.3.122
func EitherPartition[E, A any](p Predicate[A], empty E) func(Either[E, A]) Pair[Either[E, A], Either[E, A]]
EitherPartition separates an Either value into a Pair based on a predicate function. It returns a function that takes an Either and produces a Pair of Either values, where the first element contains values that fail the predicate and the second contains values that pass the predicate.
This function implements the Filterable specification's partition operation: https://github.com/fantasyland/fantasy-land#filterable
The behavior is as follows:
- If the input is Left, both elements of the resulting Pair will be the same Left value
- If the input is Right and the predicate returns true, the result is (Left(empty), Right(value))
- If the input is Right and the predicate returns false, the result is (Right(value), Left(empty))
This function is useful for separating Either values into two categories based on a condition, commonly used in filtering operations where you want to keep track of both the values that pass and fail a test.
Parameters:
- p: A predicate function that tests values of type A
- empty: The default Left value to use when creating Left instances for partitioning
Returns:
A function that takes an Either[E, A] and returns a Pair where: - First element: Either values that fail the predicate (or original Left) - Second element: Either values that pass the predicate (or original Left)
Example:
import (
E "github.com/IBM/fp-go/v2/either"
N "github.com/IBM/fp-go/v2/number"
P "github.com/IBM/fp-go/v2/pair"
)
// EitherPartition positive and non-positive numbers
isPositive := N.MoreThan(0)
partition := E.EitherPartition(isPositive, "not positive")
// Right value that passes predicate
result1 := partition(E.Right[string](5))
// result1 = Pair(Left("not positive"), Right(5))
left1, right1 := P.Unpack(result1)
// left1 = Left("not positive"), right1 = Right(5)
// Right value that fails predicate
result2 := partition(E.Right[string](-3))
// result2 = Pair(Right(-3), Left("not positive"))
left2, right2 := P.Unpack(result2)
// left2 = Right(-3), right2 = Left("not positive")
// Left value passes through unchanged in both positions
result3 := partition(E.EitherLeft[int]("error"))
// result3 = Pair(Left("error"), Left("error"))
left3, right3 := P.Unpack(result3)
// left3 = Left("error"), right3 = Left("error")
func EitherPartitionMap ¶ added in v2.3.122
func EitherPartitionMap[E, A, B, C any](f EitherKleisli[B, A, C], empty E) func(Either[E, A]) Pair[Either[E, B], Either[E, C]]
EitherPartitionMap separates and transforms an Either value into a Pair of Either values using a mapping function. It returns a function that takes an Either[E, A] and produces a Pair of Either values, where the mapping function f transforms the Right value into Either[B, C]. The result is partitioned based on whether f produces a Left or Right value.
This function implements the Filterable specification's partitionMap operation: https://github.com/fantasyland/fantasy-land#filterable
The behavior is as follows:
- If the input is Left, both elements of the resulting Pair will be Left with the original error
- If the input is Right and f returns Left(B), the result is (Right(B), Left(empty))
- If the input is Right and f returns Right(C), the result is (Left(empty), Right(C))
This function is useful for operations that need to categorize and transform values simultaneously, such as separating valid and invalid data while applying different transformations to each category.
Parameters:
- f: A Kleisli function that transforms values of type A to Either[B, C]
- empty: The default error value to use when creating Left instances for partitioning
Returns:
A function that takes an Either[E, A] and returns a Pair[Either[E, B], Either[E, C]] where: - If input is Left: (Left(original_error), Left(original_error)) - If f returns Left(B): (Right(B), Left(empty)) - If f returns Right(C): (Left(empty), Right(C))
Example:
import (
E "github.com/IBM/fp-go/v2/either"
P "github.com/IBM/fp-go/v2/pair"
)
// Classify and transform numbers: negative -> error message, positive -> squared value
classifyNumber := func(n int) Either[string, int] {
if n < 0 {
return E.EitherLeft[int]("negative: " + strconv.Itoa(n))
}
return E.Right[string](n * n)
}
partitionMap := E.EitherPartitionMap(classifyNumber, "not classified")
// Positive number - goes to right side as squared value
result1 := partitionMap(E.Right[string](5))
// result1 = Pair(Left("not classified"), Right(25))
left1, right1 := P.Unpack(result1)
// left1 = Left("not classified"), right1 = Right(25)
// Negative number - goes to left side with error message
result2 := partitionMap(E.Right[string](-3))
// result2 = Pair(Right("negative: -3"), Left("not classified"))
left2, right2 := P.Unpack(result2)
// left2 = Right("negative: -3"), right2 = Left("not classified")
// Original Left value - appears in both positions
result3 := partitionMap(E.EitherLeft[int]("original error"))
// result3 = Pair(Left("original error"), Left("original error"))
left3, right3 := P.Unpack(result3)
// left3 = Left("original error"), right3 = Left("original error")
// Validate and transform user input
type ValidationError struct{ Field, Message string }
type User struct{ Name string; Age int }
validateUser := func(input map[string]string) Either[ValidationError, User] {
name, hasName := input["name"]
ageStr, hasAge := input["age"]
if !hasName {
return E.EitherLeft[User](ValidationError{"name", "missing"})
}
if !hasAge {
return E.EitherLeft[User](ValidationError{"age", "missing"})
}
age, err := strconv.Atoi(ageStr)
if err != nil {
return E.EitherLeft[User](ValidationError{"age", "invalid"})
}
return E.Right[ValidationError](User{name, age})
}
partitionUsers := E.EitherPartitionMap(validateUser, ValidationError{"", "not processed"})
validInput := map[string]string{"name": "Alice", "age": "30"}
result4 := partitionUsers(E.Right[string](validInput))
// result4 = Pair(Left(ValidationError{"", "not processed"}), Right(User{"Alice", 30}))
invalidInput := map[string]string{"name": "Bob"}
result5 := partitionUsers(E.Right[string](invalidInput))
// result5 = Pair(Right(ValidationError{"age", "missing"}), Left(ValidationError{"", "not processed"}))
func EitherReduce ¶ added in v2.3.122
EitherReduce folds an Either into a single value using a reducer function. Returns the initial value for Left, or applies the reducer to the Right value.
func EitherSequence2 ¶ added in v2.3.122
func EitherSequence2[E, T1, T2, R any](f func(T1, T2) Either[E, R]) func(Either[E, T1], Either[E, T2]) Either[E, R]
EitherSequence2 sequences two Either values using a combining function. Short-circuits on the first Left encountered.
func EitherSequence3 ¶ added in v2.3.122
func EitherSequence3[E, T1, T2, T3, R any](f func(T1, T2, T3) Either[E, R]) func(Either[E, T1], Either[E, T2], Either[E, T3]) Either[E, R]
EitherSequence3 sequences three Either values using a combining function. Short-circuits on the first Left encountered.
func EitherToError ¶ added in v2.3.122
EitherToError converts an Either[error, A] to an error, returning nil for Right values.
Example:
err := either.EitherToError(either.EitherLeft[int](errors.New("fail"))) // error
err := either.EitherToError(either.EitherRight[error](42)) // nil
func EitherToType ¶ added in v2.3.122
EitherToType attempts to convert an any value to a specific type, returning Either.
Example:
convert := either.EitherToType[int](func(v any) error {
return fmt.Errorf("cannot convert %v to int", v)
})
result := convert(42) // Right(42)
result := convert("string") // Left(error)
func EitherUnwrap ¶ added in v2.3.122
EitherUnwrap converts an Either into the idiomatic Go tuple (value, error). For Right values, returns (value, zero-error). For Left values, returns (zero-value, error).
Example:
val, err := either.EitherUnwrap(either.Right[error](42)) // 42, nil
val, err := either.EitherUnwrap(either.Left[int](errors.New("fail"))) // 0, error
func EitherUnwrapError ¶ added in v2.3.122
EitherUnwrapError converts an Either[error, A] into the idiomatic Go tuple (A, error).
Example:
val, err := either.EitherUnwrapError(either.EitherRight[error](42)) // 42, nil
val, err := either.EitherUnwrapError(either.EitherLeft[int](errors.New("fail"))) // zero, error
func IsoComposeIso ¶
IsoComposeIso combines two isomorphisms to create a new isomorphism. Given Iso[S, A] and Iso[A, B], creates Iso[S, B]. The resulting isomorphism first applies the outer iso (S → A), then the inner iso (A → B).
Type Parameters:
- S: The outermost source type
- A: The intermediate type
- B: The innermost target type
Parameters:
- ab: The inner isomorphism (A → B)
Returns:
- A function that takes the outer isomorphism (S → A) and returns the composed isomorphism (S → B)
Example:
metersToKm := MakeIso(
func(m float64) float64 { return m / 1000 },
func(km float64) float64 { return km * 1000 },
)
kmToMiles := MakeIso(
func(km float64) float64 { return km * 0.621371 },
func(mi float64) float64 { return mi / 0.621371 },
)
// IsoComposeIso: meters → kilometers → miles
metersToMiles := F.Pipe1(metersToKm, IsoComposeIso[float64](kmToMiles))
miles := metersToMiles.Get(5000) // ~3.11 miles
meters := metersToMiles.ReverseGet(3.11) // ~5000 meters
func IsoComposeLens ¶
IsoComposeLens combines an isomorphism with a lens to produce a new lens.
Given an isomorphism Iso[S, A] and a lens Lens[A, B], IsoComposeLens creates a Lens[S, B]. Internally the isomorphism is first converted to a Lens[S, A] via IsoAsLens, then composed with the provided lens using LensComposeLens.
This is useful when the outer view of a structure is captured by a total, invertible transformation (an iso) and you want to drill further into the result with a lens — for example, when S is a newtype wrapper around A and you need to focus on a field of A.
The resulting lens satisfies all three lens laws whenever both the isomorphism and the inner lens individually satisfy them.
The composition follows: (sa ∘ ab).Get(s) = ab.Get(sa.Get(s))
Type Parameters:
- S: Outermost source type — the input to the resulting lens
- A: Intermediate type — the target of the iso and the source of the inner lens
- B: Inner focus type — the focus of the resulting lens
Parameters:
- ab: Lens from A to B (inner lens)
Returns:
- A function that takes an Iso[S, A] and returns a Lens[S, B]
Example:
type Celsius float64
type Thermometer struct{ Reading Celsius }
// Isomorphism: float64 ↔ Celsius
floatToCelsius := MakeIso(
func(f float64) Celsius { return Celsius(f) },
func(c Celsius) float64 { return float64(c) },
)
// Lens: Thermometer → Celsius (focuses on the Reading field)
readingLens := MakeLens(
func(t Thermometer) Celsius { return t.Reading },
func(t Thermometer, c Celsius) Thermometer { t.Reading = c; return t },
)
// Compose: float64 → Celsius → Thermometer.Reading (Celsius)
// Result type: Lens[float64, Celsius]
tempLens := F.Pipe1(floatToCelsius, IsoComposeLens[float64](readingLens))
t := Thermometer{Reading: 100}
reading := tempLens.Get(100.0) // Celsius(100)
updated := tempLens.Set(Celsius(0))(0.0) // Thermometer{Reading: 0}
See Also:
- IsoComposeIso: the variant that composes with an Iso[A, B] instead of a Lens[A, B]
- LensComposeLens: the pure-lens equivalent
- IsoAsLens: converts an Iso to a Lens directly
func IsoFrom ¶
IsoFrom wraps a target value into a source value using an isomorphism. This is an alias for Wrap, provided for semantic clarity when the direction of conversion is important.
Type Parameters:
- S: The source type to convert from
- A: The target type
Parameters:
- a: The target value to convert
Returns:
- A function that takes an Iso[S, A] and returns the converted value of type S
Example:
type Email string
type ValidatedEmail struct{ value Email }
emailIso := MakeIso(
func(ve ValidatedEmail) Email { return ve.value },
func(e Email) ValidatedEmail { return ValidatedEmail{value: e} },
)
// Convert from Email
validated := IsoFrom[ValidatedEmail](Email("admin@example.com"))(emailIso)
// ValidatedEmail{value: "admin@example.com"}
func IsoIMap ¶
IsoIMap bidirectionally maps the target type of an isomorphism. Given Iso[S, A] and functions A → B and B → A, creates Iso[S, B]. This allows you to transform both directions of an isomorphism.
Type Parameters:
- S: The source type (unchanged)
- A: The original target type
- B: The new target type
Parameters:
- ab: Function to map from A to B
- ba: Function to map from B to A (inverse of ab)
Returns:
- A function that transforms Iso[S, A] to Iso[S, B]
Example:
type Celsius float64
type Kelvin float64
celsiusIso := Id[Celsius]()
// Create isomorphism to Kelvin
celsiusToKelvin := F.Pipe1(
celsiusIso,
IsoIMap(
func(c Celsius) Kelvin { return Kelvin(c + 273.15) },
func(k Kelvin) Celsius { return Celsius(k - 273.15) },
),
)
kelvin := celsiusToKelvin.Get(Celsius(20)) // 293.15 K
celsius := celsiusToKelvin.ReverseGet(Kelvin(293.15)) // 20°C
Note: The functions ab and ba must be inverses of each other to maintain the isomorphism laws.
func IsoModify ¶
func IsoModify[S any, FCT ~func(A) A, A any](f FCT) func(Iso[S, A]) Endomorphism[S]
IsoModify creates a function that applies a transformation in the target space. It converts the source value to the target type, applies the transformation, then converts back to the source type.
Type Parameters:
- S: The source type
- FCT: The transformation function type (A → A)
- A: The target type
Parameters:
- f: The transformation function to apply in the target space
Returns:
- A function that takes an Iso[S, A] and returns an endomorphism (S → S)
Example:
type Meters float64
type Kilometers float64
mToKm := MakeIso(
func(m Meters) Kilometers { return Kilometers(m / 1000) },
func(km Kilometers) Meters { return Meters(km * 1000) },
)
// Double the distance in kilometers, result in meters
doubled := IsoModify[Meters](func(km Kilometers) Kilometers {
return km * 2
})(mToKm)(Meters(5000))
// Result: Meters(10000)
func IsoTo ¶
IsoTo extracts the target value from a source value using an isomorphism. This is an alias for Unwrap, provided for semantic clarity when the direction of conversion is important.
Type Parameters:
- A: The target type to convert to
- S: The source type
Parameters:
- s: The source value to convert
Returns:
- A function that takes an Iso[S, A] and returns the converted value of type A
Example:
type Email string
type ValidatedEmail struct{ value Email }
emailIso := MakeIso(
func(ve ValidatedEmail) Email { return ve.value },
func(e Email) ValidatedEmail { return ValidatedEmail{value: e} },
)
// Convert to Email
email := IsoTo[Email](ValidatedEmail{value: "user@example.com"})(emailIso)
// "user@example.com"
func IsoUnwrap ¶
IsoUnwrap extracts the target value from a source value using an isomorphism. This is a convenience function that applies the Get function of the isomorphism.
Type Parameters:
- A: The target type to extract
- S: The source type
Parameters:
- s: The source value to unwrap
Returns:
- A function that takes an Iso[S, A] and returns the unwrapped value of type A
Example:
type UserId int
userIdIso := MakeIso(
func(id UserId) int { return int(id) },
func(i int) UserId { return UserId(i) },
)
rawId := IsoUnwrap[int](UserId(42))(userIdIso) // 42
Note: This function is also available as To for semantic clarity.
func IsoWrap ¶
IsoWrap wraps a target value into a source value using an isomorphism. This is a convenience function that applies the ReverseGet function of the isomorphism.
Type Parameters:
- S: The source type to wrap into
- A: The target type
Parameters:
- a: The target value to wrap
Returns:
- A function that takes an Iso[S, A] and returns the wrapped value of type S
Example:
type UserId int
userIdIso := MakeIso(
func(id UserId) int { return int(id) },
func(i int) UserId { return UserId(i) },
)
userId := IsoWrap[UserId](42)(userIdIso) // UserId(42)
Note: This function is also available as From for semantic clarity.
func LensComposePrism ¶ added in v2.3.122
LensComposePrism composes a Lens with a Prism to create an Optional.
This composition allows you to focus on a part of a structure (using a Lens) and then optionally extract a variant from that part (using a Prism). The result is an Optional because the Prism may not match the focused value.
The composition follows the Optional laws (a relaxed form of lens laws):
SetGet Law (GetSet for Optional):
- If optional.GetOption(s) = Some(b), then optional.GetOption(optional.Set(b)(s)) = Some(b)
- This ensures that setting a value and then getting it returns the same value
GetSet Law (for Optional):
- If optional.GetOption(s) = None, then optional.Set(b)(s) = s (no-op)
- This ensures that setting a value when the optional doesn't match leaves the structure unchanged
These laws are documented in the official fp-ts documentation: https://gcanti.github.io/monocle-ts/modules/Optional.ts.html
Type Parameters:
- S: The source/outer structure type
- A: The intermediate type (focused by the Lens)
- B: The target type (focused by the Prism within A)
Parameters:
- p: A Prism[A, B] that optionally extracts B from A
Returns:
- A function that takes a Lens[S, A] and returns an Optional[S, B]
Behavior:
- GetOption: First uses the Lens to get A from S, then uses the Prism to try to extract B from A. Returns Some(b) if both operations succeed, None otherwise.
- Set: When setting a value b:
- If GetOption(s) returns Some(_), it means the Prism matches, so we: 1. Use Prism.ReverseGet to construct an A from b 2. Use Lens.Set to update S with the new A
- If GetOption(s) returns None, the Prism doesn't match, so we return s unchanged (no-op)
Example:
type Config struct {
Database DatabaseConfig
}
type DatabaseConfig struct {
Connection ConnectionType
}
type ConnectionType interface{ isConnection() }
type PostgreSQL struct{ Host string }
type MySQL struct{ Host string }
// Lens to focus on Database field
dbLens := lens.MakeLens(
func(c Config) DatabaseConfig { return c.Database },
func(c Config, db DatabaseConfig) Config { c.Database = db; return c },
)
// Prism to extract PostgreSQL from ConnectionType
pgPrism := prism.MakePrism(
func(ct ConnectionType) OptionOption[PostgreSQL] {
if pg, ok := ct.(PostgreSQL); ok {
return OptionSome(pg)
}
return OptionNone[PostgreSQL]()
},
func(pg PostgreSQL) ConnectionType { return pg },
)
// LensComposePrism to create Optional[Config, PostgreSQL]
configPgOptional := LensComposePrism[Config, DatabaseConfig, PostgreSQL](pgPrism)(dbLens)
config := Config{Database: DatabaseConfig{Connection: PostgreSQL{Host: "localhost"}}}
host := configPgOptional.GetOption(config) // Some(PostgreSQL{Host: "localhost"})
updated := configPgOptional.Set(PostgreSQL{Host: "remote"})(config)
// updated.Database.Connection = PostgreSQL{Host: "remote"}
configMySQL := Config{Database: DatabaseConfig{Connection: MySQL{Host: "localhost"}}}
none := configPgOptional.GetOption(configMySQL) // None (Prism doesn't match)
unchanged := configPgOptional.Set(PostgreSQL{Host: "remote"})(configMySQL)
// unchanged == configMySQL (no-op because Prism doesn't match)
func LensComposePrismRef ¶ added in v2.3.122
LensComposePrismRef composes a Lens operating on pointer types with a Prism to create an Optional.
This is the pointer-safe variant of Compose, designed for working with pointer types (*S). It automatically handles nil pointer cases and creates copies before modification to ensure immutability and prevent unintended side effects.
The composition follows the same Optional laws as Compose:
SetGet Law (GetSet for Optional):
- If optional.GetOption(s) = Some(b), then optional.GetOption(optional.Set(b)(s)) = Some(b)
- This ensures that setting a value and then getting it returns the same value
GetSet Law (for Optional):
- If optional.GetOption(s) = None, then optional.Set(b)(s) = s (no-op)
- This ensures that setting a value when the optional doesn't match leaves the structure unchanged
Nil Pointer Handling:
- When s is nil and GetOption would return None, Set operations return nil (no-op)
- When s is nil and GetOption would return Some (after creating default), Set creates a new instance
- All Set operations create a shallow copy of *S before modification to preserve immutability
These laws are documented in the official fp-ts documentation: https://gcanti.github.io/monocle-ts/modules/Optional.ts.html
Type Parameters:
- S: The source/outer structure type (used as *S in the lens)
- A: The intermediate type (focused by the Lens)
- B: The target type (focused by the Prism within A)
Parameters:
- p: A Prism[A, B] that optionally extracts B from A
Returns:
- A function that takes a Lens[*S, A] and returns an Optional[*S, B]
Behavior:
- GetOption: First uses the Lens to get A from *S, then uses the Prism to try to extract B from A. Returns Some(b) if both operations succeed, None otherwise.
- Set: When setting a value b:
- Creates a shallow copy of *S before any modification (nil-safe)
- If GetOption(s) returns Some(_), it means the Prism matches, so we: 1. Use Prism.ReverseGet to construct an A from b 2. Use Lens.Set to update the copy of *S with the new A
- If GetOption(s) returns None, the Prism doesn't match, so we return s unchanged (no-op)
Example:
type Config struct {
Connection ConnectionType
AppName string
}
type ConnectionType interface{ isConnection() }
type PostgreSQL struct{ Host string }
type MySQL struct{ Host string }
// Lens to focus on Connection field (pointer-based)
connLens := lens.MakeLensRef(
func(c *Config) ConnectionType { return c.Connection },
func(c *Config, ct ConnectionType) *Config { c.Connection = ct; return c },
)
// Prism to extract PostgreSQL from ConnectionType
pgPrism := prism.MakePrism(
func(ct ConnectionType) OptionOption[PostgreSQL] {
if pg, ok := ct.(PostgreSQL); ok {
return OptionSome(pg)
}
return OptionNone[PostgreSQL]()
},
func(pg PostgreSQL) ConnectionType { return pg },
)
// Compose to create Optional[*Config, PostgreSQL]
configPgOptional := LensComposePrismRef[Config, ConnectionType, PostgreSQL](pgPrism)(connLens)
// Works with non-nil pointers
config := &Config{Connection: PostgreSQL{Host: "localhost"}}
host := configPgOptional.GetOption(config) // Some(PostgreSQL{Host: "localhost"})
updated := configPgOptional.Set(PostgreSQL{Host: "remote"})(config)
// updated is a new *Config with Connection = PostgreSQL{Host: "remote"}
// original config is unchanged (immutability preserved)
// Handles nil pointers safely
var nilConfig *Config = nil
none := configPgOptional.GetOption(nilConfig) // None (nil pointer)
unchanged := configPgOptional.Set(PostgreSQL{Host: "remote"})(nilConfig)
// unchanged == nil (no-op because source is nil)
// Works with mismatched prisms
configMySQL := &Config{Connection: MySQL{Host: "localhost"}}
none = configPgOptional.GetOption(configMySQL) // None (Prism doesn't match)
unchanged = configPgOptional.Set(PostgreSQL{Host: "remote"})(configMySQL)
// unchanged == configMySQL (no-op because Prism doesn't match)
func LensModify ¶
func LensModify[S any, FCT ~func(A) A, A any](f FCT) func(Lens[S, A]) Endomorphism[S]
LensModify transforms a value through a lens using a transformation F.
Instead of setting a specific value, LensModify applies a function to the current value. This is useful for updates like incrementing a counter, appending to a string, etc. If the transformation doesn't change the value, the original structure is returned.
Type Parameters:
- S: Structure type
- FCT: Transformation function type (A → A)
- A: Focus type
Parameters:
- f: Transformation function to apply to the focused value
Returns:
- A function that takes a Lens[S, A] and returns an Endomorphism[S]
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 },
)
counter := Counter{Value: 5}
// Increment the counter
incremented := F.Pipe2(
valueLens,
lens.LensModify[Counter](func(v int) int { return v + 1 }),
F.Ap(counter),
)
// incremented.Value == 6
// Double the counter
doubled := F.Pipe2(
valueLens,
lens.LensModify[Counter](func(v int) int { return v * 2 }),
F.Ap(counter),
)
// doubled.Value == 10
func LensModifyF ¶
func LensModifyF[S, A, HKTA, HKTS any]( fmap functor.MapType[A, S, HKTA, HKTS], ) func(func(A) HKTA) func(Lens[S, A]) func(S) HKTS
LensModifyF transforms a value through a lens using a function that returns a value in a functor context.
This is the functorial version of Modify, allowing transformations that produce effects (like Option, Either, IO, etc.) while updating the focused value. The functor's map operation is used to apply the lens's setter to the transformed value, preserving the computational context.
This function corresponds to modifyF from monocle-ts, enabling effectful updates through lenses.
Type Parameters ¶
- S: Structure type
- A: Focus type (the value being transformed)
- HKTA: Higher-kinded type containing the transformed value (e.g., Option[A], Either[E, A])
- HKTS: Higher-kinded type containing the updated structure (e.g., Option[S], Either[E, S])
Parameters ¶
- fmap: A functor map operation that transforms A to S within the functor context
Returns ¶
- A curried function that takes: 1. A transformation function (A → HKTA) 2. A Lens[S, A] 3. A structure S And returns the updated structure in the functor context (HKTS)
Example Usage ¶
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 },
)
// Validate age is positive, returning Option
validateAge := func(age int) option.Option[int] {
if age > 0 {
return option.Some(age)
}
return option.None[int]()
}
// Create a modifier that validates while updating
modifyAge := lens.LensModifyF[Person, int](option.Functor[int, Person]().Map)
person := Person{Name: "Alice", Age: 30}
result := modifyAge(validateAge)(ageLens)(person)
// result is Some(Person{Name: "Alice", Age: 30})
invalidResult := modifyAge(func(age int) option.Option[int] {
return option.None[int]()
})(ageLens)(person)
// invalidResult is None[Person]()
See Also ¶
- Modify: Non-functorial version for simple transformations
- functor.Functor: The functor interface used for mapping
func LensSet ¶
func LensSet[S any, A any](a A) func(Lens[S, A]) Endomorphism[S]
LensSet returns a function that updates the focus of a lens to a constant value.
This is a convenience helper for partially applying a value before supplying the lens, making it useful in composition pipelines with F.Pipe.
Example:
type Counter struct {
Value int
}
valueLens := lens.MakeLens(
func(c Counter) int { return c.Value },
func(c Counter, value int) Counter {
c.Value = value
return c
},
)
counter := Counter{Value: 5}
updated := F.Pipe2(
10,
lens.LensSet[Counter](10),
F.Ap(valueLens),
)
// updated.Value == 10
func OptionCompactArray ¶ added in v2.3.120
OptionCompactArray filters an array of Options, keeping only the Some values and discarding None values.
Example:
input := A.From(OptionSome(1), OptionNone[int](), OptionSome(3), OptionSome(5), OptionNone[int]()) result := OptionCompactArray(input) // [1, 3, 5]
func OptionCompactArrayG ¶ added in v2.3.120
OptionCompactArrayG filters an array of Options, keeping only the Some values and discarding None values. This is the generic version that works with custom slice types.
Example:
type MySlice []int
input := A.From(OptionSome(1), OptionNone[int](), OptionSome(3))
result := OptionCompactArrayG[[]Option[int], MySlice](input) // MySlice{1, 3}
func OptionFold ¶ added in v2.3.120
OptionFold 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 is Some.
Example:
handler := OptionFold(
func() string { return "no value" },
func(x int) string { return fmt.Sprintf("value: %d", x) },
)
result := handler(OptionSome(42)) // "value: 42"
result := handler(OptionNone[int]()) // "no value"
Relation to predicate.OptionFold:
option.OptionFold and predicate.OptionFold are two specialisations of the same categorical pattern — eliminating a two-case sum type into a common result type B.
option.Option[A] is a two-case sum type {None, OptionSome(A)}. The Some constructor carries a payload of type A, so the onSome branch receives it; the None branch carries no payload and is therefore a thunk:
option.OptionFold :: (() → B) → (A → B) → Option[A] → B
predicate.Predicate[A] is morally equivalent to A → bool, where bool is the smallest two-case sum type {false, true}. Because bool carries no payload beyond the branch tag, both handlers in predicate.OptionFold must receive A to preserve context:
predicate.OptionFold :: (A → B) → (A → B) → (A → bool) → A → B
The link between the two is FromPredicate, which converts a Predicate[A] into an Option[A]-producing function. Using it, predicate.OptionFold can always be expressed in terms of option.OptionFold:
predicate.OptionFold(onFalse, onTrue)(p)(a)
== option.OptionFold(func() B { return onFalse(a) }, onTrue)(FromPredicate(p)(a))
Conversely, option.OptionFold cannot in general be expressed via predicate.OptionFold because None carries no A value for the false branch to inspect.
See Also:
- MonadFold: The uncurried form of this function
- predicate.OptionFold: The analogous eliminator for the bool two-case sum type
- FromPredicate: Converts a Predicate[A] into a OptionKleisli[A, A] producing Option[A]
func OptionFromEq ¶ added in v2.3.120
func OptionFromEq[A any](pred eq.Eq[A]) func(A) OptionKleisli[A, A]
func OptionFromStrictEq ¶ added in v2.3.120
func OptionFromStrictEq[A comparable]() func(A) OptionKleisli[A, A]
func OptionGetOrElse ¶ added in v2.3.120
OptionGetOrElse returns a function that extracts the value from an Option or returns a default.
Example:
getOrZero := OptionGetOrElse(lazy.Of(0)) result := getOrZero(OptionSome(42)) // 42 result := getOrZero(OptionNone[int]()) // 0
func OptionIsNone ¶ added in v2.3.120
OptionIsNone checks if an Option is None (contains no value).
Example:
opt := OptionNone[int]() OptionIsNone(opt) // true opt := OptionSome(42) OptionIsNone(opt) // false
func OptionIsSome ¶ added in v2.3.120
OptionIsSome checks if an Option contains a value.
Example:
opt := OptionSome(42) OptionIsSome(opt) // true opt := OptionNone[int]() OptionIsSome(opt) // false
func OptionMonadFold ¶ added in v2.3.120
OptionMonadFold performs a fold operation on an Option. If the Option is Some, applies onSome to the value. If the Option is None, calls onNone.
Example:
opt := OptionSome(42)
result := OptionMonadFold(opt,
func() string { return "no value" },
func(x int) string { return fmt.Sprintf("value: %d", x) },
) // "value: 42"
func OptionMonadGetOrElse ¶ added in v2.3.120
OptionMonadGetOrElse extracts the value from an Option or returns a default value. This is the monadic form of GetOrElse.
Example:
result := OptionMonadGetOrElse(OptionSome(42), lazy.Of(0)) // 42 result := OptionMonadGetOrElse(OptionNone[int](), lazy.Of(0)) // 0
func OptionReduce ¶ added in v2.3.120
OptionReduce folds an Option into a single value using a reducer function. If the Option is None, returns the initial value.
Example:
sum := OptionReduce(func(acc, val int) int { return acc + val }, 0)
result := sum(OptionSome(5)) // 5
result := sum(OptionNone[int]()) // 0
func OptionSequence2 ¶ added in v2.3.120
func OptionSequence2[T1, T2, R any](f func(T1, T2) Option[R]) func(Option[T1], Option[T2]) Option[R]
OptionSequence2 returns a function that sequences two Options with a combining function.
Example:
add := OptionSequence2(func(a, b int) Option[int] { return OptionSome(a + b) })
result := add(OptionSome(2), OptionSome(3)) // OptionSome(5)
func OptionToNillable2 ¶ added in v2.3.120
OptionToNillable2 converts an Option[A] back to a nullable pointer. Returns a pointer to the contained value when the Option is Some, nil otherwise. This is the inverse of FromNillable2: round-tripping through both functions preserves the value but allocates a new pointer on each call.
Type Parameters:
- A: the type contained in the Option
Parameters:
- fa: the Option value to convert
Returns:
- a pointer to a copy of the contained value when fa is Some
- nil when fa is None
See Also:
- FromNillable2: the inverse — converts *A to Option[A]
func OptionUnwrap ¶ added in v2.3.120
OptionUnwrap extracts the value and presence flag from an Option. Returns the value and true if Some, or zero value and false if None.
Example:
opt := OptionSome(42) val, ok := OptionUnwrap(opt) // val = 42, ok = true opt := OptionNone[int]() val, ok := OptionUnwrap(opt) // val = 0, ok = false
func OptionalAsTraversal ¶
func OptionalFromPredicate ¶
func OptionalFromPredicate[S, A any](pred func(A) bool) func(func(S) A, func(S, A) S) Optional[S, A]
OptionalFromPredicate creates an optional from getter and setter functions. It checks for optional values and the correct update procedure
func OptionalFromPredicateRef ¶
func OptionalFromPredicateRef[S, A any](pred func(A) bool) func(func(*S) A, func(*S, A) *S) Optional[*S, A]
FromPredicate creates an optional from getter and setter functions. It checks for optional values and the correct update procedure
func OptionalModifyOption ¶
func OptionalModifyOption[S, A any](f func(A) A) func(Optional[S, A]) OptionKleisli[S, S]
func OptionalSetOption ¶
func OptionalSetOption[S, A any](a A) func(Optional[S, A]) OptionKleisli[S, S]
func PrismAsTraversal ¶
func PrismAsTraversal[R ~func(func(A) HKTA) func(S) HKTS, S, A, HKTS, HKTA any]( fof pointed.OfType[S, HKTS], fmap functor.MapType[A, S, HKTA, HKTS], ) func(Prism[S, A]) R
PrismAsTraversal converts a Prism into a Traversal.
A Traversal is a more general optic that can focus on zero or more values, while a Prism focuses on zero or one value. This function lifts a Prism into the Traversal abstraction, allowing it to be used in contexts that expect traversals.
The conversion works by:
- If the prism matches (GetOption returns Some), the traversal focuses on that value
- If the prism doesn't match (GetOption returns None), the traversal focuses on zero values
Type Parameters:
- R: The traversal function type ~func(func(A) HKTA) func(S) HKTS
- S: The source type
- A: The focus type
- HKTS: Higher-kinded type for S (e.g., functor/applicative context)
- HKTA: Higher-kinded type for A (e.g., functor/applicative context)
Parameters:
- fof: Function to lift S into the higher-kinded type HKTS (pure/of operation)
- fmap: Function to map over HKTA and produce HKTS (functor map operation)
Returns:
- A function that converts a Prism[S, A] into a Traversal R
Example:
// Convert a prism to a traversal for use with applicative functors
prism := MakePrism(...)
traversal := AsTraversal(
func(s S) HKTS { return pure(s) },
func(hkta HKTA, f func(A) S) HKTS { return fmap(hkta, f) },
)(prism)
Note: This function is typically used in advanced scenarios involving higher-kinded types and applicative functors. Most users will work directly with prisms rather than converting them to traversals.
func PrismSet ¶
func PrismSet[S, A any](a A) func(Prism[S, A]) Endomorphism[S]
PrismSet creates a function that sets a value through a prism. If the prism matches, it replaces the focused value with the new value. If the prism doesn't match, it returns the original value unchanged.
Parameters:
- a: The new value to set
Returns:
- A function that takes a prism and returns an endomorphism (S → S)
Example:
somePrism := MakePrism(...) setter := PrismSet[Option[int], int](100) result := setter(somePrism)(Some(42)) // Some(100) result = setter(somePrism)(None[int]()) // None[int]() (unchanged)
Types ¶
type Either ¶ added in v2.3.122
type Either[E, A any] struct { // contains filtered or unexported fields }
Either defines a data structure that logically holds either an E or an A. The flag discriminates the cases
func EitherFlatten ¶ added in v2.3.122
EitherFlatten removes one level of nesting from a nested Either.
Example:
nested := either.EitherRight[error](either.EitherRight[error](42)) result := either.EitherFlatten(nested) // Right(42)
func EitherFromIO ¶ added in v2.3.122
EitherFromIO executes an IO operation and wraps the result in a Right value. This is useful for lifting pure IO operations into the Either context.
Example:
getValue := lazy.Of(42) result := either.EitherFromIO[error](getValue) // Right(42)
go: inline
func EitherLeft ¶ added in v2.3.122
EitherLeft creates a new Either representing a EitherLeft (error/failure) value. By convention, EitherLeft represents the error case.
Example:
result := either.EitherLeft[int](errors.New("something went wrong"))
func EitherMemoize ¶ added in v2.3.122
EitherMemoize returns the Either unchanged (Either values are already memoized).
func EitherMonadAlt ¶ added in v2.3.122
EitherMonadAlt provides an alternative Either if the first is Left. This is the monadic version of EitherAlt.
func EitherMonadAp ¶ added in v2.3.122
EitherMonadAp applies a function wrapped in Either to a value wrapped in Either. If either the function or the value is Left, returns Left. This is the applicative apply operation.
Example:
fab := either.EitherRight[error](N.Mul(2)) fa := either.EitherRight[error](21) result := either.EitherMonadAp(fab, fa) // Right(42)
func EitherMonadBiMap ¶ added in v2.3.122
func EitherMonadBiMap[E1, E2, A, B any](fa Either[E1, A], f func(E1) E2, g func(a A) B) Either[E2, B]
EitherMonadBiMap applies two functions: one to transform a Left value, another to transform a Right value. This allows transforming both channels of the Either simultaneously.
Example:
result := either.EitherMonadBiMap(
either.EitherLeft[int](errors.New("error")),
error.Error,
func(n int) string { return fmt.Sprint(n) },
) // Left("error")
func EitherMonadChain ¶ added in v2.3.122
EitherMonadChain sequences two computations, where the second depends on the result of the first. If the first Either is Left, returns Left without executing the second computation. This is the monadic bind operation (also known as flatMap).
Example:
result := either.EitherMonadChain(
either.EitherRight[error](21),
func(x int) either.Either[error, int] {
return either.EitherRight[error](x * 2)
},
) // Right(42)
func EitherMonadChainFirst ¶ added in v2.3.122
EitherMonadChainFirst executes a side-effect computation but returns the original value. Useful for performing actions (like logging) without changing the value.
Example:
result := either.EitherMonadChainFirst(
either.EitherRight[error](42),
func(x int) either.Either[error, string] {
fmt.Println(x) // side effect
return either.EitherRight[error]("logged")
},
) // Right(42) - original value preserved
func EitherMonadChainLeft ¶ added in v2.3.122
func EitherMonadChainLeft[EA, EB, A any](fa Either[EA, A], f EitherKleisli[EB, EA, A]) Either[EB, A]
EitherMonadChainLeft sequences a computation on the Left (error) value, allowing error recovery or transformation. If the Either is Left, applies the provided function to the error value, which returns a new Either. If the Either is Right, returns the Right value unchanged with the new error type.
This is the dual of EitherMonadChain - while EitherMonadChain operates on Right values (success), EitherMonadChainLeft operates on Left values (errors). It's useful for error recovery, error transformation, or chaining alternative computations when an error occurs.
Note: EitherMonadChainLeft is identical to EitherOrElse - both provide the same functionality for error recovery.
The error type can be transformed from EA to EB, allowing flexible error type conversions.
Example:
// Error recovery: convert specific errors to success
result := either.EitherMonadChainLeft(
either.EitherLeft[int](errors.New("not found")),
func(err error) either.Either[string, int] {
if err.Error() == "not found" {
return either.EitherRight[string](0) // default value
}
return either.EitherLeft[int](err.Error()) // transform error
},
) // Right(0)
// Error transformation: change error type
result := either.EitherMonadChainLeft(
either.EitherLeft[int](404),
func(code int) either.Either[string, int] {
return either.EitherLeft[int](fmt.Sprintf("Error code: %d", code))
},
) // Left("Error code: 404")
// Right values pass through unchanged
result := either.EitherMonadChainLeft(
either.EitherRight[error](42),
func(err error) either.Either[string, int] {
return either.EitherLeft[int]("error")
},
) // Right(42)
func EitherMonadChainOptionK ¶ added in v2.3.122
func EitherMonadChainOptionK[A, B, E any](onNone func() E, ma Either[E, A], f func(A) Option[B]) Either[E, B]
EitherMonadChainOptionK chains a function that returns an Option, converting None to Left.
Example:
result := either.EitherMonadChainOptionK(
func() error { return errors.New("not found") },
either.EitherRight[error](42),
func(x int) option.Option[string] {
if x > 0 { return option.Some("positive") }
return option.None[string]()
},
) // Right("positive")
func EitherMonadChainTo ¶ added in v2.3.122
EitherMonadChainTo ignores the first Either and returns the second. Useful for sequencing operations where you don't need the first result.
func EitherMonadExtend ¶ added in v2.3.122
EitherMonadExtend applies a function to an Either value, where the function receives the entire Either as input. This is the Extend (or Comonad) operation that allows computations to depend on the context.
If the Either is Left, it returns Left unchanged without applying the function. If the Either is Right, it applies the function to the entire Either and wraps the result in a Right.
This operation is useful when you need to perform computations that depend on whether a value is present (Right) or absent (Left), not just on the value itself.
Type Parameters:
- E: The error type (Left channel)
- A: The input value type (Right channel)
- B: The output value type
Parameters:
- fa: The Either value to extend
- f: Function that takes the entire Either[E, A] and produces a value of type B
Returns:
- Either[E, B]: Left if input was Left, otherwise Right containing the result of f(fa)
Example:
// Count how many times we've seen a Right value
counter := func(e either.Either[error, int]) int {
return either.Fold(
func(err error) int { return 0 },
func(n int) int { return 1 },
)(e)
}
result := either.EitherMonadExtend(either.Right[error](42), counter) // Right(1)
result := either.EitherMonadExtend(either.Left[int](errors.New("err")), counter) // Left(error)
func EitherMonadFlap ¶ added in v2.3.122
EitherMonadFlap applies a value to a function wrapped in Either. This is the reverse of EitherMonadAp.
func EitherMonadMap ¶ added in v2.3.122
EitherMonadMap transforms the Right value using the provided function. If the Either is Left, returns Left unchanged. This is the functor map operation.
Example:
result := either.EitherMonadMap(
either.EitherRight[error](21),
N.Mul(2),
) // Right(42)
func EitherMonadMapLeft ¶ added in v2.3.122
EitherMonadMapLeft applies a transformation function to the Left (error) value. If the Either is Right, returns Right unchanged.
Example:
result := either.EitherMonadMapLeft(
either.EitherLeft[int](errors.New("error")),
error.Error,
) // Left("error")
func EitherMonadMapTo ¶ added in v2.3.122
EitherMonadMapTo replaces the Right value with a constant value. If the Either is Left, returns Left unchanged.
Example:
result := either.EitherMonadMapTo(either.EitherRight[error](21), "success") // Right("success")
func EitherMonadSequence2 ¶ added in v2.3.122
func EitherMonadSequence2[E, T1, T2, R any](e1 Either[E, T1], e2 Either[E, T2], f func(T1, T2) Either[E, R]) Either[E, R]
EitherMonadSequence2 sequences two Either values using a combining function. Short-circuits on the first Left encountered.
func EitherMonadSequence3 ¶ added in v2.3.122
func EitherMonadSequence3[E, T1, T2, T3, R any](e1 Either[E, T1], e2 Either[E, T2], e3 Either[E, T3], f func(T1, T2, T3) Either[E, R]) Either[E, R]
EitherMonadSequence3 sequences three Either values using a combining function. Short-circuits on the first Left encountered.
func EitherOf ¶ added in v2.3.122
EitherOf constructs a Right value containing the given value. This is the monadic return/pure operation for Either. Equivalent to EitherRight.
Example:
result := either.EitherOf[error](42) // Right(42)
func EitherRight ¶ added in v2.3.122
EitherRight creates a new Either representing a EitherRight (success) value. By convention, EitherRight represents the success case.
Example:
result := either.EitherRight[error](42)
func EitherSequenceArray ¶ added in v2.3.122
EitherSequenceArray converts a homogeneous sequence of Either into an Either of sequence. If any element is Left, returns that Left (short-circuits). Otherwise, returns Right containing all the Right values.
Example:
eithers := A.From(
either.Right[error](1),
either.Right[error](2),
either.Right[error](3),
)
result := either.EitherSequenceArray(eithers)
// result is Right([]int{1, 2, 3})
func EitherSequenceArrayG ¶ added in v2.3.122
func EitherSequenceRecord ¶ added in v2.3.122
func EitherSequenceRecord[K comparable, E, A any](ma map[K]Either[E, A]) Either[E, map[K]A]
EitherSequenceRecord converts a map of Either values into an Either of a map. If any value is Left, returns that Left (short-circuits). Otherwise, returns Right containing a map of all the Right values.
Example:
eithers := map[string]either.Either[error, int]{
"a": either.Right[error](1),
"b": either.Right[error](2),
}
result := either.EitherSequenceRecord(eithers)
// result is Right(map[string]int{"a": 1, "b": 2})
func EitherSequenceRecordG ¶ added in v2.3.122
func EitherSequenceRecordG[GA ~map[K]A, GOA ~map[K]Either[E, A], K comparable, E, A any](ma GOA) Either[E, GA]
func EitherSequenceSeq ¶ added in v2.3.122
SequenceSeq converts an iterator of Either into an Either of iterator. If any element is Left, returns that Left (short-circuits). Otherwise, returns Right containing an iterator of all the Right values.
This function eagerly evaluates all Either values in the input iterator to detect any Left values, then returns an iterator over the collected Right values.
Type Parameters ¶
- E: The error type for Left values
- A: The value type for Right values
Parameters ¶
- ma: An iterator of Either values
Returns ¶
- Either containing an iterator of Right values, or the first Left encountered
Example Usage ¶
eithers := slices.Values([]either.Either[error, int]{
either.Right[error](1),
either.Right[error](2),
either.Right[error](3),
})
result := either.SequenceSeq(eithers)
// result is Right(iterator over [1, 2, 3])
See Also ¶
- EitherSequenceArray: For slice-based sequencing
- EitherTraverseSeq: For transforming and sequencing in one step
func EitherSwap ¶ added in v2.3.122
EitherSwap exchanges the Left and Right type parameters.
Example:
result := either.EitherSwap(either.EitherRight[error](42)) // Left(42)
result := either.EitherSwap(either.EitherLeft[int](errors.New("err"))) // Right(error)
func EitherTryCatch ¶ added in v2.3.122
EitherTryCatch converts a (value, error) tuple into an Either, applying a transformation to the error.
Example:
result := either.EitherTryCatch(
42, nil,
func(err error) string { return err.Error() },
) // Right(42)
func EitherTryCatchError ¶ added in v2.3.122
EitherTryCatchError is a specialized version of EitherTryCatch for error types. Converts a (value, error) tuple into Either[error, A].
Example:
result := either.EitherTryCatchError(42, nil) // Right(42)
result := either.EitherTryCatchError(0, errors.New("fail")) // Left(error)
func EitherZero ¶ added in v2.3.122
EitherZero returns the zero value of an Either, which is a Right containing the zero value of type A. This function is useful as an identity element in monoid operations or for creating an empty Either in a Right state.
The returned Either is always a Right value containing the zero value of type A. For reference types (pointers, slices, maps, channels, functions, interfaces), the zero value is nil. For value types (numbers, booleans, structs), it's the type's zero value.
Important: EitherZero() returns the same value as the default initialization of Either[E, A]. When you declare `var e Either[E, A]` without initialization, it has the same value as EitherZero[E, A]().
Note: This differs from creating a Left value, which would represent an error or failure state. EitherZero always produces a successful (Right) state with a zero value.
Example:
// Zero Either with int value
e1 := either.EitherZero[error, int]() // Right(0)
// Zero Either with string value
e2 := either.EitherZero[error, string]() // Right("")
// Zero Either with pointer type
e3 := either.EitherZero[error, *int]() // Right(nil)
// Zero equals default initialization
var defaultInit Either[error, int]
zero := either.EitherZero[error, int]()
assert.Equal(t, defaultInit, zero) // true
// Verify it's a Right value
e := either.EitherZero[error, int]()
assert.True(t, either.IsRight(e)) // true
assert.False(t, either.IsLeft(e)) // false
type EitherKleisli ¶ added in v2.3.122
EitherKleisli represents a Kleisli arrow for the Either monad. It's a function from A to Either[E, B], used for composing operations that may fail.
func EitherAltAllArray ¶ added in v2.3.122
EitherAltAllArray combines multiple Either values from an array using the Alt operation. It starts with an initial Either and iteratively applies Alt with each Either in the array, returning the first Right value encountered or the last Left value if all are Left.
The Alt operation returns the first Either if it's Right, otherwise returns the alternative. This function chains multiple Alt operations together, effectively implementing a "first success" or "fallback chain" pattern for Either values.
Implementation:
This function is semantically equivalent to alt.AltAllArray[Either[E, A]](Alt)(startWith) but uses the generic implementation directly. The generic alt.AltAllArray provides lazy evaluation through thunks, which enables early break when a Right value is found.
Short-Circuit Behavior:
This function short-circuits on the first Right value but processes all Left values:
- If startWith is Right, it returns immediately without examining the array
- When iterating, it returns immediately upon finding the first Right value
- The array is not fully consumed once a Right value is found
- If all elements are Left, the entire array is traversed and the last Left is returned
Relationship to array.Fold and AltMonoid:
EitherAltAllArray is closely related to array.Fold with AltMonoid:
- When startWith is Left, EitherAltAllArray(Left[E, A](e))(eithers) is equivalent to array.Fold(AltMonoid[E, A]())(eithers)
- When startWith is Right, it's equivalent to prepending startWith to the array before folding: array.Fold(AltMonoid[E, A]())(append([]Either[E, A]{startWith}, eithers...))
- AltMonoid is a monoid that uses Alt as its Concat operation and Left as Empty
- Both approaches have O(n) time complexity and similar performance
Use EitherAltAllArray when you want to:
- Express the "find first Right value" pattern clearly
- Specify a custom starting value (not just Left)
- Work specifically with Either values in a functional style
- Implement fallback chains for error handling
Type Parameters:
- E: The type of error/Left value
- A: The type of success/Right value
Parameters:
- startWith: The initial Either to start the chain with
Returns:
- Kleisli[E, []Either[E, A], A]: A function that takes an array of Either values and returns an Either containing the first Right value, or the last Left value if all are Left
See Also:
- Alt: The underlying Alt operation
- EitherAltAllSeq: Similar function for iterator sequences
- AltMonoid: Monoid that uses Alt operation
func EitherAltAllSeq ¶ added in v2.3.122
EitherAltAllSeq combines multiple Either values from an iterator sequence using the Alt operation. It starts with an initial Either and iteratively applies Alt with each Either from the sequence, returning the first Right value encountered or the last Left value if all are Left.
This function is similar to EitherAltAllArray but works with Go's iterator sequences, making it suitable for lazy evaluation and potentially infinite sequences.
Implementation:
This function is semantically equivalent to alt.AltAllSeq[Either[E, A]](Alt)(startWith) but uses the generic implementation directly. The generic alt.AltAllSeq provides lazy evaluation through thunks, which enables early break when a Right value is found.
Short-Circuit Behavior:
This function short-circuits on the first Right value but processes all Left values:
- If startWith is Right, it returns immediately without consuming the sequence
- When iterating, it returns immediately upon finding the first Right value
- The sequence is not fully consumed once a Right value is found
- This makes it safe to use with infinite sequences as long as a Right value exists
- If all elements are Left, the entire sequence is consumed and the last Left is returned
Relationship to Folding:
Like EitherAltAllArray, this function implements a fold operation using the Alt operation. The key difference is that it works with iterator sequences instead of arrays, enabling:
- Lazy evaluation of the sequence
- Working with potentially infinite sequences
- Memory-efficient processing of large datasets
- Composition with other iterator-based operations
The relationship to AltMonoid is the same as EitherAltAllArray, but applied to sequences rather than arrays.
Type Parameters:
- E: The type of error/Left value
- A: The type of success/Right value
Parameters:
- startWith: The initial Either to start the chain with
Returns:
- EitherKleisli[E, iter.Seq[Either[E, A]], A]: A function that takes a sequence of Either values and returns an Either containing the first Right value, or the last Left value if all are Left
See Also:
- Alt: The underlying Alt operation
- EitherAltAllArray: Similar function for arrays
- AltMonoid: Monoid that uses Alt operation
func EitherAltW ¶ added in v2.3.122
EitherAltW provides an alternative Either if the first is Left, allowing different error types. The 'W' suffix indicates "widening" of the error type.
Example:
alternative := either.EitherAltW[error, string](func() either.Either[string, int] {
return either.EitherRight[string](99)
})
result := alternative(either.EitherLeft[int](errors.New("fail"))) // Right(99)
func EitherChainLeft ¶ added in v2.3.122
EitherChainLeft is the curried version of EitherMonadChainLeft. Returns a function that sequences a computation on the Left (error) value.
Note: EitherChainLeft is identical to EitherOrElse - both provide the same functionality for error recovery.
This is useful for creating reusable error handlers or transformers that can be composed with other Either operations using pipes or function composition.
Example:
// Create a reusable error handler
handleNotFound := either.EitherChainLeft[error, string](func(err error) either.Either[string, int] {
if err.Error() == "not found" {
return either.EitherRight[string](0)
}
return either.EitherLeft[int](err.Error())
})
// Use in a pipeline
result := F.Pipe1(
either.EitherLeft[int](errors.New("not found")),
handleNotFound,
) // Right(0)
func EitherFromNillable ¶ added in v2.3.122
func EitherFromNillable[A, E any](e E) EitherKleisli[E, *A, *A]
EitherFromNillable creates an Either from a pointer, using the provided error for nil pointers.
Example:
var ptr *int = nil
result := either.EitherFromNillable[int](errors.New("nil"))(ptr) // Left(error)
val := 42
result := either.EitherFromNillable[int](errors.New("nil"))(&val) // Right(&42)
func EitherFromPredicate ¶ added in v2.3.122
func EitherFromPredicate[E, A any](pred Predicate[A], onFalse func(A) E) EitherKleisli[E, A, A]
EitherFromPredicate creates an Either based on a predicate. If the predicate returns true, creates a Right; otherwise creates a Left using onFalse.
Example:
isPositive := either.EitherFromPredicate(
N.MoreThan(0),
func(x int) error { return errors.New("not positive") },
)
result := isPositive(42) // Right(42)
result := isPositive(-1) // Left(error)
func EitherOrElse ¶ added in v2.3.122
func EitherOrElse[E1, E2, A any](onLeft EitherKleisli[E2, E1, A]) EitherKleisli[E2, Either[E1, A], A]
EitherOrElse recovers from a Left (error) by providing an alternative computation. If the Either is Right, it returns the value unchanged. If the Either is Left, it applies the provided function to the error value, which returns a new Either that replaces the original.
Note: EitherOrElse is identical to EitherChainLeft - both provide the same functionality for error recovery.
This is useful for error recovery, fallback logic, or chaining alternative computations. The error type can be widened from E1 to E2, allowing transformation of error types.
Example:
// Recover from specific errors with fallback values
recover := either.EitherOrElse(func(err error) either.Either[error, int] {
if err.Error() == "not found" {
return either.EitherRight[error](0) // default value
}
return either.EitherLeft[int](err) // propagate other errors
})
result := recover(either.EitherLeft[int](errors.New("not found"))) // Right(0)
result := recover(either.EitherRight[error](42)) // Right(42) - unchanged
func EitherTraverseArray ¶ added in v2.3.122
func EitherTraverseArray[E, A, B any](f EitherKleisli[E, A, B]) EitherKleisli[E, []A, []B]
EitherTraverseArray transforms an array by applying a function that returns an Either to each element. If any element produces a Left, the entire result is that Left (short-circuits). Otherwise, returns Right containing the array of all Right values.
Example:
parse := func(s string) either.Either[error, int] {
v, err := strconv.Atoi(s)
return either.FromError(v, err)
}
result := either.EitherTraverseArray(parse)([]string{"1", "2", "3"})
// result is Right([]int{1, 2, 3})
func EitherTraverseArrayG ¶ added in v2.3.122
func EitherTraverseArrayG[GA ~[]A, GB ~[]B, E, A, B any](f EitherKleisli[E, A, B]) EitherKleisli[E, GA, GB]
EitherTraverseArrayG transforms an array by applying a function that returns an Either to each element. If any element produces a Left, the entire result is that Left (short-circuits). Otherwise, returns Right containing the array of all Right values. The G suffix indicates support for generic slice types.
Example:
parse := func(s string) either.Either[error, int] {
v, err := strconv.Atoi(s)
return either.FromError(v, err)
}
result := either.EitherTraverseArrayG[[]string, []int](parse)([]string{"1", "2", "3"})
// result is Right([]int{1, 2, 3})
func EitherTraverseArrayWithIndex ¶ added in v2.3.122
func EitherTraverseArrayWithIndex[E, A, B any](f func(int, A) Either[E, B]) EitherKleisli[E, []A, []B]
EitherTraverseArrayWithIndex transforms an array by applying an indexed function that returns an Either. The function receives both the index and the element. If any element produces a Left, the entire result is that Left (short-circuits).
Example:
validate := func(i int, s string) either.Either[error, string] {
if S.IsNonEmpty(s) {
return either.Right[error](fmt.Sprintf("%d:%s", i, s))
}
return either.Left[string](fmt.Errorf("empty at index %d", i))
}
result := either.EitherTraverseArrayWithIndex(validate)([]string{"a", "b"})
// result is Right([]string{"0:a", "1:b"})
func EitherTraverseArrayWithIndexG ¶ added in v2.3.122
func EitherTraverseArrayWithIndexG[GA ~[]A, GB ~[]B, E, A, B any](f func(int, A) Either[E, B]) EitherKleisli[E, GA, GB]
EitherTraverseArrayWithIndexG transforms an array by applying an indexed function that returns an Either. The function receives both the index and the element. If any element produces a Left, the entire result is that Left (short-circuits). The G suffix indicates support for generic slice types.
Example:
validate := func(i int, s string) either.Either[error, string] {
if S.IsNonEmpty(s) {
return either.Right[error](fmt.Sprintf("%d:%s", i, s))
}
return either.Left[string](fmt.Errorf("empty at index %d", i))
}
result := either.EitherTraverseArrayWithIndexG[[]string, []string](validate)([]string{"a", "b"})
// result is Right([]string{"0:a", "1:b"})
func EitherTraverseRecord ¶ added in v2.3.122
func EitherTraverseRecord[K comparable, E, A, B any](f EitherKleisli[E, A, B]) EitherKleisli[E, map[K]A, map[K]B]
EitherTraverseRecord transforms a map by applying a function that returns an Either to each value. If any value produces a Left, the entire result is that Left (short-circuits). Otherwise, returns Right containing the map of all Right values.
Example:
parse := func(s string) either.Either[error, int] {
v, err := strconv.Atoi(s)
return either.FromError(v, err)
}
result := either.EitherTraverseRecord[string](parse)(map[string]string{"a": "1", "b": "2"})
// result is Right(map[string]int{"a": 1, "b": 2})
func EitherTraverseRecordG ¶ added in v2.3.122
func EitherTraverseRecordG[GA ~map[K]A, GB ~map[K]B, K comparable, E, A, B any](f EitherKleisli[E, A, B]) EitherKleisli[E, GA, GB]
EitherTraverseRecordG transforms a map by applying a function that returns an Either to each value. If any value produces a Left, the entire result is that Left (short-circuits). Otherwise, returns Right containing the map of all Right values. The G suffix indicates support for generic map types.
Example:
parse := func(s string) either.Either[error, int] {
v, err := strconv.Atoi(s)
return either.FromError(v, err)
}
result := either.EitherTraverseRecordG[map[string]string, map[string]int](parse)(map[string]string{"a": "1", "b": "2"})
// result is Right(map[string]int{"a": 1, "b": 2})
func EitherTraverseRecordWithIndex ¶ added in v2.3.122
func EitherTraverseRecordWithIndex[K comparable, E, A, B any](f func(K, A) Either[E, B]) EitherKleisli[E, map[K]A, map[K]B]
EitherTraverseRecordWithIndex transforms a map by applying an indexed function that returns an Either. The function receives both the key and the value. If any value produces a Left, the entire result is that Left (short-circuits).
Example:
validate := func(k string, v string) either.Either[error, string] {
if len(v) > 0 {
return either.Right[error](k + ":" + v)
}
return either.Left[string](fmt.Errorf("empty value for key %s", k))
}
result := either.EitherTraverseRecordWithIndex[string](validate)(map[string]string{"a": "1"})
// result is Right(map[string]string{"a": "a:1"})
func EitherTraverseRecordWithIndexG ¶ added in v2.3.122
func EitherTraverseRecordWithIndexG[GA ~map[K]A, GB ~map[K]B, K comparable, E, A, B any](f func(K, A) Either[E, B]) EitherKleisli[E, GA, GB]
EitherTraverseRecordWithIndexG transforms a map by applying an indexed function that returns an Either. The function receives both the key and the value. If any value produces a Left, the entire result is that Left (short-circuits). The G suffix indicates support for generic map types.
Example:
validate := func(k string, v string) either.Either[error, string] {
if len(v) > 0 {
return either.Right[error](k + ":" + v)
}
return either.Left[string](fmt.Errorf("empty value for key %s", k))
}
result := either.EitherTraverseRecordWithIndexG[map[string]string, map[string]string](validate)(map[string]string{"a": "1"})
// result is Right(map[string]string{"a": "a:1"})
func EitherTraverseSeq ¶ added in v2.3.122
func EitherTraverseSeq[E, A, B any](f EitherKleisli[E, A, B]) EitherKleisli[E, iter.Seq[A], iter.Seq[B]]
TraverseSeq transforms an iterator by applying a function that returns an Either to each element. If any element produces a Left, the entire result is that Left (short-circuits). Otherwise, returns Right containing an iterator of all Right values.
The function eagerly evaluates all elements in the input iterator to detect any Left values, then returns an iterator over the collected Right values. This is necessary because Either represents computations that can fail, and we need to know if any element failed before producing the result iterator.
Type Parameters ¶
- E: The error type for Left values
- A: The input element type
- B: The output element type
Parameters ¶
- f: A function that transforms each element into an Either
Returns ¶
- A function that takes an iterator of A and returns Either containing an iterator of B
Example Usage ¶
parse := func(s string) either.Either[error, int] {
v, err := strconv.Atoi(s)
return either.FromError(v, err)
}
input := slices.Values([]string{"1", "2", "3"})
result := either.TraverseSeq(parse)(input)
// result is Right(iterator over [1, 2, 3])
See Also ¶
- EitherTraverseArray: For slice-based traversal
- EitherSequenceSeq: For sequencing iterators of Either values
func EitherWithResource ¶ added in v2.3.122
func EitherWithResource[A, E, R, ANY any]( onCreate func() Either[E, R], onRelease EitherKleisli[E, R, ANY], ) EitherKleisli[E, EitherKleisli[E, R, A], A]
EitherWithResource constructs a function that creates a resource, operates on it, and then releases it. This ensures proper resource cleanup even if operations fail. The resource is released immediately after the operation completes.
Parameters:
- onCreate: Function to create/acquire the resource
- onRelease: Function to release/cleanup the resource
Returns a function that takes an operation to perform on the resource.
Example:
withFile := either.EitherWithResource(
func() either.Either[error, *os.File] {
return either.TryCatchError(os.Open("file.txt"))
},
func(f *os.File) either.Either[error, any] {
return either.TryCatchError(f.Close())
},
)
result := withFile(func(f *os.File) either.Either[error, string] {
// Use file here
return either.Right[error]("data")
})
type EitherOperator ¶ added in v2.3.122
type EitherOperator[E, A, B any] = EitherKleisli[E, Either[E, A], B]
EitherOperator represents a function that transforms one Either into another. It takes an Either[E, A] and produces an Either[E, B].
func EitherAlt ¶ added in v2.3.122
EitherAlt provides an alternative Either if the first is Left.
Example:
alternative := either.EitherAlt[error](func() either.Either[error, int] {
return either.EitherRight[error](99)
})
result := alternative(either.EitherLeft[int](errors.New("fail"))) // Right(99)
func EitherAp ¶ added in v2.3.122
EitherAp is the curried version of EitherMonadAp. Returns a function that applies a wrapped function to the given wrapped value.
func EitherChain ¶ added in v2.3.122
func EitherChain[E, A, B any](f EitherKleisli[E, A, B]) EitherOperator[E, A, B]
EitherChain is the curried version of EitherMonadChain. Sequences two computations where the second depends on the first.
func EitherChainFirst ¶ added in v2.3.122
func EitherChainFirst[E, A, B any](f EitherKleisli[E, A, B]) EitherOperator[E, A, A]
EitherChainFirst is the curried version of EitherMonadChainFirst.
func EitherChainTo ¶ added in v2.3.122
EitherChainTo is the curried version of EitherMonadChainTo.
func EitherExtend ¶ added in v2.3.122
EitherExtend is the curried version of EitherMonadExtend. It returns a function that applies the given function to an Either value.
This is useful for creating reusable transformations that depend on the Either context.
Type Parameters:
- E: The error type (Left channel)
- A: The input value type (Right channel)
- B: The output value type
Parameters:
- f: Function that takes the entire Either[E, A] and produces a value of type B
Returns:
- Operator[E, A, B]: A function that transforms Either[E, A] to Either[E, B]
Example:
// Create a reusable extender that extracts metadata
getMetadata := either.EitherExtend(func(e either.Either[error, string]) string {
return either.Fold(
func(err error) string { return "error: " + err.Error() },
func(s string) string { return "value: " + s },
)(e)
})
result := getMetadata(either.Right[error]("hello")) // Right("value: hello")
func EitherFilter ¶ added in v2.3.122
func EitherFilter[E, A any](p Predicate[A], empty E) EitherOperator[E, A, A]
EitherFilter creates a filtering operation for Either values based on a predicate function. It returns a function that takes an Either and produces an Either, where Right values that fail the predicate are converted to Left values with the provided empty value.
This function implements the Filterable specification's filter operation: https://github.com/fantasyland/fantasy-land#filterable
The behavior is as follows:
- If the input is Left, it passes through unchanged
- If the input is Right and the predicate returns true, the Right value passes through unchanged
- If the input is Right and the predicate returns false, it's converted to Left(empty)
This function is useful for conditional validation or filtering of Either values, where you want to reject Right values that don't meet certain criteria by converting them to Left values with a default error.
Parameters:
- p: A predicate function that tests values of type A
- empty: The default Left value to use when filtering out Right values that fail the predicate
Returns:
An Operator function that takes an Either[E, A] and returns an Either[E, A] where: - Left values pass through unchanged - Right values that pass the predicate remain as Right - Right values that fail the predicate become Left(empty)
Example:
import (
E "github.com/IBM/fp-go/v2/either"
N "github.com/IBM/fp-go/v2/number"
)
// EitherFilter to keep only positive numbers
isPositive := N.MoreThan(0)
filterPositive := E.EitherFilter(isPositive, "not positive")
// Right value that passes predicate - remains Right
result1 := filterPositive(E.Right[string](5))
// result1 = Right(5)
// Right value that fails predicate - becomes Left
result2 := filterPositive(E.Right[string](-3))
// result2 = Left("not positive")
// Left value passes through unchanged
result3 := filterPositive(E.EitherLeft[int]("original error"))
// result3 = Left("original error")
// Chaining filters
isEven := func(n int) bool { return n%2 == 0 }
filterEven := E.EitherFilter(isEven, "not even")
// Apply multiple filters in sequence
result4 := filterEven(filterPositive(E.Right[string](4)))
// result4 = Right(4) - passes both filters
result5 := filterEven(filterPositive(E.Right[string](3)))
// result5 = Left("not even") - passes first, fails second
func EitherFilterMap ¶ added in v2.3.122
func EitherFilterMap[E, A, B any](f OptionKleisli[A, B], empty E) EitherOperator[E, A, B]
EitherFilterMap combines filtering and mapping operations for Either values using an Option-returning function. It returns a function that takes an Either[E, A] and produces an Either[E, B], where Right values are transformed by applying the function f. If f returns Some(B), the result is Right(B). If f returns None, the result is Left(empty).
This function implements the Filterable specification's filterMap operation: https://github.com/fantasyland/fantasy-land#filterable
The behavior is as follows:
- If the input is Left, it passes through with its error value preserved as EitherLeft[B]
- If the input is Right and f returns Some(B), the result is Right(B)
- If the input is Right and f returns None, the result is Left(empty)
This function is useful for operations that combine validation/filtering with transformation, such as parsing strings to numbers (where invalid strings result in None), or extracting optional fields from structures.
Parameters:
- f: An Option Kleisli function that transforms values of type A to Option[B]
- empty: The default Left value to use when f returns None
Returns:
An Operator function that takes an Either[E, A] and returns an Either[E, B] where: - Left values pass through with error preserved - Right values are transformed by f: Some(B) becomes Right(B), None becomes Left(empty)
Example:
import (
E "github.com/IBM/fp-go/v2/either"
O "github.com/IBM/fp-go/v2/option"
"strconv"
)
// Parse string to int, filtering out invalid values
parseInt := func(s string) O.Option[int] {
if n, err := strconv.Atoi(s); err == nil {
return O.Some(n)
}
return O.None[int]()
}
filterMapInt := E.EitherFilterMap(parseInt, "invalid number")
// Valid number string - transforms to Right(int)
result1 := filterMapInt(E.Right[string]("42"))
// result1 = Right(42)
// Invalid number string - becomes Left
result2 := filterMapInt(E.Right[string]("abc"))
// result2 = Left("invalid number")
// Left value passes through with error preserved
result3 := filterMapInt(E.EitherLeft[string]("original error"))
// result3 = Left("original error")
// Extract optional field from struct
type Person struct {
Name string
Email O.Option[string]
}
extractEmail := func(p Person) O.Option[string] { return p.Email }
filterMapEmail := E.EitherFilterMap(extractEmail, "no email")
result4 := filterMapEmail(E.Right[string](Person{Name: "Alice", Email: O.Some("alice@example.com")}))
// result4 = Right("alice@example.com")
result5 := filterMapEmail(E.Right[string](Person{Name: "Bob", Email: O.None[string]()}))
// result5 = Left("no email")
func EitherFlap ¶ added in v2.3.122
func EitherFlap[E, B, A any](a A) EitherOperator[E, func(A) B, B]
EitherFlap is the curried version of EitherMonadFlap.
func EitherMap ¶ added in v2.3.122
func EitherMap[E, A, B any](f func(A) B) EitherOperator[E, A, B]
EitherMap is the curried version of EitherMonadMap. Transforms the Right value using the provided function.
func EitherMapTo ¶ added in v2.3.122
func EitherMapTo[E, A, B any](b B) EitherOperator[E, A, B]
EitherMapTo is the curried version of EitherMonadMapTo.
type EitherTraversable ¶ added in v2.3.122
type EitherTraversable[E, A, B, GA, GB any] = func(EitherKleisli[E, A, B]) EitherKleisli[E, GA, GB]
func EitherTraversableArray ¶ added in v2.3.122
func EitherTraversableArray[E, A, B any]() EitherTraversable[E, A, B, []A, []B]
func EitherTraversableRecord ¶ added in v2.3.122
func EitherTraversableRecord[K comparable, E, A, B any]() EitherTraversable[E, A, B, map[K]A, map[K]B]
type Endomorphism ¶
type Endomorphism[A any] = endomorphism.Endomorphism[A]
Endomorphism is a function from a type to itself (A → A). It represents transformations that preserve the type.
type Iso ¶
type Iso[S, A any] struct { // Get converts a value from the source type S to the target type A. Get func(s S) A // ReverseGet converts a value from the target type A back to the source type S. // This is the inverse of Get. ReverseGet func(a A) S // contains filtered or unexported fields }
Iso represents an isomorphism between types S and A. An isomorphism is a bidirectional transformation that converts between two types without any loss of information. It consists of two functions that are inverses of each other.
Type Parameters:
- S: The source type
- A: The target type
Fields:
- Get: Converts from S to A
- ReverseGet: Converts from A back to S
Laws: An Iso must satisfy the round-trip laws:
- ReverseGet(Get(s)) == s for all s: S
- Get(ReverseGet(a)) == a for all a: A
Example:
// Isomorphism between Celsius and Fahrenheit
tempIso := Iso[float64, float64]{
Get: func(c float64) float64 { return c*9/5 + 32 },
ReverseGet: func(f float64) float64 { return (f - 32) * 5 / 9 },
}
fahrenheit := tempIso.Get(20.0) // 68.0
celsius := tempIso.ReverseGet(68.0) // 20.0
func IsoId ¶
IsoId returns an identity isomorphism that performs no transformation. Both Get and ReverseGet are the identity function.
Type Parameters:
- S: The type for both source and target
Returns:
- An Iso[S, S] where Get and ReverseGet are both identity functions
Example:
idIso := IsoId[int]() value := idIso.Get(42) // 42 same := idIso.ReverseGet(42) // 42
Use cases:
- As a starting point for isomorphism composition
- When you need an isomorphism but don't want to transform the value
- In generic code that requires an isomorphism parameter
func IsoReverse ¶
IsoReverse swaps the direction of an isomorphism. Given Iso[S, A], creates Iso[A, S] where Get and ReverseGet are swapped.
Type Parameters:
- S: The original source type (becomes target)
- A: The original target type (becomes source)
Parameters:
- sa: The isomorphism to reverse
Returns:
- An Iso[A, S] with Get and ReverseGet swapped
Example:
celsiusToFahrenheit := MakeIso(
func(c float64) float64 { return c*9/5 + 32 },
func(f float64) float64 { return (f - 32) * 5 / 9 },
)
// IsoReverse to get Fahrenheit to Celsius
fahrenheitToCelsius := IsoReverse(celsiusToFahrenheit)
celsius := fahrenheitToCelsius.Get(68.0) // 20.0
fahrenheit := fahrenheitToCelsius.ReverseGet(20.0) // 68.0
func MakeIso ¶
MakeIso constructs an isomorphism from two functions. The functions should be inverses of each other to satisfy the isomorphism laws.
Type Parameters:
- S: The source type
- A: The target type
Parameters:
- get: Function to convert from S to A
- reverse: Function to convert from A to S (inverse of get)
Returns:
- An Iso[S, A] that uses the provided functions
Example:
// Create an isomorphism between string and []byte
stringBytesIso := MakeIso(
func(s string) []byte { return []byte(s) },
func(b []byte) string { return string(b) },
)
bytes := stringBytesIso.Get("hello") // []byte("hello")
str := stringBytesIso.ReverseGet([]byte("hi")) // "hi"
func (Iso[S, A]) Compose ¶
Compose returns a new isomorphism that focuses deeper by chaining this isomorphism (S → A) with an inner isomorphism (A → B), producing a composed isomorphism (S → B).
This is the method-receiver form of the package-level OptionalComposeOptional function, available only on Go 1.27 and later because Go did not support type parameters on methods before that version. On earlier toolchains, use the equivalent free function instead:
// method form (go1.27+) composed := outerIso.Compose(innerIso) // free-function form (all versions) composed := iso.Compose[S](innerIso)(outerIso)
Get of the composed isomorphism applies the outer Get followed by the inner Get: composed.Get(s) = ab.Get(sa.Get(s)).
ReverseGet of the composed isomorphism applies the inner ReverseGet followed by the outer ReverseGet: composed.ReverseGet(b) = sa.ReverseGet(ab.ReverseGet(b)).
The composed isomorphism satisfies both iso round-trip laws whenever both constituent isomorphisms individually satisfy them:
composed.ReverseGet(composed.Get(s)) == s for all s: S composed.Get(composed.ReverseGet(b)) == b for all b: B
Type Parameters:
- B: the target type of the inner isomorphism and of the resulting isomorphism
Parameters:
- ab: the inner isomorphism from A to B
Returns:
- Iso[S, B]: a new isomorphism from S directly to B
See Also:
- Compose: the equivalent package-level function
- Reverse: swaps the direction of an isomorphism
func (Iso[S, A]) ComposeLens ¶
ComposeLens returns a new lens by composing this isomorphism (S ↔ A) with an inner lens (A → B), producing a Lens[S, B].
Internally the isomorphism is first converted to a Lens[S, A] via IsoAsLens, then composed with the provided lens using LensComposeLens. The result focuses on a value of type B that is reached by first applying the isomorphism's Get direction and then the inner lens's Get.
This is the method-receiver form of the package-level IsoComposeLens function, available only on Go 1.27 and later because Go did not support type parameters on methods before that version. On earlier toolchains use the equivalent free function:
// method form (go1.27+) streetLens := addressIso.ComposeLens(streetFieldLens) // free-function form (all versions) streetLens := IsoComposeLens[S](streetFieldLens)(addressIso)
The resulting lens satisfies all three lens laws whenever both the isomorphism and the inner lens individually satisfy them.
Type Parameters:
- B: the focus type of the inner lens and of the resulting lens
Parameters:
- ab: the inner lens from A to B
Returns:
- Lens[S, B]: a new lens from S directly to B
See Also:
- Compose: the equivalent method for composing with an Iso[A, B] instead of a Lens[A, B]
- IsoComposeLens: the equivalent package-level function
type Lens ¶
type Lens[S, A any] struct { // Get extracts the focused value of type A from structure S. Get func(s S) A // Set returns a function that updates the focused value in structure S. // The returned function takes a structure S and returns a new structure S // with the focused value updated to a. The original structure is never modified. Set func(a A) Endomorphism[S] // contains filtered or unexported fields }
Lens is a functional reference to a subpart of a data structure.
A Lens[S, A] provides a composable way to focus on a field of type A within a structure of type S. It consists of two operations:
- Get: Extracts the focused value from the structure (S → A)
- Set: Updates the focused value in the structure, returning a new structure (A → S → S)
Lenses maintain immutability by always returning new copies of the structure when setting values, never modifying the original.
Type Parameters:
- S: The source/structure type (the whole)
- A: The focus/field type (the part)
Lens Laws:
A well-behaved lens must satisfy three laws:
- GetSet (You get what you set): lens.Set(lens.Get(s))(s) == s
- SetGet (You set what you get): lens.Get(lens.Set(a)(s)) == a
- SetSet (Setting twice is the same as setting once): lens.Set(a2)(lens.Set(a1)(s)) == lens.Set(a2)(s)
Example Usage:
type Person struct {
Name string
Age int
}
// Create a lens focusing on the Name field
nameLens := lens.MakeLens(
func(p Person) string { return p.Name },
func(name string) func(Person) Person {
return func(p Person) Person {
return Person{Name: name, Age: p.Age}
}
},
)
person := Person{Name: "Alice", Age: 30}
name := nameLens.Get(person) // Returns: "Alice"
updated := nameLens.Set("Bob")(person) // Returns: Person{Name: "Bob", Age: 30}
// Original person remains unchanged (immutability preserved)
func IsoAsLens ¶
IsoAsLens converts an Iso[S, A] into a Lens[S, A].
The resulting lens uses the iso's Get as its getter and its ReverseGet as its setter. Because an isomorphism is total and invertible, Set always replaces the focused value by applying ReverseGet — the original S is discarded.
Type Parameters:
- S: The source type of the isomorphism and of the resulting lens
- A: The target type of the isomorphism and the focus type of the resulting lens
Parameters:
- sa: The isomorphism to convert
Returns:
- Lens[S, A]: a lens whose Get is sa.Get and whose Set is sa.ReverseGet
See Also:
- IsoAsLensRef: the pointer-receiver variant for Iso[*S, A]
func IsoAsLensRef
deprecated
IsoAsLensRef converts an Iso[*S, A] into a Lens[*S, A] for pointer-based structures.
This is the pointer-receiver variant of IsoAsLens. It accepts an isomorphism whose source type is already a pointer (*S) and wraps the resulting lens with copy-on-write semantics: before the setter is applied, a shallow copy of *S is made so that the original value is never mutated. A nil pointer is handled safely by substituting a zero-value S.
In practice the copy-on-write wrapper is a no-op for an iso-derived setter, because the setter is simply ReverseGet(a) and ignores the incoming *S entirely. The wrapper exists for consistency with other pointer lenses and to guard against nil inputs.
Deprecated: IsoAsLens[*S, A] is sufficient because the copy-on-write wrapper added by this function has no observable effect for iso-derived setters. Prefer IsoAsLens unless you specifically need the nil-pointer safety on the incoming *S, which the iso's ReverseGet already cannot depend on.
Type Parameters:
- S: The pointee type; the isomorphism source is *S
- A: The target type of the isomorphism and the focus type of the resulting lens
Parameters:
- sa: The isomorphism from *S to A to convert
Returns:
- Lens[*S, A]: a lens whose Get is sa.Get and whose Set applies sa.ReverseGet with copy-on-write protection on the *S receiver
See Also:
- IsoAsLens: the general form that accepts any Iso[S, A], including Iso[*S, A]
func LensId ¶
LensId returns an identity Lens that focuses on the entire structure.
The identity lens is useful as a starting point for lens composition or when you need a lens that doesn't actually focus on a subpart. Get returns the structure unchanged, and Set replaces the entire structure.
Type Parameters:
- S: The structure type
Returns:
- A Lens[S, S] where both source and focus are the same type
Example:
type Person struct {
Name string
Age int
}
idLens := lens.LensId[Person]()
person := Person{Name: "Alice", Age: 30}
same := idLens.Get(person) // Returns person unchanged
replaced := idLens.Set(Person{Name: "Bob", Age: 25})(person)
// replaced is Person{Name: "Bob", Age: 25}
func LensIdRef ¶
LensIdRef returns an identity Lens for pointer-based structures.
This is the pointer version of LensId. It focuses on the entire pointer structure, with automatic copying to ensure immutability.
Type Parameters:
- S: The structure type (will be used as *S)
Returns:
- A Lens[*S, *S] where both source and focus are pointers to the same type
Example:
idLens := lens.LensIdRef[Person]()
person := &Person{Name: "Alice", Age: 30}
same := idLens.Get(person) // Returns person pointer
replaced := idLens.Set(&Person{Name: "Bob", Age: 25})(person)
// person.Name is still "Alice", replaced is a new pointer
func MakeLens ¶
MakeLens creates a Lens based on a getter and a setter F.
The setter must create a (shallow) copy of the data structure. This happens automatically when the data is passed by value. For pointer-based structures, use MakeLensRef instead. For other reference types (slices, maps), ensure the setter creates a copy.
Type Parameters:
- GET: Getter function type (S → A)
- SET: Setter function type (S, A → S)
- S: Source structure type
- A: Focus/field type
Parameters:
- get: Function to extract value A from structure S
- set: Function to update value A in structure S, returning a new S
Returns:
- A Lens[S, A] that can get and set values immutably
Example:
type Person struct {
Name string
Age int
}
nameLens := lens.MakeLens(
func(p Person) string { return p.Name },
func(p Person, name string) Person {
p.Name = name
return p
},
)
person := Person{Name: "Alice", Age: 30}
name := nameLens.Get(person) // "Alice"
updated := nameLens.Set("Bob")(person) // Person{Name: "Bob", Age: 30}
func MakeLensCurried ¶
func MakeLensCurried[GET ~func(S) A, SET ~func(A) Endomorphism[S], S, A any](get GET, set SET) Lens[S, A]
MakeLensCurried creates a Lens with a curried setter F.
This is similar to MakeLens but accepts a curried setter (A → S → S) instead of an uncurried one (S, A → S). The curried form is more composable in functional pipelines.
The setter must create a (shallow) copy of the data structure. This happens automatically when the data is passed by value. For pointer-based structures, use MakeLensRefCurried.
Type Parameters:
- GET: Getter function type (S → A)
- SET: Curried setter function type (A → S → S)
- S: Source structure type
- A: Focus/field type
Parameters:
- get: Function to extract value A from structure S
- set: Curried function to update value A in structure S
Returns:
- A Lens[S, A] that can get and set values immutably
Example:
nameLens := lens.MakeLensCurried(
func(p Person) string { return p.Name },
func(name string) func(Person) Person {
return func(p Person) Person {
p.Name = name
return p
}
},
)
func MakeLensCurriedRefWithName ¶
func MakeLensCurriedRefWithName[GET ~func(*S) A, SET ~func(A) Endomorphism[*S], S, A any](get GET, set SET, name string) Lens[*S, A]
MakeLensCurriedRefWithName creates a Lens for pointer-based structures with a curried setter and a custom name.
This is the named variant of MakeLensCurriedRefWithName combined with automatic copy-on-write semantics for pointer receivers. The setter does not need to create a copy manually; the copy is applied by the wrapped curried setter produced by setCopyCurried. The name is used in String, Format, and LogValue for debugging and structured logging.
Type Parameters:
- GET: Getter function type (*S → A)
- SET: Curried setter function type (A → *S → *S)
- S: Source structure type (will be used as *S)
- A: Focus/field type
Parameters:
- get: Function to extract value A from pointer *S
- set: Curried function to update value A in pointer *S (copying handled automatically)
- name: A descriptive name for the lens (used in String() and Format())
Returns:
- A Lens[*S, A] with the specified name
func MakeLensCurriedWithName ¶
func MakeLensCurriedWithName[GET ~func(S) A, SET ~func(A) Endomorphism[S], S, A any](get GET, set SET, name string) Lens[S, A]
MakeLensCurriedWithName creates a Lens with a curried setter and a custom name.
This combines the benefits of MakeLensCurried (curried setter for better composition) with MakeLensWithName (custom name for debugging). The name is useful for debugging complex lens compositions and understanding which lens is being used in error messages or logs.
The setter must create a (shallow) copy of the data structure. This happens automatically when the data is passed by value. For pointer-based structures, use MakeLensRefCurried.
Type Parameters:
- GET: Getter function type (S → A)
- SET: Curried setter function type (A → S → S)
- S: Source structure type
- A: Focus/field type
Parameters:
- get: Function to extract value A from structure S
- set: Curried function to update value A in structure S
- name: A descriptive name for the lens (used in String() and Format())
Returns:
- A Lens[S, A] with the specified name
Example:
type Person struct {
Name string
Age int
}
nameLens := lens.MakeLensCurriedWithName(
func(p Person) string { return p.Name },
func(name string) func(Person) Person {
return func(p Person) Person {
p.Name = name
return p
}
},
"Person.Name",
)
fmt.Printf("Using lens: %s\n", nameLens) // Prints: "Using lens: Person.Name"
func MakeLensRef ¶
MakeLensRef creates a Lens for pointer-based structures.
Unlike MakeLens, the setter does not need to create a copy manually. This function automatically wraps the setter to create a shallow copy of the pointed-to value before modification, ensuring immutability.
This lens assumes that property A always exists in structure S (i.e., it's not optional).
Type Parameters:
- GET: Getter function type (*S → A)
- SET: Setter function type (*S, A → *S)
- S: Source structure type (will be used as *S)
- A: Focus/field type
Parameters:
- get: Function to extract value A from pointer *S
- set: Function to update value A in pointer *S (copying handled automatically)
Returns:
- A Lens[*S, A] that can get and set values immutably on pointers
Example:
type Person struct {
Name string
Age int
}
nameLens := lens.MakeLensRef(
func(p *Person) string { return p.Name },
func(p *Person, name string) *Person {
p.Name = name // No manual copy needed
return p
},
)
person := &Person{Name: "Alice", Age: 30}
updated := nameLens.Set("Bob")(person)
// person.Name is still "Alice", updated is a new pointer with Name "Bob"
func MakeLensRefCurried ¶
func MakeLensRefCurried[S, A any](get func(*S) A, set func(A) Endomorphism[*S]) Lens[*S, A]
MakeLensRefCurried creates a Lens for pointer-based structures with a curried setter.
This combines the benefits of MakeLensRef (automatic copying) with MakeLensCurried (curried setter for better composition). The setter does not need to create a copy manually; this function automatically wraps it to ensure immutability.
This lens assumes that property A always exists in structure S (i.e., it's not optional).
Type Parameters:
- S: Source structure type (will be used as *S)
- A: Focus/field type
Parameters:
- get: Function to extract value A from pointer *S
- set: Curried function to update value A in pointer *S (copying handled automatically)
Returns:
- A Lens[*S, A] that can get and set values immutably on pointers
Example:
nameLens := lens.MakeLensRefCurried(
func(p *Person) string { return p.Name },
func(name string) func(*Person) *Person {
return func(p *Person) *Person {
p.Name = name // No manual copy needed
return p
}
},
)
func MakeLensRefCurriedWithName ¶
func MakeLensRefCurriedWithName[S, A any](get func(*S) A, set func(A) Endomorphism[*S], name string) Lens[*S, A]
MakeLensRefCurriedWithName creates a Lens for pointer-based structures with a curried setter and custom name.
This combines the benefits of MakeLensRefCurried (automatic copying with curried setter) with MakeLensWithName (custom name for debugging). The setter does not need to create a copy manually; this function automatically wraps it to ensure immutability. The curried form is more composable in functional pipelines, and the name is useful for debugging.
This lens assumes that property A always exists in structure S (i.e., it's not optional).
Type Parameters:
- S: Source structure type (will be used as *S)
- A: Focus/field type
Parameters:
- get: Function to extract value A from pointer *S
- set: Curried function to update value A in pointer *S (copying handled automatically)
- name: A descriptive name for the lens (used in String() and Format())
Returns:
- A Lens[*S, A] with the specified name
Example:
type Person struct {
Name string
Age int
}
nameLens := lens.MakeLensRefCurriedWithName(
func(p *Person) string { return p.Name },
func(name string) func(*Person) *Person {
return func(p *Person) *Person {
p.Name = name // No manual copy needed
return p
}
},
"Person.Name",
)
person := &Person{Name: "Alice", Age: 30}
fmt.Printf("Using lens: %s\n", nameLens) // Prints: "Using lens: Person.Name"
updated := nameLens.Set("Bob")(person)
// person.Name is still "Alice", updated is a new pointer with Name "Bob"
func MakeLensRefWithName ¶
func MakeLensRefWithName[GET ~func(*S) A, SET func(*S, A) *S, S, A any](get GET, set SET, name string) Lens[*S, A]
MakeLensRefWithName creates a Lens for pointer-based structures with a custom name.
This combines MakeLensRef (automatic copying for pointer structures) with MakeLensWithName (custom name for debugging). The setter does not need to create a copy manually; this function automatically wraps it to ensure immutability. The name is useful for debugging complex lens compositions and understanding which lens is being used in error messages or logs.
This lens assumes that property A always exists in structure S (i.e., it's not optional).
Type Parameters:
- GET: Getter function type (*S → A)
- SET: Setter function type (*S, A → *S)
- S: Source structure type (will be used as *S)
- A: Focus/field type
Parameters:
- get: Function to extract value A from pointer *S
- set: Function to update value A in pointer *S (copying handled automatically)
- name: A descriptive name for the lens (used in String() and Format())
Returns:
- A Lens[*S, A] with the specified name
Example:
type Person struct {
Name string
Age int
}
nameLens := lens.MakeLensRefWithName(
func(p *Person) string { return p.Name },
func(p *Person, name string) *Person {
p.Name = name // No manual copy needed
return p
},
"Person.Name",
)
person := &Person{Name: "Alice", Age: 30}
fmt.Printf("Using lens: %s\n", nameLens) // Prints: "Using lens: Person.Name"
updated := nameLens.Set("Bob")(person)
// person.Name is still "Alice", updated is a new pointer with Name "Bob"
func MakeLensStrict ¶
func MakeLensStrict[GET ~func(*S) A, SET func(*S, A) *S, S any, A comparable](get GET, set SET) Lens[*S, A]
MakeLensStrict creates a Lens for pointer-based structures with strict equality optimization.
This is a convenience function that combines MakeLensWithEq with strict equality comparison (==). It's suitable for comparable types (primitives, strings, pointers, etc.) and provides the same optimization as MakeLensWithEq: if the new value equals the current value, the original pointer is returned unchanged instead of creating a copy.
The setter does not need to create a copy manually; this function automatically wraps it to ensure immutability when changes are made.
This lens assumes that property A always exists in structure S (i.e., it's not optional).
Type Parameters:
- GET: Getter function type (*S → A)
- SET: Setter function type (*S, A → *S)
- S: Source structure type (will be used as *S)
- A: Focus/field type (must be comparable)
Parameters:
- get: Function to extract value A from pointer *S
- set: Function to update value A in pointer *S (copying handled automatically)
Returns:
- A Lens[*S, A] that can get and set values immutably on pointers with strict equality optimization
Example:
type Person struct {
Name string
Age int
}
// Using MakeLensStrict for a string field (comparable type)
nameLens := lens.MakeLensStrict(
func(p *Person) string { return p.Name },
func(p *Person, name string) *Person {
p.Name = name // No manual copy needed
return p
},
)
person := &Person{Name: "Alice", Age: 30}
// Setting the same value returns the original pointer (no copy)
same := nameLens.Set("Alice")(person)
// same == person (same pointer)
// Setting a different value creates a new copy
updated := nameLens.Set("Bob")(person)
// person.Name is still "Alice", updated is a new pointer with Name "Bob"
func MakeLensStrictWithName ¶
func MakeLensStrictWithName[GET ~func(*S) A, SET func(*S, A) *S, S any, A comparable](get GET, set SET, name string) Lens[*S, A]
MakeLensStrictWithName creates a Lens for pointer-based structures with strict equality optimization and a custom name.
This combines MakeLensStrict (strict equality optimization using ==) with MakeLensWithName (custom name for debugging). It's a convenience function suitable for comparable types (primitives, strings, pointers, etc.). If the new value equals the current value, the original pointer is returned unchanged instead of creating a copy. The name is useful for debugging.
The setter does not need to create a copy manually; this function automatically wraps it to ensure immutability when changes are made.
This lens assumes that property A always exists in structure S (i.e., it's not optional).
Type Parameters:
- GET: Getter function type (*S → A)
- SET: Setter function type (*S, A → *S)
- S: Source structure type (will be used as *S)
- A: Focus/field type (must be comparable)
Parameters:
- get: Function to extract value A from pointer *S
- set: Function to update value A in pointer *S (copying handled automatically)
- name: A descriptive name for the lens (used in String() and Format())
Returns:
- A Lens[*S, A] with strict equality optimization and the specified name
Example:
type Person struct {
Name string
Age int
}
// Using MakeLensStrictWithName for a string field (comparable type)
nameLens := lens.MakeLensStrictWithName(
func(p *Person) string { return p.Name },
func(p *Person, name string) *Person {
p.Name = name // No manual copy needed
return p
},
"Person.Name",
)
person := &Person{Name: "Alice", Age: 30}
fmt.Printf("Using lens: %s\n", nameLens) // Prints: "Using lens: Person.Name"
// Setting the same value returns the original pointer (no copy)
same := nameLens.Set("Alice")(person) // same == person
// Setting a different value creates a new copy
updated := nameLens.Set("Bob")(person) // person.Name still "Alice"
func MakeLensWithEq ¶
func MakeLensWithEq[GET ~func(*S) A, SET func(*S, A) *S, S, A any](pred EQ.Eq[A], get GET, set SET) Lens[*S, A]
MakeLensWithEq creates a Lens for pointer-based structures with equality optimization.
This is similar to MakeLensRef but includes an optimization: if the new value equals the current value (according to the provided Eq predicate), the original pointer is returned unchanged instead of creating a copy. This can improve performance and reduce allocations when setting values that don't actually change the structure.
The setter does not need to create a copy manually; this function automatically wraps it to ensure immutability when changes are made.
This lens assumes that property A always exists in structure S (i.e., it's not optional).
Type Parameters:
- GET: Getter function type (*S → A)
- SET: Setter function type (*S, A → *S)
- S: Source structure type (will be used as *S)
- A: Focus/field type
Parameters:
- pred: Equality predicate to compare values of type A
- get: Function to extract value A from pointer *S
- set: Function to update value A in pointer *S (copying handled automatically)
Returns:
- A Lens[*S, A] that can get and set values immutably on pointers with equality optimization
Example:
type Person struct {
Name string
Age int
}
nameLens := lens.MakeLensWithEq(
eq.FromStrictEquals[string](),
func(p *Person) string { return p.Name },
func(p *Person, name string) *Person {
p.Name = name // No manual copy needed
return p
},
)
person := &Person{Name: "Alice", Age: 30}
// Setting the same value returns the original pointer (no copy)
same := nameLens.Set("Alice")(person)
// same == person (same pointer)
// Setting a different value creates a new copy
updated := nameLens.Set("Bob")(person)
// person.Name is still "Alice", updated is a new pointer with Name "Bob"
func MakeLensWithEqWithName ¶
func MakeLensWithEqWithName[GET ~func(*S) A, SET func(*S, A) *S, S, A any](pred EQ.Eq[A], get GET, set SET, name string) Lens[*S, A]
MakeLensWithEqWithName creates a Lens for pointer-based structures with equality optimization and a custom name.
This combines MakeLensWithEq (equality optimization) with MakeLensWithName (custom name for debugging). If the new value equals the current value (according to the provided Eq predicate), the original pointer is returned unchanged instead of creating a copy. The name is useful for debugging complex lens compositions.
The setter does not need to create a copy manually; this function automatically wraps it to ensure immutability when changes are made.
This lens assumes that property A always exists in structure S (i.e., it's not optional).
Type Parameters:
- GET: Getter function type (*S → A)
- SET: Setter function type (*S, A → *S)
- S: Source structure type (will be used as *S)
- A: Focus/field type
Parameters:
- pred: Equality predicate to compare values of type A
- get: Function to extract value A from pointer *S
- set: Function to update value A in pointer *S (copying handled automatically)
- name: A descriptive name for the lens (used in String() and Format())
Returns:
- A Lens[*S, A] with equality optimization and the specified name
Example:
type Person struct {
Name string
Age int
}
nameLens := lens.MakeLensWithEqWithName(
eq.FromStrictEquals[string](),
func(p *Person) string { return p.Name },
func(p *Person, name string) *Person {
p.Name = name // No manual copy needed
return p
},
"Person.Name",
)
person := &Person{Name: "Alice", Age: 30}
fmt.Printf("Using lens: %s\n", nameLens) // Prints: "Using lens: Person.Name"
// Setting the same value returns the original pointer (no copy)
same := nameLens.Set("Alice")(person) // same == person
// Setting a different value creates a new copy
updated := nameLens.Set("Bob")(person) // person.Name still "Alice"
func MakeLensWithName ¶
func MakeLensWithName[GET ~func(S) A, SET ~func(S, A) S, S, A any](get GET, set SET, name string) Lens[S, A]
MakeLensWithName creates a Lens with a custom name for debugging and logging.
This is identical to MakeLens but allows you to specify a name that will be used when the lens is printed or formatted. The name is useful for debugging complex lens compositions and understanding which lens is being used in error messages or logs.
The setter must create a (shallow) copy of the data structure. This happens automatically when the data is passed by value. For pointer-based structures, use MakeLensRef instead.
Type Parameters:
- GET: Getter function type (S → A)
- SET: Setter function type (S, A → S)
- S: Source structure type
- A: Focus/field type
Parameters:
- get: Function to extract value A from structure S
- set: Function to update value A in structure S, returning a new S
- name: A descriptive name for the lens (used in String() and Format())
Returns:
- A Lens[S, A] with the specified name
Example:
type Person struct {
Name string
Age int
}
nameLens := lens.MakeLensWithName(
func(p Person) string { return p.Name },
func(p Person, name string) Person {
p.Name = name
return p
},
"Person.Name",
)
fmt.Printf("Using lens: %s\n", nameLens) // Prints: "Using lens: Person.Name"
func (Lens[S, A]) Compose ¶
Compose returns a new lens that focuses deeper into the structure by chaining this lens (S → A) with an inner lens (A → B), producing a composed lens (S → B).
This is the method-receiver form of the package-level IsoComposeIso function, available only on Go 1.27 and later because Go did not support type parameters on methods before that version. On earlier toolchains, use the equivalent free function instead:
// method form (go1.27+) personStreetLens := addressLens.Compose(streetLens) // free-function form (all versions) personStreetLens := lens.Compose[Person](streetLens)(addressLens)
The composed lens satisfies all three lens laws whenever both constituent lenses individually satisfy them.
Type Parameters:
- B: the focus type of the inner lens and of the resulting lens
Parameters:
- ab: the inner lens from A to B
Returns:
- Lens[S, B]: a new lens from S directly to B
See Also:
- Compose: the equivalent package-level function
func (Lens[S, A]) ComposeIso ¶
ComposeIso returns a new lens that focuses on a value of type B by composing this lens (S → A) with an isomorphism (A ↔ B), producing a lens (S → B).
This is the method-receiver form of the package-level LensComposeIso function, available only on Go 1.27 and later because Go did not support type parameters on methods before that version. On earlier toolchains use the equivalent free function:
// method form (go1.27+) fahrenheitLens := readingLens.ComposeIso(celsiusToFahrenheit) // free-function form (all versions) fahrenheitLens := LensComposeIso[Thermometer](celsiusToFahrenheit)(readingLens)
The resulting lens satisfies all three lens laws whenever both the outer lens and the isomorphism individually satisfy them.
Type Parameters:
- B: the focus type of the resulting lens — the target type of the isomorphism
Parameters:
- ab: the isomorphism from A to B
Returns:
- Lens[S, B]: a new lens from S directly to B
See Also:
- Compose: the equivalent method for composing with a Lens[A, B] instead of an Iso[A, B]
- LensComposeIso: the equivalent package-level function
func (Lens[S, A]) ComposePrism ¶ added in v2.3.122
ComposePrism returns a new Optional that focuses on a value of type B by composing this lens (S → A) with a prism (A → B), producing an Optional (S → B).
This is the method-receiver form of the package-level LensComposePrism function, available only on Go 1.27 and later because Go did not support type parameters on methods before that version. On earlier toolchains use the equivalent free function:
// method form (go1.27+) opt := myLens.ComposePrism(myPrism) // free-function form (all versions) opt := LensComposePrism[S](myPrism)(myLens)
The result is an Optional because the prism may not match the focused value. GetOption applies the lens first, then the prism; Set updates the structure only when GetOption would return Some — matching the Optional no-op law.
The composed Optional satisfies the standard Optional laws (GetSet, SetGet, SetSet) whenever the constituent lens and prism individually satisfy the lens and prism laws respectively.
Type Parameters:
- B: the focus type of the prism and of the resulting Optional
Parameters:
- ab: the prism from A to B
Returns:
- Optional[S, B]: a new Optional from S directly to B
See Also:
- Compose: method for composing with a Lens[A, B] instead of a Prism[A, B]
- ComposeIso: method for composing with an Iso[A, B] instead of a Prism[A, B]
- LensComposePrism: the equivalent package-level function
func (Lens) Format ¶
Format implements fmt.Formatter.
Supports all standard format verbs:
- %s, %v, %+v, %q, and all other verbs: uses the String() representation (the lens name)
The exact output format is not a stable contract and may change across versions.
func (Lens) LogValue ¶
LogValue implements slog.LogValuer.
Returns a slog.Value that represents the lens for structured logging. The lens name is logged as a string value. The exact structure of the returned slog.Value is not a stable contract and may change across versions.
func (Lens[S, A]) Modify ¶
func (la Lens[S, A]) Modify(f Endomorphism[A]) Endomorphism[S]
Modify applies a transformation function to the value focused by the lens.
This method transforms the focused value within a structure by applying an endomorphism (a function from A to A) and returns a new structure with the transformed value. The transformation is applied by first getting the current value, applying the function, and then setting the result back into the structure.
Type Parameters:
- S: The structure type containing the focused value
- A: The type of the focused value
Parameters:
- f: An endomorphism that transforms the focused value
Returns:
- An endomorphism on S that applies the transformation
Example:
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 },
)
person := Person{Name: "Alice", Age: 30}
incrementAge := ageLens.Modify(func(age int) int { return age + 1 })
older := incrementAge(person)
// older.Age == 31, person.Age == 30 (original unchanged)
See Also:
- Modify: Package-level function for use in pipelines
- Set: For setting a constant value instead of transforming
type LensKleisli ¶
LensKleisli represents a function that takes a value of type A and returns a Lens[S, B]. This is useful for composing lenses in a monadic style, allowing for dynamic lens creation based on input values.
Type Parameters:
- S: The source/structure type
- A: The input type
- B: The focus type of the resulting lens
type LensOperator ¶
type LensOperator[S, A, B any] = LensKleisli[S, Lens[S, A], B]
LensOperator is a specialized Kleisli that takes a Lens[S, A] and returns a Lens[S, B]. This enables lens transformations and compositions where one lens is used to derive another.
Type Parameters:
- S: The source/structure type
- A: The focus type of the input lens
- B: The focus type of the resulting lens
func LensComposeIso ¶
LensComposeIso converts a Lens to a property of `A` into a lens to a property of type `B` the transformation is done via an ISO
func LensComposeLens ¶
LensComposeLens combines two lenses to focus on a deeply nested field.
Given a lens from S to A and a lens from A to B, LensComposeLens creates a lens from S to B. This allows you to navigate through nested structures in a composable way.
The composition follows the mathematical property: (sa ∘ ab).Get = ab.Get ∘ sa.Get
Type Parameters:
- S: Outer structure type
- A: Intermediate structure type
- B: Inner focus type
Parameters:
- ab: Lens from A to B (inner lens)
Returns:
- A function that takes a Lens[S, A] and returns a Lens[S, B]
Example:
type Address struct {
Street string
City string
}
type Person struct {
Name string
Address Address
}
addressLens := lens.MakeLens(
func(p Person) Address { return p.Address },
func(p Person, a Address) Person { p.Address = a; return p },
)
streetLens := lens.MakeLens(
func(a Address) string { return a.Street },
func(a Address, s string) Address { a.Street = s; return a },
)
// LensComposeLens to access street directly from person
personStreetLens := F.Pipe1(addressLens, lens.LensComposeLens[Person](streetLens))
person := Person{Name: "Alice", Address: Address{Street: "Main St"}}
street := personStreetLens.Get(person) // "Main St"
updated := personStreetLens.Set("Oak Ave")(person)
func LensComposeLensRef
deprecated
LensComposeLensRef combines two lenses for pointer-based structures.
Deprecated: LensComposeLensRef is not needed. When the outer lens is already a pointer lens (Lens[*S, A], created with MakeLensRef or MakeLensRefCurried), its Set implementation already copies *S before writing. The copy that LensComposeLensRef adds via MakeLensRefCurriedWithName is therefore redundant — the composed setter calls the outer lens's Set, which copies, so the original pointer is never mutated.
Use LensComposeLens[*S] instead:
// Before personStreetLens := F.Pipe1(addressLens, lens.LensComposeLensRef[Person](streetLens)) // After — identical behaviour, no extra copy personStreetLens := F.Pipe1(addressLens, lens.Compose[*Person](streetLens))
Type Parameters:
- S: Outer structure type (will be used as *S)
- A: Intermediate structure type
- B: Inner focus type
Parameters:
- ab: Lens from A to B (inner lens)
Returns:
- A function that takes a Lens[*S, A] and returns a Lens[*S, B]
func LensIMap ¶
LensIMap transforms the focus type of a lens using an isomorphism.
An isomorphism is a pair of functions (A → B, B → A) that are inverses of each other. LensIMap allows you to work with a lens in a different but equivalent type. This is useful for unit conversions, encoding/decoding, or any bidirectional transformation.
Type Parameters:
- E: Structure type
- AB: Forward transformation function type (A → B)
- BA: Backward transformation function type (B → A)
- A: Original focus type
- B: Transformed focus type
Parameters:
- ab: Forward transformation (A → B)
- ba: Backward transformation (B → A)
Returns:
- A function that takes a Lens[E, A] and returns a Lens[E, B]
Example:
type Celsius float64
type Fahrenheit float64
celsiusToFahrenheit := func(c Celsius) Fahrenheit {
return Fahrenheit(c*9/5 + 32)
}
fahrenheitToCelsius := func(f Fahrenheit) Celsius {
return Celsius((f - 32) * 5 / 9)
}
type Weather struct {
Temperature Celsius
}
tempCelsiusLens := lens.MakeLens(
func(w Weather) Celsius { return w.Temperature },
func(w Weather, t Celsius) Weather { w.Temperature = t; return w },
)
// Create a lens that works with Fahrenheit
tempFahrenheitLens := F.Pipe1(
tempCelsiusLens,
lens.LensIMap[Weather](celsiusToFahrenheit, fahrenheitToCelsius),
)
weather := Weather{Temperature: 20} // 20°C
tempF := tempFahrenheitLens.Get(weather) // 68°F
updated := tempFahrenheitLens.Set(86)(weather) // Set to 86°F (30°C)
type Option ¶
type Option[A any] struct { // contains filtered or unexported fields }
Option defines a data structure that logically holds a value or not. It represents an optional value: every Option is either Some and contains a value, or None, and does not contain a value.
Option is commonly used to represent the result of operations that may fail, as an alternative to returning nil pointers or using error values.
Example:
var opt Option[int] = Some(42) // Contains a value var opt Option[int] = None[int]() // Contains no value
func EitherToOption ¶ added in v2.3.122
EitherToOption converts an Either to an Option, discarding the Left value.
Example:
result := either.EitherToOption(either.EitherRight[error](42)) // Some(42)
result := either.EitherToOption(either.EitherLeft[int](errors.New("err"))) // None
func OptionFlatten ¶ added in v2.3.120
OptionFlatten removes one level of nesting from a nested Option.
Example:
nested := OptionSome(OptionSome(42)) result := OptionFlatten(nested) // OptionSome(42) nested := OptionSome(OptionNone[int]()) result := OptionFlatten(nested) // None
func OptionFromNillable
deprecated
added in
v2.3.120
OptionFromNillable converts a pointer to an Option wrapping the pointer itself. Returns OptionSome(*A) when the pointer is non-nil, None otherwise.
Deprecated: Use FromNillable2 instead. FromNillable2 unwraps the pointed-to value into an Option[A], which is the more useful form: it avoids carrying a *A inside the Option and composes naturally with the rest of the Option API.
func OptionFromNillable2 ¶ added in v2.3.120
OptionFromNillable2 converts a pointer to an Option of the pointed-to value. Returns OptionSome(value) when the pointer is non-nil (dereferencing it), None otherwise. This is the preferred alternative to FromNillable because the resulting Option[A] composes naturally with Map, Chain, and the rest of the Option API without having to deal with an intermediate pointer inside the Option.
Type Parameters:
- A: the type that the pointer points to
Parameters:
- a: a pointer to a value of type A; may be nil
Returns:
- OptionSome(*a) when a is non-nil
- None when a is nil
See Also:
- ToNillable2: the inverse — converts Option[A] back to *A
- FromNillable: the older variant that wraps the pointer itself as Option[*A]
func OptionInstanceOf ¶ added in v2.3.120
OptionInstanceOf 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 := OptionInstanceOf[int](x) // Some(42) var y any = "hello" result := OptionInstanceOf[int](y) // None (wrong type)
func OptionMonadAlt ¶ added in v2.3.120
MonadAlt returns the first Option if it's Some, otherwise returns the alternative. This is the monadic form of the Alt operation.
Example:
result := MonadAlt(OptionSome(5), func() Option[int] { return OptionSome(10) }) // OptionSome(5)
result := MonadAlt(OptionNone[int](), func() Option[int] { return OptionSome(10) }) // OptionSome(10)
func OptionMonadAp ¶ added in v2.3.120
OptionMonadAp applies a function wrapped in an Option to a value wrapped in an Option. If either the function or the value is None, returns None. This is the monadic form of the applicative functor.
Example:
fab := OptionSome(N.Mul(2)) fa := OptionSome(5) result := OptionMonadAp(fab, fa) // OptionSome(10)
func OptionMonadChain ¶ added in v2.3.120
func OptionMonadChain[A, B any](fa Option[A], f OptionKleisli[A, B]) Option[B]
OptionMonadChain applies a function that returns an Option to the value inside an Option. This is the monadic bind operation. If the input is None, returns None.
Example:
fa := OptionSome(5) result := OptionMonadChain(fa, F.Flow2(Predicate(N.MoreThan(0)), Map(N.Mul(2)))) // OptionSome(10)
func OptionMonadChainFirst ¶ added in v2.3.120
func OptionMonadChainFirst[A, B any](ma Option[A], f OptionKleisli[A, B]) Option[A]
OptionMonadChainFirst applies a function that returns an Option but keeps the original value. If either operation results in None, returns None.
Example:
result := OptionMonadChainFirst(OptionSome(5), func(x int) Option[string] {
return OptionSome(fmt.Sprintf("%d", x))
}) // OptionSome(5) - original value is kept
func OptionMonadChainTo ¶ added in v2.3.120
OptionMonadChainTo ignores the first Option and returns the second Option. Useful for sequencing operations where the first result is not needed.
Example:
result := OptionMonadChainTo(OptionSome(5), OptionSome("hello")) // OptionSome("hello")
func OptionMonadFlap ¶ added in v2.3.120
OptionMonadFlap applies a value to a function wrapped in an Option. This is the monadic form of Flap.
Example:
fab := OptionSome(N.Mul(2)) result := OptionMonadFlap(fab, 5) // OptionSome(10)
func OptionMonadMap ¶ added in v2.3.120
OptionMonadMap applies a function to the value inside an Option. If the Option is None, returns None. This is the monadic form of Map.
Example:
fa := OptionSome(5) result := OptionMonadMap(fa, N.Mul(2)) // OptionSome(10)
func OptionMonadMapTo ¶ added in v2.3.120
OptionMonadMapTo replaces the value inside an Option with a constant value. If the Option is None, returns None. This is the monadic form of MapTo.
Example:
fa := OptionSome(5)
result := OptionMonadMapTo(fa, "hello") // OptionSome("hello")
func OptionMonadSequence2 ¶ added in v2.3.120
func OptionMonadSequence2[T1, T2, R any](o1 Option[T1], o2 Option[T2], f func(T1, T2) Option[R]) Option[R]
OptionMonadSequence2 sequences two Options and applies a function to their values. Returns None if either Option is None.
Example:
result := OptionMonadSequence2(OptionSome(2), OptionSome(3), func(a, b int) Option[int] {
return OptionSome(a + b)
}) // OptionSome(5)
func OptionNone ¶ added in v2.3.120
OptionNone creates an Option that contains no value.
Example:
opt := OptionNone[int]() // Empty Option of type int opt := OptionNone[string]() // Empty Option of type string
func OptionOf ¶ added in v2.3.120
OptionOf creates an Option that contains a value. This is an alias for OptionSome and is used in monadic contexts.
Example:
opt := OptionOf(42) // Option containing 42
func OptionSequenceArray ¶ added in v2.3.120
OptionSequenceArray converts an array of Options into an Option of an array. Returns Some containing all values if all Options are Some, None if any is None.
Example:
result := OptionSequenceArray(A.From(OptionSome(1), OptionSome(2), OptionSome(3))) // OptionSome([1, 2, 3]) result := OptionSequenceArray(A.From(OptionSome(1), OptionNone[int](), OptionSome(3))) // None
func OptionSequenceArrayG ¶ added in v2.3.120
OptionSequenceArrayG converts an array of Options into an Option of an array. Returns Some containing all values if all Options are Some, None if any is None. This is the generic version that works with custom slice types.
Example:
type MySlice []int
result := OptionSequenceArrayG[MySlice](A.From(OptionSome(1), OptionSome(2))) // OptionSome(MySlice{1, 2})
result := OptionSequenceArrayG[MySlice](A.From(OptionSome(1), OptionNone[int]())) // None
func OptionSome ¶ added in v2.3.120
OptionSome creates an Option that contains a value.
Example:
opt := OptionSome(42) // Option containing 42
opt := OptionSome("hello") // Option containing "hello"
func OptionToAny ¶ added in v2.3.120
OptionToAny converts a value of any type to Option[any]. This always succeeds and returns Some containing the value as any.
Example:
result := OptionToAny(42) // Some(any(42))
result := OptionToAny("hello") // Some(any("hello"))
func OptionTryCatch ¶ added in v2.3.120
OptionTryCatch executes a function that may return an error and converts the result to an Option. Returns OptionSome(value) if no error occurred, None if an error occurred.
Example:
result := OptionTryCatch(func() (int, error) {
return strconv.Atoi("42")
}) // OptionSome(42)
func OptionZero ¶ added in v2.3.120
OptionZero returns the zero value of an Option, which is None. This function is useful as an identity element in monoid operations or for creating an empty Option.
The zero value for Option[A] is always None, representing the absence of a value. This is consistent with the Option monad's semantics where None represents "no value" and Some represents "a value".
Important: OptionZero() returns the same value as the default initialization of Option[A]. When you declare `var o Option[A]` without initialization, it has the same value as OptionZero[A]().
Note: Unlike other types where zero might be a default value, Option's zero is explicitly the absence of any value (None), not Some with a zero value.
Example:
// OptionZero Option of any type is always None o1 := option.OptionZero[int]() // None o2 := option.OptionZero[string]() // None o3 := option.OptionZero[*int]() // None // OptionZero equals default initialization var defaultInit Option[int] zero := option.OptionZero[int]() assert.Equal(t, defaultInit, zero) // true // Verify it's None o := option.OptionZero[int]() assert.True(t, option.IsNone(o)) // true assert.False(t, option.IsOptionSome(o)) // false // Different from Some with zero value someZero := option.OptionSome(0) // OptionSome(0) zero := option.OptionZero[int]() // None assert.NotEqual(t, someZero, zero) // they are different
func (Option[A]) Format ¶ added in v2.3.120
Format implements fmt.Formatter for Option. Supports all standard format verbs:
- %s, %v, %+v, %q, and all other verbs: uses String() representation
The exact output format is not a stable contract and may change across versions.
func (Option[A]) MarshalJSON ¶ added in v2.3.120
func (Option[A]) String ¶ added in v2.3.120
String implements fmt.Stringer for Option. Returns a human-readable string representation intended for debugging and logging. The exact format, including any package-path prefix that appears in %T output, is not a stable contract and may change across versions.
Example:
Some(42).String() // "Some[int](42)" None[int]().String() // "None[int]"
func (*Option[A]) UnmarshalJSON ¶ added in v2.3.120
type OptionKleisli ¶ added in v2.3.120
func OptionFromNonZero ¶ added in v2.3.120
func OptionFromNonZero[A comparable]() OptionKleisli[A, A]
func OptionFromPredicate ¶ added in v2.3.120
func OptionFromPredicate[A any](pred Predicate[A]) OptionKleisli[A, A]
OptionFromPredicate 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.
Example:
isPositive := OptionFromPredicate(N.MoreThan(0)) result := isPositive(5) // OptionSome(5) result := isPositive(-1) // None
func OptionFromValidation ¶ added in v2.3.120
func OptionFromValidation[A, B any](f func(A) (B, bool)) OptionKleisli[A, B]
OptionFromValidation converts a validation function (returning value and bool) to an Option-returning function. This is an alias for Optionize1.
Example:
parseNum := OptionFromValidation(func(s string) (int, bool) {
n, err := strconv.Atoi(s)
return n, err == nil
})
result := parseNum("42") // OptionSome(42)
func OptionFromZero ¶ added in v2.3.120
func OptionFromZero[A comparable]() OptionKleisli[A, A]
func OptionOptionize1 ¶ added in v2.3.120
func OptionOptionize1[F ~func(T0) (R, bool), T0, R any](f F) OptionKleisli[T0, R]
OptionOptionize1 converts a function with 1 parameters returning a tuple of a return value R and a boolean into a function with 1 parameters returning an Option[R]
func OptionTraverseArray ¶ added in v2.3.120
func OptionTraverseArray[A, B any](f OptionKleisli[A, B]) OptionKleisli[[]A, []B]
OptionTraverseArray 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 := F.Flow2(Predicate(N.MoreThan(0)), Map(N.Mul(2)))
result := OptionTraverseArray(validate)([]int{1, 2, 3}) // OptionSome([2, 4, 6])
result := OptionTraverseArray(validate)([]int{1, -1, 3}) // None
func OptionTraverseArrayG ¶ added in v2.3.120
func OptionTraverseArrayG[GA ~[]A, GB ~[]B, A, B any](f OptionKleisli[A, B]) OptionKleisli[GA, GB]
OptionTraverseArrayG 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 OptionNone[int]() }
return OptionSome(n)
}
result := OptionTraverseArrayG[[]string, []int](parse)([]string{"1", "2", "3"}) // OptionSome([1, 2, 3])
result := OptionTraverseArrayG[[]string, []int](parse)([]string{"1", "x", "3"}) // None
func OptionTraverseArrayWithIndex ¶ added in v2.3.120
func OptionTraverseArrayWithIndex[A, B any](f func(int, A) Option[B]) OptionKleisli[[]A, []B]
OptionTraverseArrayWithIndex 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 OptionSome(x) }
return OptionNone[int]()
}
result := OptionTraverseArrayWithIndex(f)([]int{1, 2, 3}) // OptionSome([1, 2, 3])
func OptionTraverseArrayWithIndexG ¶ added in v2.3.120
func OptionTraverseArrayWithIndexG[GA ~[]A, GB ~[]B, A, B any](f func(int, A) Option[B]) OptionKleisli[GA, GB]
OptionTraverseArrayWithIndexG 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 OptionSome(fmt.Sprintf("%d:%s", i, s))
}
result := OptionTraverseArrayWithIndexG[[]string, []string](f)([]string{"a", "b"}) // OptionSome(["0:a", "1:b"])
type OptionKleisliI ¶ added in v2.3.120
type OptionOperator ¶ added in v2.3.120
type OptionOperator[A, B any] = OptionKleisli[Option[A], B]
func OptionAlt ¶ added in v2.3.120
OptionAlt returns a function that provides an alternative Option if the input is None.
Example:
withDefault := OptionAlt(func() Option[int] { return OptionSome(0) })
result := withDefault(OptionSome(5)) // OptionSome(5)
result := withDefault(OptionNone[int]()) // OptionSome(0)
func OptionAp ¶ added in v2.3.120
OptionAp is the curried applicative functor for Option. Returns a function that applies an Option-wrapped function to the given Option value.
Example:
fa := OptionSome(5) applyTo5 := OptionAp[int](fa) fab := OptionSome(N.Mul(2)) result := applyTo5(fab) // OptionSome(10)
func OptionChain ¶ added in v2.3.120
func OptionChain[A, B any](f OptionKleisli[A, B]) OptionOperator[A, B]
OptionChain returns a function that applies an Option-returning function to an Option value. This is the curried form of the monadic bind operation.
Example:
validate := OptionChain(F.Flow2(Predicate(N.MoreThan(0)), Map(N.Mul(2)))) result := validate(OptionSome(5)) // OptionSome(10)
func OptionChainFirst ¶ added in v2.3.120
func OptionChainFirst[A, B any](f OptionKleisli[A, B]) OptionOperator[A, A]
OptionChainFirst returns a function that applies an Option-returning function but keeps the original value.
Example:
logAndKeep := OptionChainFirst(func(x int) Option[string] {
fmt.Println(x)
return OptionSome("logged")
})
result := logAndKeep(OptionSome(5)) // OptionSome(5)
func OptionChainOptionNone ¶ added in v2.3.120
ChainNone is the curried version that sequences a computation on the None (empty) value. Returns a function that applies the provided function when the Option is None, or returns None when the Option is Some.
Note: ChainNone is identical to Alt - both provide the same functionality for providing alternative values when an Option is None.
The naming convention follows the pattern established by ChainLeft in the Either type, where operations on the "error" or "empty" case use the Left/None suffix to distinguish them from operations on the "success" or "present" case (Chain operates on Some values, while ChainNone operates on None values).
This is useful for creating reusable default value providers or transformers that can be composed with other Option operations using pipes or function composition.
Example:
// Create a reusable default provider
provideDefault := option.ChainNone(func() option.Option[int] {
return option.OptionSome(42)
})
// Use in a pipeline
result := F.Pipe1(
option.OptionNone[int](),
provideDefault,
) // OptionSome(42)
// Some values pass through unchanged
result := F.Pipe1(
option.OptionSome(10),
provideDefault,
) // OptionSome(10)
func OptionChainTo ¶ added in v2.3.120
OptionChainTo returns a function that ignores its input Option and returns a fixed Option.
Example:
replaceWith := OptionChainTo(OptionSome("hello"))
result := replaceWith(OptionSome(42)) // OptionSome("hello")
func OptionFilter ¶ added in v2.3.120
func OptionFilter[A any](pred Predicate[A]) OptionOperator[A, A]
OptionFilter keeps the Option if it's Some and the predicate is satisfied, otherwise returns None.
Example:
isPositive := OptionFilter(N.MoreThan(0)) result := isPositive(OptionSome(5)) // OptionSome(5) result := isPositive(OptionSome(-1)) // None result := isPositive(OptionNone[int]()) // None
func OptionFlap ¶ added in v2.3.120
func OptionFlap[B, A any](a A) OptionOperator[func(A) B, B]
OptionFlap returns a function that applies a value to an Option-wrapped function.
Example:
applyFive := OptionFlap[int](5) fab := OptionSome(N.Mul(2)) result := applyFive(fab) // OptionSome(10)
func OptionMap ¶ added in v2.3.120
func OptionMap[A, B any](f func(a A) B) OptionOperator[A, B]
OptionMap returns a function that applies a transformation to the value inside an Option. If the Option is None, returns None.
Example:
double := OptionMap(N.Mul(2)) result := double(OptionSome(5)) // OptionSome(10) result := double(OptionNone[int]()) // None
func OptionMapTo ¶ added in v2.3.120
func OptionMapTo[A, B any](b B) OptionOperator[A, B]
OptionMapTo returns a function that replaces the value inside an Option with a constant.
Example:
replaceWith42 := OptionMapTo[string, int](42)
result := replaceWith42(OptionSome("hello")) // OptionSome(42)
type OptionTraversable ¶ added in v2.3.120
type OptionTraversable[A, B, GA, GB any] = func(OptionKleisli[A, B]) OptionKleisli[GA, GB]
OptionTraversable represents a data structure that can be traversed from left to right, applying an effectful function to each element and collecting the results.
A Traversable takes a Kleisli arrow (a function that returns an Option) and produces another Kleisli arrow that operates on a container of values.
Type Parameters:
- A: The input element type
- B: The output element type
- GA: The input container type (e.g., []A, map[K]A)
- GB: The output container type (e.g., []B, map[K]B)
The Traversable signature:
func(Kleisli[A, B]) Kleisli[GA, GB]
expands to:
func(func(A) Option[B]) func(GA) Option[GB]
This means: given a function that transforms A to Option[B], produce a function that transforms a container of A values into an Option of a container of B values.
Behavior:
- If all transformations succeed (return Some), the result is Some containing the container of all transformed values
- If any transformation fails (returns None), the entire result is None
Common Use Cases:
- Validating and transforming collections where any failure should fail the whole operation
- Parsing collections of strings where all must parse successfully
- Applying optional transformations across data structures
Example:
// Array traversable
traversable := TraversableArray[string, int]()
parse := func(s string) Option[int] {
n, err := strconv.Atoi(s)
if err != nil { return None[int]() }
return Some(n)
}
result := traversable(parse)([]string{"1", "2", "3"}) // Some([1, 2, 3])
result := traversable(parse)([]string{"1", "x", "3"}) // None
See Also:
- TraversableArray: Traversable instance for arrays
- TraverseArray: Direct array traversal function
- TraverseRecord: Traversal for maps/records
func OptionTraversableArray ¶ added in v2.3.120
func OptionTraversableArray[A, B any]() OptionTraversable[A, B, []A, []B]
OptionTraversableArray returns a Traversable instance for arrays. A Traversable represents a data structure that can be traversed from left to right, applying an effectful function to each element and collecting the results.
This function provides a way to obtain the traversal operation for arrays as a first-class value, which is useful when you need to pass the traversal operation as a parameter or compose it with other operations.
Type Parameters:
- A: The input element type
- B: The output element type
Returns:
- Traversable[A, B, []A, []B]: A function that takes a Kleisli arrow and returns another Kleisli arrow that operates on arrays
The returned Traversable has the signature:
func(OptionKleisli[A, B]) OptionKleisli[[]A, []B]
which is equivalent to:
func(func(A) Option[B]) func([]A) Option[[]B]
Example:
// Get the traversable instance
traversable := OptionTraversableArray[string, int]()
// Use it with a parsing function
parse := func(s string) Option[int] {
n, err := strconv.Atoi(s)
if err != nil { return OptionNone[int]() }
return OptionSome(n)
}
result := traversable(parse)([]string{"1", "2", "3"}) // OptionSome([1, 2, 3])
See Also:
- TraverseArray: Direct traversal without obtaining the Traversable instance
- TraverseArrayG: Generic version supporting custom slice types
type Optional ¶
type Optional[S, A any] struct { GetOption func(s S) Option[A] Set func(a A) EM.Endomorphism[S] // contains filtered or unexported fields }
Optional is an optional reference to a subpart of a data type
func LensAsOptional ¶ added in v2.3.122
LensAsOptional converts a Lens into an Optional
func MakeOptional ¶
func MakeOptional[S, A any](get OptionKleisli[S, A], set func(S, A) S) Optional[S, A]
MakeOptional creates an Optional based on a getter and a setter function. Make sure that the setter creates a (shallow) copy of the data. This happens automatically if the data is passed by value. For pointers consider to use `MakeOptionalRef` and for other kinds of data structures that are copied by reference make sure the setter creates the copy.
func MakeOptionalCurried ¶
func MakeOptionalCurried[S, A any](get OptionKleisli[S, A], set func(A) func(S) S) Optional[S, A]
func MakeOptionalCurriedWithName ¶
func MakeOptionalCurriedWithName[S, A any](get OptionKleisli[S, A], set func(A) func(S) S, name string) Optional[S, A]
func MakeOptionalRef ¶
func MakeOptionalRef[S, A any](get OptionKleisli[*S, A], set func(*S, A) *S) Optional[*S, A]
MakeOptionalRef creates an Optional based on a getter and a setter function. The setter passed in does not have to create a shallow copy, the implementation wraps the setter into one that copies the pointer before modifying it
func MakeOptionalRefCurriedWithName ¶
func MakeOptionalRefCurriedWithName[S, A any](get OptionKleisli[*S, A], set func(A) func(*S) *S, name string) Optional[*S, A]
func MakeOptionalRefWithName ¶
func MakeOptionalRefWithName[S, A any](get OptionKleisli[*S, A], set func(*S, A) *S, name string) Optional[*S, A]
func MakeOptionalWithName ¶
func MakeOptionalWithName[S, A any](get OptionKleisli[S, A], set func(S, A) S, name string) Optional[S, A]
func OptionalId ¶
OptionalId returns am optional implementing the identity operation
func OptionalIdRef ¶
Id returns am optional implementing the identity operation
func OptionalSome ¶ added in v2.3.122
OptionalSome creates an Optional that focuses on the OptionalSome variant of an Option within a structure.
Given an Optional[S, Option[A]] that focuses on an Option field, this function returns an Optional[S, A] that focuses directly on the value within OptionalSome.
This is useful when you have a structure containing an Option field and want to work with the value inside OptionalSome without manually unwrapping the Option.
The conversion works by composing the provided optional with a prism that extracts values from OptionalSome. The resulting optional:
- Returns OptionalSome(a) from GetOption only when both the outer optional matches and the inner Option is OptionalSome
- Performs Set only when both conditions are met (no-op otherwise)
The resulting Optional satisfies the three optional laws:
GetSet Law (No-op on None): If GetOption(s) returns None (either because the outer optional doesn't match or the inner Option is None), then Set(a)(s) returns s unchanged.
Formally: GetOption(s) = None => Set(a)(s) = s
SetGet Law (Get what you Set): If GetOption(s) returns OptionalSome(_), then GetOption(Set(a)(s)) returns OptionalSome(a).
Formally: GetOption(s) = OptionalSome(_) => GetOption(Set(a)(s)) = OptionalSome(a)
SetSet Law (Last Set Wins): Set(b)(Set(a)(s)) equals Set(b)(s).
Formally: Set(b)(Set(a)(s)) = Set(b)(s)
Type Parameters:
- S: The structure type
- A: The type of value within the Option
Parameters:
- soa: An optional focusing on an Option[A] field within S
Returns:
- An Optional[S, A] that focuses directly on values within OptionalSome
Example:
type Config struct {
Timeout Option[int]
}
// Create an optional for the Timeout field
timeoutOptional := optional.MakeOptional(
func(c Config) Option[Option[int]] {
return OptionalSome(c.Timeout)
},
func(c Config, opt Option[int]) Config {
c.Timeout = opt
return c
},
)
// Focus on the value within OptionalSome
valueOptional := OptionalSome(timeoutOptional)
// Use the optional
config := Config{Timeout: OptionalSome(30)}
value := valueOptional.GetOption(config) // OptionalSome(30)
updated := valueOptional.Set(60)(config) // Config{Timeout: OptionalSome(60)}
// Set is no-op when inner Option is None (Law 1)
emptyConfig := Config{Timeout: None[int]()}
unchanged := valueOptional.Set(60)(emptyConfig) // emptyConfig (unchanged)
See Also:
- AsOptional: Converts prisms to optionals
- PrismSome: The underlying prism for Option types
- github.com/IBM/fp-go/v2/optics/optional.Compose for composing optionals
func PrismAsOptional ¶ added in v2.3.122
PrismAsOptional converts a Prism into an Optional.
A Prism[S, A] focuses on a specific variant within a sum type S, providing:
- GetOption: Attempts to extract A from S (returns Option[A])
- ReverseGet: Constructs S from A (always succeeds)
An Optional[S, A] focuses on a value that may not exist within S, providing:
- GetOption: Attempts to extract A from S (returns Option[A])
- Set: Updates A within S if it exists (no-op if it doesn't)
The conversion works by:
- Using the prism's GetOption directly as the optional's GetOption
- Implementing Set using the prism's Set operation, which internally uses GetOption to check if the value exists before updating
The resulting Optional satisfies the three optional laws:
GetSet Law (No-op on None): If GetOption(s) returns None, then Set(a)(s) returns s unchanged. This is satisfied because the prism's Set operation checks GetOption and only updates when it returns Some.
Formally: GetOption(s) = None => Set(a)(s) = s
SetGet Law (Get what you Set): If GetOption(s) returns Some(_), then GetOption(Set(a)(s)) returns Some(a). This is satisfied because the prism's Set operation replaces the focused value with the new value when GetOption returns Some.
Formally: GetOption(s) = Some(_) => GetOption(Set(a)(s)) = Some(a)
SetSet Law (Last Set Wins): Set(b)(Set(a)(s)) equals Set(b)(s). This is satisfied because both operations check GetOption and only update when it returns Some, with the prism's Set operation ensuring the last set wins.
Formally: Set(b)(Set(a)(s)) = Set(b)(s)
Type Parameters:
- S: The source type (sum type)
- A: The focus type (variant within the sum type)
Parameters:
- sa: A prism focusing on variant A within sum type S
Returns:
- An Optional[S, A] that focuses on the same variant
Example:
type Result interface{ isResult() }
type Success struct{ Value int }
type Failure struct{ Error string }
// Create a prism for the Success variant
successPrism := prism.MakePrism(
func(r Result) Option[int] {
if s, ok := r.(Success); ok {
return Some(s.Value)
}
return None[int]()
},
func(v int) Result { return Success{Value: v} },
)
// Convert to optional
successOptional := PrismAsOptional(successPrism)
// Use the optional
result := Success{Value: 42}
value := successOptional.GetOption(result) // Some(42)
updated := successOptional.Set(100)(result) // Success{Value: 100}
// Set is no-op when GetOption returns None (Law 1)
failure := Failure{Error: "failed"}
unchanged := successOptional.Set(100)(failure) // failure (unchanged)
See Also:
- Some: Focuses on the Some variant of Option types
- github.com/IBM/fp-go/v2/optics/prism for prism operations
- github.com/IBM/fp-go/v2/optics/optional for optional operations
func (Optional[S, A]) Compose ¶
Compose returns a new Optional that focuses deeper into a structure by chaining this optional (S → A) with an inner optional (A → B), producing a composed optional (S → B).
This is the method-receiver form of the package-level OptionalComposeOptional function, available only on Go 1.27 and later because Go did not support type parameters on methods before that version. On earlier toolchains, use the equivalent free function instead:
// method form (go1.27+) composed := outerOptional.Compose(innerOptional) // free-function form (all versions) composed := optional.Compose[S](innerOptional)(outerOptional)
GetOption of the composed optional chains the two GetOption functions: it first applies the outer optional to obtain an Option[A], then chains the inner optional through that option via O.Chain, returning None whenever either optional produces None.
Set of the composed optional updates the deeply nested focus by threading the new value back through the inner optional's Set and then propagating the change upward via the outer optional's Set. When either optional produces None, Set is a no-op and the original S is returned unchanged, consistent with the Optional no-op law.
The composed optional satisfies all three optional laws (GetSet, SetGet, SetSet) whenever both constituent optionals individually satisfy them.
Type Parameters:
- B: the focus type of the inner optional and of the resulting optional
Parameters:
- ab: the inner optional from A to B
Returns:
- Optional[S, B]: a new optional from S directly to B
See Also:
- Compose: the equivalent package-level function
- ComposeRef: variant for pointer-based outer structures
func (Optional[S, A]) ComposeLens ¶ added in v2.3.122
ComposeLens returns a new Optional that focuses deeper into a structure by composing this optional (S → A) with a lens (A → B), producing an optional (S → B).
Because a Lens always succeeds, the resulting Optional inherits its partiality exclusively from the outer optional: GetOption returns None only when this optional produces None; Set is a no-op only in that same case.
This is the method-receiver form of the package-level OptionalComposeLens function, available only on Go 1.27 and later because Go did not support type parameters on methods before that version. On earlier toolchains, use the equivalent free function instead:
// method form (go1.27+) composed := outerOptional.ComposeLens(innerLens) // free-function form (all versions) composed := OptionalComposeLens[S](innerLens)(outerOptional)
GetOption of the composed optional applies this optional's GetOption to obtain an Option[A], then – when Some – applies the lens's Get to retrieve B, returning None whenever this optional produces None.
Set of the composed optional updates the deeply nested focus: it uses the lens's Set to embed the new B back into A, then propagates the updated A upward via this optional's Set. When this optional produces None, Set is a no-op and the original S is returned unchanged, consistent with the Optional no-op law.
The composed optional satisfies all three optional laws (GetSet, SetGet, SetSet) whenever this optional individually satisfies them (the lens laws are always satisfied by a well-formed Lens).
Type Parameters:
- B: the focus type of the inner lens and of the resulting optional
Parameters:
- ab: the inner lens from A to B
Returns:
- Optional[S, B]: a new optional from S directly to B
See Also:
- Compose: variant that composes with an Optional[A, B] instead of a Lens
- OptionalComposeLens: the equivalent package-level function
func (Optional[S, A]) ComposePrism ¶ added in v2.3.122
ComposePrism returns a new Optional that focuses deeper into a structure by composing this optional (S → A) with a prism (A → B), producing an optional (S → B).
Because a Prism may not match its input, the resulting Optional is None whenever either this optional produces None or the prism does not match the focused A value. Set is a no-op in both cases.
This is the method-receiver form of the package-level OptionalComposePrism function, available only on Go 1.27 and later because Go did not support type parameters on methods before that version. On earlier toolchains, use the equivalent free function instead:
// method form (go1.27+) composed := outerOptional.ComposePrism(innerPrism) // free-function form (all versions) composed := OptionalComposePrism[S](innerPrism)(outerOptional)
GetOption of the composed optional first applies this optional's GetOption to obtain an Option[A]; when Some, it applies the prism's GetOption to try to extract B from A. None is returned whenever either step fails.
Set of the composed optional checks whether GetOption would return Some before writing: when it would, it uses the prism's ReverseGet to reconstruct an A from the new B, then propagates the updated A upward via this optional's Set. When GetOption returns None (either because this optional misses or because the prism does not match), Set is a no-op and the original S is returned unchanged, consistent with the Optional no-op law.
The composed optional satisfies all three optional laws (GetSet, SetGet, SetSet) whenever both this optional and the prism individually satisfy their respective laws.
Type Parameters:
- B: the focus type of the prism and of the resulting optional
Parameters:
- ab: the prism from A to B
Returns:
- Optional[S, B]: a new optional from S directly to B
See Also:
- Compose: variant that composes with an Optional[A, B] instead of a Prism
- ComposeLens: variant that composes with a Lens[A, B] instead of a Prism
- OptionalComposePrism: the equivalent package-level function
func (Optional) Format ¶
Format implements fmt.Formatter for Optional. Supports all standard format verbs:
- %s, %v, %+v, %q, and all other verbs: uses String() representation (optional name)
The exact output format is not a stable contract and may change across versions.
func (Optional) String ¶
func (o Optional) String() string
String returns the name of the optional for debugging and display purposes. The exact format is not a stable contract and may change across versions.
Example:
fieldOptional := optional.MakeOptionalWithName(..., "Person.Email") fmt.Println(fieldOptional) // Prints: "Person.Email"
type OptionalKleisli ¶
OptionalKleisli represents a function that takes a value of type A and returns an Optional[S, B]. This is commonly used for composing optionals in a monadic style.
Type Parameters:
- S: The source type of the resulting optional
- A: The input type to the function
- B: The focus type of the resulting optional
type OptionalOperator ¶
OptionalOperator represents a function that transforms one optional into another. It takes an Optional[S, A] and returns an Optional[S, B], allowing for optional transformations.
Type Parameters:
- S: The source type (remains constant)
- A: The original focus type
- B: The new focus type
func OptionalComposeLens ¶ added in v2.3.122
LensComposeOptional composes a lens with an optional
func OptionalComposeOptional ¶
OptionalComposeOptional combines two Optional and allows to narrow down the focus to a sub-Optional
func OptionalComposeOptionalRef ¶
OptionalComposeOptionalRef combines two Optional and allows to narrow down the focus to a sub-Optional
func OptionalComposePrism ¶ added in v2.3.122
OptionalComposePrism composes an Optional with a Prism to create a new Optional.
This composition allows you to first focus on a value that may not exist (using an Optional), and then focus on a variant within that value (using a Prism). The result is an Optional because either the initial optional may not match, or the prism may not match the focused value.
The composition works by:
- Converting the Prism to an Optional using AsOptional
- Composing the input Optional with the prism-derived Optional using optional composition
The resulting Optional satisfies the three optional laws:
GetSet Law (No-op on None): If GetOption(s) returns None (either the optional doesn't match or the prism doesn't match), then Set(b)(s) returns s unchanged. This is satisfied because both the optional and prism-to-optional conversions ensure Set is a no-op when GetOption returns None.
Formally: GetOption(s) = None => Set(b)(s) = s
SetGet Law (Get what you Set): If GetOption(s) returns Some(_) (both optional and prism match), then GetOption(Set(b)(s)) returns Some(b). This is satisfied because optional composition preserves this property from both components.
Formally: GetOption(s) = Some(_) => GetOption(Set(b)(s)) = Some(b)
SetSet Law (Last Set Wins): Set(c)(Set(b)(s)) equals Set(c)(s). This is satisfied because optional composition preserves this property.
Formally: Set(c)(Set(b)(s)) = Set(c)(s)
Type Parameters:
- S: The source type
- A: The intermediate type (focused by the Optional)
- B: The target type (variant within A, focused by the Prism)
Parameters:
- ab: A Prism[A, B] that focuses on variant B within type A
Returns:
- A function that takes an Optional[S, A] and returns an Optional[S, B]
Example:
type Config struct {
Database Option[DatabaseConfig]
}
type DatabaseConfig interface{ isDatabase() }
type PostgreSQL struct{ Host string }
type MySQL struct{ Host string }
// Optional focusing on Database field
dbOptional := optional.MakeOptional(
func(c Config) Option[DatabaseConfig] {
return c.Database
},
func(c Config, db DatabaseConfig) Config {
c.Database = Some(db)
return c
},
)
// Prism focusing on PostgreSQL variant
pgPrism := prism.MakePrism(
func(db DatabaseConfig) Option[PostgreSQL] {
if pg, ok := db.(PostgreSQL); ok {
return Some(pg)
}
return None[PostgreSQL]()
},
func(pg PostgreSQL) DatabaseConfig { return pg },
)
// OptionalComposePrism to create Optional[Config, PostgreSQL]
configPgOptional := OptionalComposePrism[Config, DatabaseConfig, PostgreSQL](pgPrism)(dbOptional)
// Use the optional
config := Config{Database: Some(PostgreSQL{Host: "localhost"})}
host := configPgOptional.GetOption(config) // Some(PostgreSQL{Host: "localhost"})
updated := configPgOptional.Set(PostgreSQL{Host: "remote"})(config)
// updated.Database = Some(PostgreSQL{Host: "remote"})
// Set is no-op when optional doesn't match (Law 1)
emptyConfig := Config{Database: None[DatabaseConfig]()}
unchanged := configPgOptional.Set(PostgreSQL{Host: "remote"})(emptyConfig)
// unchanged == emptyConfig (no-op)
// Set is no-op when prism doesn't match (Law 1)
mysqlConfig := Config{Database: Some(MySQL{Host: "localhost"})}
unchanged = configPgOptional.Set(PostgreSQL{Host: "remote"})(mysqlConfig)
// unchanged == mysqlConfig (no-op)
See Also:
- AsOptional: Converts prisms to optionals
- github.com/IBM/fp-go/v2/optics/optional.OptionalComposePrism for optional composition
- github.com/IBM/fp-go/v2/optics/prism/lens for the inverse composition (prism then lens)
func OptionalIChain ¶
func OptionalIChain[S, A, B any](ab OptionKleisli[A, B], ba OptionKleisli[B, A]) OptionalOperator[S, A, B]
OptionalIChain implements a bidirectional mapping of the transform if the transform can produce optionals (e.g. in case of type mappings)
func OptionalIChainAny ¶
OptionalIChainAny implements a bidirectional mapping to and from any
func OptionalIMap ¶
func OptionalIMap[S, A, B any](ab func(A) B, ba func(B) A) OptionalOperator[S, A, B]
OptionalIMap implements a bidirectional mapping of the transform
type Predicate ¶ added in v2.3.120
func EitherExists ¶ added in v2.3.122
EitherExists creates a predicate that tests whether an Either value is Right and its value satisfies the given predicate. It returns a function that takes an Either[E, T] and returns true only if the Either is Right and the predicate p returns true for the Right value.
This function is useful for checking if an Either contains a successful value that meets certain criteria, commonly used in filtering operations, validation chains, or conditional logic where you need to verify both the success state and a property of the success value.
The behavior is as follows:
- If the input is Left, returns false (regardless of the predicate)
- If the input is Right and p returns true for the Right value, returns true
- If the input is Right and p returns false for the Right value, returns false
Type Parameters:
- E: The type of the Left value (error type)
- T: The type of the Right value (success type)
Parameters:
- p: A predicate function that tests values of type T
Returns:
A Predicate function that takes an Either[E, T] and returns true if it's Right and satisfies p
Example:
import (
E "github.com/IBM/fp-go/v2/either"
N "github.com/IBM/fp-go/v2/number"
)
// Check if Either contains a positive number
isPositive := N.MoreThan(0)
hasPositive := E.EitherExists[string](isPositive)
result1 := hasPositive(E.Right[string](5))
// result1 = true (Right with positive value)
result2 := hasPositive(E.Right[string](-3))
// result2 = false (Right with non-positive value)
result3 := hasPositive(E.Left[int]("error"))
// result3 = false (Left value)
// Use in filtering
values := []E.Either[string, int]{
E.Right[string](5),
E.Left[int]("error"),
E.Right[string](-3),
E.Right[string](10),
}
hasPositiveValue := func(e E.Either[string, int]) bool {
return hasPositive(e)
}
// Filter to keep only Eithers with positive Right values
// filtered would contain: [Right(5), Right(10)]
See Also:
- ExistsLeft: Tests if Either is Left and satisfies a predicate
- Filter: Converts Right values that fail a predicate to Left
func EitherExistsLeft ¶ added in v2.3.122
EitherExistsLeft creates a predicate that tests whether an Either value is Left and its value satisfies the given predicate. It returns a function that takes an Either[E, T] and returns true only if the Either is Left and the predicate p returns true for the Left value.
This function is useful for checking if an Either contains an error value that meets certain criteria, commonly used in error filtering, error categorization, or conditional logic where you need to verify both the error state and a property of the error value.
The behavior is as follows:
- If the input is Right, returns false (regardless of the predicate)
- If the input is Left and p returns true for the Left value, returns true
- If the input is Left and p returns false for the Left value, returns false
Type Parameters:
- T: The type of the Right value (success type)
- E: The type of the Left value (error type)
Parameters:
- p: A predicate function that tests values of type E
Returns:
A Predicate function that takes an Either[E, T] and returns true if it's Left and satisfies p
Example:
import (
E "github.com/IBM/fp-go/v2/either"
"strings"
)
// Check if Either contains a validation error
isValidationError := func(s string) bool {
return strings.HasPrefix(s, "validation:")
}
hasValidationError := E.EitherExistsLeft[int](isValidationError)
result1 := hasValidationError(E.Left[int]("validation: invalid input"))
// result1 = true (Left with validation error)
result2 := hasValidationError(E.Left[int]("network: connection failed"))
// result2 = false (Left with non-validation error)
result3 := hasValidationError(E.Right[string](42))
// result3 = false (Right value)
// Use in error categorization
results := []E.Either[string, int]{
E.Left[int]("validation: empty field"),
E.Right[string](100),
E.Left[int]("network: timeout"),
E.Left[int]("validation: invalid format"),
}
hasValidationErr := func(e E.Either[string, int]) bool {
return hasValidationError(e)
}
// Filter to find validation errors
// filtered would contain: [Left("validation: empty field"), Left("validation: invalid format")]
See Also:
- Exists: Tests if Either is Right and satisfies a predicate
- IsLeft: Tests if Either is Left without checking the value
func EitherForAll ¶ added in v2.3.122
EitherForAll creates a predicate that tests whether an Either value is Left or its Right value satisfies the given predicate. It returns a function that takes an Either[E, T] and returns true if the Either is Left (regardless of its value) or if it's Right and the predicate p returns true for the Right value.
This function implements universal quantification over the Either type. In logical terms, it states: "for all values in the Either, the predicate holds" - which is vacuously true for Left values (empty case) and requires the predicate to hold for Right values (non-empty case).
The behavior is as follows:
- If the input is Left, returns true (vacuous truth - predicate holds for empty case)
- If the input is Right and p returns true for the Right value, returns true
- If the input is Right and p returns false for the Right value, returns false
Relationship to Haskell and Category Theory:
In Haskell, this corresponds to the all function for the Either type when viewed as a Foldable:
all :: Foldable t => (a -> Bool) -> t a -> Bool all p (Right x) = p x all p (Left _) = True
From a category theory perspective, Either[E, T] is a coproduct (sum type) in the category of types. EitherForAll implements a natural transformation from predicates on T to predicates on Either[E, T], preserving the logical structure where:
- The Left case represents the "empty" or "absent" case (like Nothing in Maybe/Option)
- The Right case represents the "present" case that must satisfy the predicate
This is dual to Exists, which implements existential quantification:
- EitherForAll: "all elements satisfy p" (true for empty, requires p for non-empty)
- Exists: "some element satisfies p" (false for empty, requires p for non-empty)
The relationship follows De Morgan's laws:
- EitherForAll(p) ≡ not(Exists(not(p)))
- Exists(p) ≡ not(EitherForAll(not(p)))
Type Parameters:
- E: The type of the Left value (error type)
- T: The type of the Right value (success type)
Parameters:
- p: A predicate function that tests values of type T
Returns:
A Predicate function that takes an Either[E, T] and returns true if it's Left or Right with p satisfied
Example:
import (
E "github.com/IBM/fp-go/v2/either"
N "github.com/IBM/fp-go/v2/number"
)
// Check if Either is Left or contains a positive number
isPositive := N.MoreThan(0)
allPositive := E.EitherForAll[string](isPositive)
result1 := allPositive(E.Right[string](5))
// result1 = true (Right with positive value satisfies predicate)
result2 := allPositive(E.Right[string](-3))
// result2 = false (Right with non-positive value fails predicate)
result3 := allPositive(E.Left[int]("error"))
// result3 = true (Left is vacuously true - no value to check)
// Use in validation: ensure all successful results meet criteria
values := []E.Either[string, int]{
E.Right[string](5),
E.Left[int]("error"), // Ignored (vacuously true)
E.Right[string](10),
E.Right[string](-3), // Fails validation
}
allValid := func(e E.Either[string, int]) bool {
return allPositive(e)
}
// Check if all non-error values are positive
// result would be false because Right(-3) fails the predicate
// Contrast with Exists:
hasPositive := E.Exists[string](isPositive)
// hasPositive checks if there EXISTS a Right value satisfying p
// allPositive checks if ALL Right values satisfy p (Left is ignored)
See Also:
- Exists: Tests if Either is Right and satisfies a predicate (existential quantification)
- ExistsLeft: Tests if Either is Left and satisfies a predicate
- Filter: Converts Right values that fail a predicate to Left
func OptionExists ¶ added in v2.3.120
OptionExists creates a predicate that tests whether an Option value is Some and its value satisfies the given predicate. It returns a function that takes an Option[T] and returns true only if the Option is Some and the predicate p returns true for the contained value.
This function is useful for checking if an Option contains a value that meets certain criteria, commonly used in filtering operations, validation chains, or conditional logic where you need to verify both the presence of a value and a property of that value.
The behavior is as follows:
- If the input is None, returns false (regardless of the predicate)
- If the input is Some and p returns true for the contained value, returns true
- If the input is Some and p returns false for the contained value, returns false
Type Parameters:
- T: The type of the value contained in the Option
Parameters:
- p: A predicate function that tests values of type T
Returns:
A Predicate function that takes an Option[T] and returns true if it's Some and satisfies p
Example:
import (
O "github.com/IBM/fp-go/v2/option"
N "github.com/IBM/fp-go/v2/number"
)
// Check if Option contains a positive number
isPositive := N.MoreThan(0)
hasPositive := O.OptionExists(isPositive)
result1 := hasPositive(O.Some(5))
// result1 = true (Some with positive value)
result2 := hasPositive(O.Some(-3))
// result2 = false (Some with non-positive value)
result3 := hasPositive(O.None[int]())
// result3 = false (None value)
// Use in filtering
values := []O.Option[int]{
O.Some(5),
O.None[int](),
O.Some(-3),
O.Some(10),
}
hasPositiveValue := func(opt O.Option[int]) bool {
return hasPositive(opt)
}
// Filter to keep only Options with positive Some values
// filtered would contain: [Some(5), Some(10)]
See Also:
- Filter: Converts Some values that fail a predicate to None
- IsSome: Tests if Option is Some without checking the value
func OptionForAll ¶ added in v2.3.120
OptionForAll creates a predicate that tests whether an Option value is None or its Some value satisfies the given predicate. It returns a function that takes an Option[T] and returns true if the Option is None (regardless of content) or if it's Some and the predicate p returns true for the contained value.
This function implements universal quantification over the Option type. In logical terms, it states: "for all values in the Option, the predicate holds" - which is vacuously true for None values (empty case) and requires the predicate to hold for Some values (non-empty case).
The behavior is as follows:
- If the input is None, returns true (vacuous truth - predicate holds for empty case)
- If the input is Some and p returns true for the contained value, returns true
- If the input is Some and p returns false for the contained value, returns false
Relationship to Haskell and Category Theory:
In Haskell, this corresponds to the all function for the Maybe type when viewed as a Foldable:
all :: Foldable t => (a -> Bool) -> t a -> Bool all p (Just x) = p x all p Nothing = True
From a category theory perspective, Option[T] is a sum type representing optional values. OptionForAll implements a natural transformation from predicates on T to predicates on Option[T], preserving the logical structure where:
- The None case represents the "empty" or "absent" case
- The Some case represents the "present" case that must satisfy the predicate
This is dual to Exists, which implements existential quantification:
- OptionForAll: "all elements satisfy p" (true for empty, requires p for non-empty)
- Exists: "some element satisfies p" (false for empty, requires p for non-empty)
The relationship follows De Morgan's laws:
- OptionForAll(p) ≡ not(Exists(not(p)))
- Exists(p) ≡ not(OptionForAll(not(p)))
Type Parameters:
- T: The type of the value contained in the Option
Parameters:
- p: A predicate function that tests values of type T
Returns:
A Predicate function that takes an Option[T] and returns true if it's None or Some with p satisfied
Example:
import (
O "github.com/IBM/fp-go/v2/option"
N "github.com/IBM/fp-go/v2/number"
)
// Check if Option is None or contains a positive number
isPositive := N.MoreThan(0)
allPositive := O.OptionForAll(isPositive)
result1 := allPositive(O.Some(5))
// result1 = true (Some with positive value satisfies predicate)
result2 := allPositive(O.Some(-3))
// result2 = false (Some with non-positive value fails predicate)
result3 := allPositive(O.None[int]())
// result3 = true (None is vacuously true - no value to check)
// Use in validation: ensure all present values meet criteria
values := []O.Option[int]{
O.Some(5),
O.None[int](), // Ignored (vacuously true)
O.Some(10),
O.Some(-3), // Fails validation
}
allValid := true
for _, v := range values {
if !allPositive(v) {
allValid = false
break
}
}
// allValid would be false because Some(-3) fails the predicate
// Contrast with Exists:
hasPositive := O.Exists(isPositive)
// hasPositive checks if there EXISTS a Some value satisfying p
// allPositive checks if ALL Some values satisfy p (None is ignored)
See Also:
- Exists: Tests if Option is Some and satisfies a predicate (existential quantification)
- Filter: Converts Some values that fail a predicate to None
- IsSome: Tests if Option is Some without checking the value
type Prism ¶
type Prism[S, A any] struct { // GetOption attempts to extract a value of type A from S. // Returns Some(a) if the extraction succeeds, None otherwise. GetOption OptionKleisli[S, A] // ReverseGet constructs an S from an A. // This operation always succeeds. ReverseGet func(A) S // contains filtered or unexported fields }
Prism is an optic used to select part of a sum type (tagged union). It provides two operations:
- GetOption: Try to extract a value of type A from S (may fail)
- ReverseGet: Construct an S from an A (always succeeds)
Prisms are useful for working with variant types like Either, Option, or custom sum types where you want to focus on a specific variant.
Type Parameters:
- S: The source type (sum type)
- A: The focus type (variant within the sum type)
Example:
type Result interface{ isResult() }
type Success struct{ Value int }
type Failure struct{ Error string }
successPrism := MakePrism(
func(r Result) Option[int] {
if s, ok := r.(Success); ok {
return Some(s.Value)
}
return None[int]()
},
func(v int) Result { return Success{Value: v} },
)
func MakePrism ¶
func MakePrism[S, A any](get OptionKleisli[S, A], rev func(A) S) Prism[S, A]
MakePrism constructs a Prism from GetOption and ReverseGet functions.
Parameters:
- get: Function to extract A from S (returns Option[A])
- rev: Function to construct S from A
Returns:
- A Prism[S, A] that uses the provided functions
Example:
prism := MakePrism(
func(opt Option[int]) Option[int] { return opt },
func(n int) Option[int] { return Some(n) },
)
func MakePrismWithName ¶
func MakePrismWithName[S, A any](get OptionKleisli[S, A], rev func(A) S, name string) Prism[S, A]
func PrismFromOption ¶
PrismFromOption creates a prism for extracting values from Option types. It provides a safe way to work with Option values, focusing on the Some case and handling the None case gracefully through the prism's GetOption behavior.
The prism's GetOption is the identity function - it returns the Option as-is. If the Option is Some(value), GetOption returns Some(value); if it's None, it returns None. This allows the prism to naturally handle the presence or absence of a value.
The prism's ReverseGet wraps a value into Some, always succeeding.
Type Parameters:
- T: The value type contained in the Option
Returns:
- A Prism[Option[T], T] that safely extracts values from Options
Example:
// Create a prism for extracting int values from Option[int]
optPrism := FromOption[int]()
// Extract from Some
someValue := option.Some(42)
result := optPrism.GetOption(someValue) // Some(42)
// Extract from None
noneValue := option.None[int]()
result = optPrism.GetOption(noneValue) // None[int]()
// Wrap value into Some
wrapped := optPrism.ReverseGet(100) // Some(100)
// Use with Set to update Some values
setter := Set[Option[int], int](200)
result := setter(optPrism)(someValue) // Some(200)
result = setter(optPrism)(noneValue) // None[int]() (unchanged)
// Compose with other prisms for nested extraction
// Extract int from Option[Option[int]]
nestedPrism := Compose[Option[Option[int]], Option[int], int](
FromOption[Option[int]](),
FromOption[int](),
)
nested := option.Some(option.Some(42))
value := nestedPrism.GetOption(nested) // Some(42)
Common use cases:
- Extracting values from optional fields
- Working with nullable data in a type-safe way
- Composing with other prisms to handle nested Options
- Filtering and transforming optional values in pipelines
- Converting between Option and other optional representations
Key insight: This prism treats Option[T] as a "container" that may or may not hold a value of type T. The prism focuses on the value inside, allowing you to work with it when present and gracefully handle its absence when not.
func PrismFromPredicate ¶
PrismFromPredicate creates a prism that matches values satisfying a predicate. GetOption returns Some(s) if the predicate is true, None otherwise. ReverseGet is the identity function (doesn't validate the predicate).
Parameters:
- pred: Predicate function to test values
Returns:
- A Prism[S, S] that filters based on the predicate
Example:
positivePrism := PrismFromPredicate(N.MoreThan(0)) value := positivePrism.GetOption(42) // Some(42) value = positivePrism.GetOption(-5) // None[int]
func PrismId ¶
PrismId returns an identity prism that focuses on the entire value. GetOption always returns Some(s), and ReverseGet is the identity function.
This is useful as a starting point for prism composition or when you need a prism that doesn't actually transform the value.
Example:
idPrism := PrismId[int]() value := idPrism.GetOption(42) // Some(42) result := idPrism.ReverseGet(42) // 42
func PrismSome ¶
PrismSome creates a prism that focuses on the PrismSome variant of an Option within a structure. It composes the provided prism (which focuses on an Option[A]) with a prism that extracts the value from PrismSome.
Type Parameters:
- S: The source type
- A: The value type within the Option
Parameters:
- soa: A prism that focuses on an Option[A] within S
Returns:
- A prism that focuses on the A value within PrismSome
Example:
type Config struct { Timeout Option[int] }
configPrism := MakePrism(...) // Prism[Config, Option[int]]
timeoutPrism := PrismSome(configPrism) // Prism[Config, int]
value := timeoutPrism.GetOption(Config{Timeout: PrismSome(30)}) // PrismSome(30)
func (Prism[S, A]) Compose ¶
Compose returns a new prism that focuses deeper into a sum type by chaining this prism (S → A) with an inner prism (A → B), producing a composed prism (S → B).
This is the method-receiver form of the package-level OptionalComposeOptional function, available only on Go 1.27 and later because Go did not support type parameters on methods before that version. On earlier toolchains, use the equivalent free function instead:
// method form (go1.27+) composed := outerPrism.Compose(innerPrism) // free-function form (all versions) composed := prism.Compose[S](innerPrism)(outerPrism)
GetOption of the composed prism chains the two GetOption functions: it first applies the outer prism to obtain an Option[A], then chains the inner prism through that option via O.Chain, returning None whenever either prism fails to match.
ReverseGet of the composed prism pipes the value back through both ReverseGet functions in order: inner first, then outer.
The composed prism satisfies both prism laws whenever both constituent prisms individually satisfy them.
Type Parameters:
- B: the focus type of the inner prism and of the resulting prism
Parameters:
- ab: the inner prism from A to B
Returns:
- Prism[S, B]: a new prism from S directly to B
See Also:
- Compose: the equivalent package-level function
func (Prism) Format ¶
Format implements fmt.Formatter.
Supports all standard format verbs:
- %s, %v, %+v, %q, and all other verbs: uses the String() representation (the prism name)
The exact output format is not a stable contract and may change across versions.
type PrismKleisli ¶
Kleisli represents a function that takes a value of type A and returns a Prism[S, B]. This is commonly used for composing prisms in a monadic style.
Type Parameters:
- S: The source type of the resulting prism
- A: The input type to the function
- B: The focus type of the resulting prism
type PrismOperator ¶
Operator represents a function that transforms one prism into another. It takes a Prism[S, A] and returns a Prism[S, B], allowing for prism transformations.
Type Parameters:
- S: The source type (remains constant)
- A: The original focus type
- B: The new focus type
func PrismComposePrism ¶
Compose composes two prisms to create a prism that focuses deeper into a structure. The resulting prism first applies the outer prism (S → A), then the inner prism (A → B).
Type Parameters:
- S: The outermost source type
- A: The intermediate type
- B: The innermost focus type
Parameters:
- ab: The inner prism (A → B)
Returns:
- A function that takes the outer prism (S → A) and returns the composed prism (S → B)
Example:
outerPrism := MakePrism(...) // Prism[Outer, Inner] innerPrism := MakePrism(...) // Prism[Inner, Value] composed := Compose[Outer](innerPrism)(outerPrism) // Prism[Outer, Value]
func PrismIMap ¶
PrismIMap bidirectionally maps the focus type of a prism. It transforms a Prism[S, A] into a Prism[S, B] using two functions: one to map A → B and another to map B → A.
Type Parameters:
- S: The source type
- A: The original focus type
- B: The new focus type
- AB: Function type A → B
- BA: Function type B → A
Parameters:
- ab: Function to map from A to B
- ba: Function to map from B to A
Returns:
- A function that transforms Prism[S, A] to Prism[S, B]
Example:
intPrism := MakePrism(...) // Prism[Result, int]
stringPrism := PrismIMap[Result](
strconv.Itoa,
func(s string) int { n, _ := strconv.Atoi(s); return n },
)(intPrism) // Prism[Result, string]
Source Files
¶
- either.go
- either_alt.go
- either_array.go
- either_core.go
- either_filterable.go
- either_format.go
- either_predicate.go
- either_profunctor.go
- either_record.go
- either_resource.go
- either_validation.go
- iso.go
- iso_format.go
- iso_go1_27.go
- lens.go
- lens_format.go
- lens_go1_27.go
- lens_optional_compose.go
- lens_prism_compose.go
- option.go
- option_array.go
- option_core.go
- option_format.go
- option_predicate.go
- optional.go
- optional_format.go
- optional_go1_27.go
- optional_prism_compose.go
- optional_traversal.go
- prism.go
- prism_format.go
- prism_go1_27.go
- prism_traversal.go
- types.go