Skip to content

Instantly share code, notes, and snippets.

@volgar1x
Created April 8, 2014 18:22
Show Gist options
  • Save volgar1x/10166773 to your computer and use it in GitHub Desktop.
Save volgar1x/10166773 to your computer and use it in GitHub Desktop.
package org.heat.shared;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
public interface Either<L, R> {
public static <L, R> Either<L, R> left(L left) { return left(left, null); }
public static <L, R> Either<L, R> right(R right) { return right(null, right); }
L left();
R right();
<T> T match(Function<L, T> left, Function<R, T> right);
default <LL, RR> Either<LL, RR> bind(Function<L, Either<LL, RR>> left, Function<R, Either<LL, RR>> right) {
return match(left, right);
}
default <LL, RR> Either<LL, RR> map(Function<L, LL> left, Function<R, RR> right) {
return bind(
l -> left(left.apply(l)),
r -> right(right.apply(r))
);
}
default <LL> Either<LL, R> leftFlatMap(Function<L, Either<LL, R>> left) {
return bind(left, Either::right);
}
default <RR> Either<L, RR> rightFlatMap(Function<R, Either<L, RR>> right) {
return bind(Either::left, right);
}
default <LL> Either<LL, R> leftMap(Function<L, LL> left) {
return bind(l -> left(left.apply(l)), Either::right);
}
default <RR> Either<L, RR> rightMap(Function<R, RR> right) {
return bind(Either::left, r -> right(right.apply(r)));
}
default Either<L, R> leftFilter(Predicate<L> fn, Supplier<R> otherwise) {
return leftFlatMap(l -> fn.test(l) ? left(l) : right(otherwise.get()));
}
default Either<L, R> rightFilter(Predicate<R> fn, Supplier<L> otherwise) {
return rightFlatMap(r -> fn.test(r) ? right(r) : left(otherwise.get()));
}
default Stream<L> leftStream() {
return match(Stream::of, r -> Stream.empty());
}
default Stream<R> rightStream() {
return match(l -> Stream.empty(), Stream::of);
}
default Optional<L> leftOption() {
return match(Optional::of, r -> Optional.empty());
}
default Optional<R> rightOption() {
return match(r -> Optional.empty(), Optional::of);
}
@SuppressWarnings({"unchecked", "UnusedParameters"})
public static <L, R> Either<L, R> left(L left, Class<R> ignored) {
return (Either<L, R>) new Left<>(left);
}
@SuppressWarnings({"unchecked", "UnusedParameters"})
public static <L, R> Either<L, R> right(Class<L> ignored, R right) {
return (Either<L, R>) new Right<>(right);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment