io.github.cwdesautels.monad.Either Maven / Gradle / Ivy
package io.github.cwdesautels.monad;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* Right biased either monad.
*/
public interface Either {
// Constructors
static Either left(L left) {
return ImmutableLeft.builder()
.left(left)
.build();
}
static Either right(R right) {
return ImmutableRight.builder()
.get(right)
.build();
}
// Behaviour
L getLeft();
R get();
boolean isLeft();
boolean isRight();
// Templates
default R orElse(R other) {
if (isRight()) {
return get();
} else {
return other;
}
}
default R orElseGet(Supplier other) {
Objects.requireNonNull(other);
if (isRight()) {
return get();
} else {
return other.get();
}
}
default R orElseMap(Function function) {
Objects.requireNonNull(function);
if (isRight()) {
return get();
} else {
return function.apply(getLeft());
}
}
default R orElseThrow(Supplier supplier) throws X {
Objects.requireNonNull(supplier);
if (isLeft()) {
throw supplier.get();
} else {
return get();
}
}
default Either swap() {
if (isRight()) {
return left(get());
} else {
return right(getLeft());
}
}
default Either map(Function function) {
Objects.requireNonNull(function);
if (isRight()) {
return right(function.apply(get()));
} else {
return left(getLeft());
}
}
default Either flatMap(Function> function) {
Objects.requireNonNull(function);
if (isRight()) {
return Objects.requireNonNull(function.apply(get()));
} else {
return left(getLeft());
}
}
default Either mapLeft(Function function) {
Objects.requireNonNull(function);
if (isLeft()) {
return left(function.apply(getLeft()));
} else {
return right(get());
}
}
default Either flatMapLeft(Function> function) {
Objects.requireNonNull(function);
if (isLeft()) {
return Objects.requireNonNull(function.apply(getLeft()));
} else {
return right(get());
}
}
default T fold(Function leftMapper, Function rightMapper) {
Objects.requireNonNull(leftMapper);
Objects.requireNonNull(rightMapper);
if (isRight()) {
return rightMapper.apply(get());
} else {
return leftMapper.apply(getLeft());
}
}
default Either ifRight(Consumer consumer) {
Objects.requireNonNull(consumer);
if (isRight()) {
consumer.accept(get());
}
return this;
}
default Either ifLeft(Consumer consumer) {
Objects.requireNonNull(consumer);
if (isLeft()) {
consumer.accept(getLeft());
}
return this;
}
default Optional toOptional() {
if (isRight()) {
return Optional.ofNullable(get());
} else {
return Optional.empty();
}
}
}