package org.leumasjaffe.container; import java.util.function.Consumer; import java.util.function.Function; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NonNull; @AllArgsConstructor(access=AccessLevel.PRIVATE) @Getter(AccessLevel.PACKAGE) // For JUnit tests only public class Either { public enum State { LEFT, RIGHT } T1 left; T2 right; public static Either ofLeft(@NonNull T1 left) { return new Either<>(left, null); } public static Either ofRight(@NonNull T2 right) { return new Either<>(null, right); } State getState() { return left == null ? State.RIGHT : State.LEFT; } public void setLeft(@NonNull T1 left) { this.right = null; this.left = left; } public void setRight(@NonNull T2 right) { this.right = right; this.left = null; } public void consume(@NonNull Consumer fLeft, @NonNull Consumer fRight) { switch (getState()) { case LEFT: fLeft.accept(left); return; case RIGHT: fRight.accept(right); return; default: throw new IllegalStateException(); } } public Either map(@NonNull Function fLeft, @NonNull Function fRight) { switch (getState()) { case LEFT: return Either.ofLeft(fLeft.apply(left)); case RIGHT: return Either.ofRight(fRight.apply(right)); default: throw new IllegalStateException(); } } public Either mapLeft(@NonNull Function fLeft) { switch (getState()) { case LEFT: return Either.ofLeft(fLeft.apply(left)); case RIGHT: return Either.ofRight(right); default: throw new IllegalStateException(); } } public Either mapRight(@NonNull Function fRight) { switch (getState()) { case LEFT: return Either.ofLeft(left); case RIGHT: return Either.ofRight(fRight.apply(right)); default: throw new IllegalStateException(); } } public static Function identity() { return (x) -> x; } public static Function discard() { return (x) -> null; } public R unify(@NonNull Function fLeft, @NonNull Function fRight) { switch (getState()) { case LEFT: return fLeft.apply(left); case RIGHT: return fRight.apply(right); default: throw new IllegalStateException(); } } }