189 lines
4.2 KiB
Go
189 lines
4.2 KiB
Go
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
|
|
}
|