Last active
June 21, 2021 16:22
-
-
Save shawnz/f5d5f704594e2e9d3cae344fcb77f93f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.shawnz.util; | |
import java.util.NoSuchElementException; | |
import java.util.function.Function; | |
public abstract class Either<L, R> { | |
private Either() { | |
} | |
public static <L, R> Either<L, R> ofLeft(L left) { | |
return new Left<>(left); | |
} | |
public static <L, R> Either<L, R> ofLeft(L left, Class<R> other) { | |
return ofLeft(left); | |
} | |
public static <L, R> Either<L, R> ofRight(R right) { | |
return new Right<>(right); | |
} | |
public static <L, R> Either<L, R> ofRight(R right, Class<L> other) { | |
return ofRight(right); | |
} | |
public static <L, R, T> Function<Either<L, R>, Either<? extends T, R>> leftMapper( | |
Function<? super L, ? extends T> leftFunction) { | |
return either -> either.mapLeft(leftFunction); | |
} | |
public static <L, R, T> Function<Either<L, R>, Either<L, ? extends T>> rightMapper( | |
Function<? super R, ? extends T> rightFunction) { | |
return either -> either.mapRight(rightFunction); | |
} | |
public abstract <T> T map(Function<? super L, ? extends T> leftFunction, Function<? super R, ? extends T> rightFunction); | |
public <T> Either<T, R> mapLeft(Function<? super L, ? extends T> leftFunction) { | |
//noinspection unchecked | |
return map( | |
left -> ofLeft(leftFunction.apply(left)), | |
right -> (Either<T, R>) this | |
); | |
} | |
public <T> Either<L, T> mapRight(Function<? super R, ? extends T> rightFunction) { | |
//noinspection unchecked | |
return map( | |
left -> (Either<L, T>) this, | |
right -> ofRight(rightFunction.apply(right)) | |
); | |
} | |
public L getLeft() { | |
return this.map(Function.identity(), right -> { | |
throw new NoSuchElementException(); | |
}); | |
} | |
public R getRight() { | |
return this.map(left -> { | |
throw new NoSuchElementException(); | |
}, Function.identity()); | |
} | |
public boolean hasLeft() { | |
return this.map(left -> true, right -> false); | |
} | |
public boolean hasRight() { | |
return this.map(left -> false, right -> true); | |
} | |
private static final class Left<L, R> extends Either<L, R> { | |
private final L left; | |
private Left(L left) { | |
if (left == null) | |
throw new NullPointerException(); | |
this.left = left; | |
} | |
@Override | |
public <T> T map(Function<? super L, ? extends T> leftFunction, Function<? super R, ? extends T> rightFunction) { | |
return leftFunction.apply(left); | |
} | |
} | |
private static final class Right<L, R> extends Either<L, R> { | |
private final R right; | |
private Right(R right) { | |
if (right == null) | |
throw new NullPointerException(); | |
this.right = right; | |
} | |
@Override | |
public <T> T map(Function<? super L, ? extends T> leftFunction, Function<? super R, ? extends T> rightFunction) { | |
return rightFunction.apply(right); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment