com.swoval.functional.Either Maven / Gradle / Ivy
package com.swoval.functional;
/**
* Represents a value that can be one of two types. Inspired by Either,
* it is right biased, but does not define all of the combinators that the scala version does.
*
* @param The left value
* @param The right value
*/
public abstract class Either {
private Either() {}
/**
* Returns the Left projection for the provided Either or throws an exception if the Either is
* actually an instance of {@link com.swoval.functional.Either.Right}.
*
* @param either the either, assumed to be an instance of left, that will
* @param the left type of the either.
* @param the right type of the either.
* @return a Left projection.
* @throws NotLeftException if the value is a {@link com.swoval.functional.Either.Right}.
*/
public static Left leftProjection(final Either either)
throws NotLeftException {
if (either.isLeft()) return (Left) either;
else throw new NotLeftException();
}
/**
* Returns the Right projection for the provided Either or throws an exception if the Either is
* actually an instance of {@link com.swoval.functional.Either.Left}.
*
* @param either the either, assumed to be an instance of left, that will
* @param the left type of the either.
* @param the right type of the either.
* @return a Right projection.
* @throws NotRightException if the value is a {@link com.swoval.functional.Either.Left}.
*/
public static Right rightProjection(final Either either)
throws NotRightException {
if (either.isRight()) return (Right) either;
else throw new NotRightException();
}
/**
* Check whether this is a Left projection.
*
* @return true if this is a Reft projection
*/
public abstract boolean isLeft();
/**
* Check whether this is a Right projection.
*
* @return true if this is a Right projection
*/
public abstract boolean isRight();
/**
* Get the right projected value of the either. This is unsafe to call without checking whether
* the value is a right first.
*
* @return the wrapped value if is a right projection
* @throws NotRightException if this is a left projection
*/
public R get() {
if (isRight()) return rightProjection(this).getValue();
else throw new NotRightException();
}
/**
* Get the right projected value of the either or a provided default value.
*
* @param either the either from which the method extracts the result if it is a {@link
* com.swoval.functional.Either.Right}.
* @param t the default value
* @param the default type
* @return the wrapped value if this is a right projection, otherwise the default
*/
public static T getOrElse(final Either, ? extends T> either, final T t) {
return either.isRight() ? either.get() : t;
}
@Override
public abstract int hashCode();
@Override
public abstract boolean equals(final Object other);
/**
* Returns a left projected either.
*
* @param value the value to wrap
* @param the type of the left parameter of the result
* @param the type of the right parameter of the result
* @param a refinement type that allows us to wrap subtypes of L
* @return A left projected either
*/
public static Either left(final T value) {
return new Left<>((L) value);
}
/**
* Returns a right projected either.
*
* @param value the value to wrap
* @param the type of the left parameter of the result
* @param the type of the right parameter of the result
* @param a refinement type that allows us to wrap subtypes of R
* @return a right projected either.
*/
public static Either right(final T value) {
return new Right<>((R) value);
}
/**
* An error that is thrown if an attempt is made to project an Either to {@link
* com.swoval.functional.Either.Left} when the object is actually an instance of {@link
* com.swoval.functional.Either.Right}.
*/
public static class NotLeftException extends RuntimeException {}
/**
* An error that is thrown if an attempt is made to project an Either to {@link
* com.swoval.functional.Either.Right} when the object is actually an instance of {@link
* com.swoval.functional.Either.Left}.
*/
public static class NotRightException extends RuntimeException {}
/**
* A left projected {@link com.swoval.functional.Either}.
*
* @param the left type
* @param the right type
*/
public static final class Left extends Either {
private final L value;
Left(final L value) {
this.value = value;
}
/**
* Returns the wrapped value
*
* @return the wrapped value
*/
public L getValue() {
return value;
}
@Override
public boolean isLeft() {
return true;
}
@Override
public boolean isRight() {
return false;
}
@Override
public String toString() {
return "Left(" + value + ")";
}
@Override
public boolean equals(Object other) {
return other instanceof com.swoval.functional.Either.Left, ?>
&& this.value.equals(((com.swoval.functional.Either.Left, ?>) other).getValue());
}
@Override
public int hashCode() {
return value.hashCode();
}
}
/**
* A right projected {@link com.swoval.functional.Either}.
*
* @param the left type
* @param the right type
*/
public static final class Right extends Either {
private final R value;
Right(final R value) {
this.value = value;
}
/**
* Returns the wrapped value.
*
* @return the wrapped value.
*/
public R getValue() {
return value;
}
@Override
public boolean isLeft() {
return false;
}
@Override
public boolean isRight() {
return true;
}
@Override
public String toString() {
return "Right(" + value + ")";
}
@Override
public boolean equals(Object other) {
return other instanceof com.swoval.functional.Either.Right, ?>
&& this.value.equals(((com.swoval.functional.Either.Right, ?>) other).getValue());
}
@Override
public int hashCode() {
return value.hashCode();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy