package mo import "fmt" var errEitherShouldBeLeftOrRight = fmt.Errorf("either should be Left or Right") var errEitherMissingLeftValue = fmt.Errorf("no such Left value") var errEitherMissingRightValue = fmt.Errorf("no such Right value") // Left builds the left side of the Either struct, as opposed to the Right side. func Left[L any, R any](value L) Either[L, R] { return Either[L, R]{ isLeft: true, left: value, } } // Right builds the right side of the Either struct, as opposed to the Left side. func Right[L any, R any](value R) Either[L, R] { return Either[L, R]{ isLeft: false, right: value, } } // Either respresents a value of 2 possible types. // An instance of Either is an instance of either A or B. type Either[L any, R any] struct { isLeft bool left L right R } // IsLeft returns true if Either is an instance of Left. func (e Either[L, R]) IsLeft() bool { return e.isLeft } // IsRight returns true if Either is an instance of Right. func (e Either[L, R]) IsRight() bool { return !e.isLeft } // Left returns left value of a Either struct. func (e Either[L, R]) Left() (L, bool) { if e.IsLeft() { return e.left, true } return empty[L](), false } // Right returns right value of a Either struct. func (e Either[L, R]) Right() (R, bool) { if e.IsRight() { return e.right, true } return empty[R](), false } // MustLeft returns left value of a Either struct or panics. func (e Either[L, R]) MustLeft() L { if !e.IsLeft() { panic(errEitherMissingLeftValue) } return e.left } // MustRight returns right value of a Either struct or panics. func (e Either[L, R]) MustRight() R { if !e.IsRight() { panic(errEitherMissingRightValue) } return e.right } // Unpack returns all values func (e Either[L, R]) Unpack() (L, R) { return e.left, e.right } // LeftOrElse returns left value of a Either struct or fallback. func (e Either[L, R]) LeftOrElse(fallback L) L { if e.IsLeft() { return e.left } return fallback } // RightOrElse returns right value of a Either struct or fallback. func (e Either[L, R]) RightOrElse(fallback R) R { if e.IsRight() { return e.right } return fallback } // LeftOrEmpty returns left value of a Either struct or empty value. func (e Either[L, R]) LeftOrEmpty() L { if e.IsLeft() { return e.left } return empty[L]() } // RightOrEmpty returns right value of a Either struct or empty value. func (e Either[L, R]) RightOrEmpty() R { if e.IsRight() { return e.right } return empty[R]() } // Swap returns the left value in Right and vice versa. func (e Either[L, R]) Swap() Either[R, L] { if e.IsLeft() { return Right[R](e.left) } return Left[R, L](e.right) } // ForEach executes the given side-effecting function, depending of value is Left or Right. func (e Either[L, R]) ForEach(leftCb func(L), rightCb func(R)) { if e.IsLeft() { leftCb(e.left) } else if e.IsRight() { rightCb(e.right) } } // Match executes the given function, depending of value is Left or Right, and returns result. func (e Either[L, R]) Match(onLeft func(L) Either[L, R], onRight func(R) Either[L, R]) Either[L, R] { if e.IsLeft() { return onLeft(e.left) } else if e.IsRight() { return onRight(e.right) } panic(errEitherShouldBeLeftOrRight) } // MapLeft executes the given function, if Either is of type Left, and returns result. func (e Either[L, R]) MapLeft(mapper func(L) Either[L, R]) Either[L, R] { if e.IsLeft() { return mapper(e.left) } else if e.IsRight() { return Right[L, R](e.right) } panic(errEitherShouldBeLeftOrRight) } // MapRight executes the given function, if Either is of type Right, and returns result. func (e Either[L, R]) MapRight(mapper func(R) Either[L, R]) Either[L, R] { if e.isLeft { return Left[L, R](e.left) } else if e.IsRight() { return mapper(e.right) } panic(errEitherShouldBeLeftOrRight) } // leftValue returns left value of a Either struct.(implementation of Foldable interface) // //nolint:unused func (e Either[L, R]) leftValue() L { return e.left } // rightValue returns right value of a Either struct.(implementation of Foldable interface) // //nolint:unused func (e Either[L, R]) rightValue() R { return e.right } // hasLeft returns true if the Result represents an error state. // //nolint:unused func (e Either[L, R]) hasLeftValue() bool { return e.isLeft }