package bjc.utils.data; import java.util.function.BiFunction; import java.util.function.Function; /** * Represents a pair where only one side has a value * * @author ben * @param * The type that could be on the left * @param * The type that could be on the right * */ public class Either implements IPair { /** * Create a new either with the left value occupied * * @param * The type of the left value * @param * The type of the empty right value * @param left * The value to put on the left * @return An either with the left side occupied */ public static Either fromLeft(LeftType left) { return new Either<>(left, null); } /** * Create a new either with the right value occupied * * @param * The type of the empty left value * @param * The type of the right value * @param right * The value to put on the right * @return An either with the right side occupied */ public static Either fromRight(RightType right) { return new Either<>(null, right); } private LeftType leftVal; private RightType rightVal; private boolean isLeft; private Either(LeftType left, RightType right) { if(left == null) { rightVal = right; } else { leftVal = left; isLeft = true; } } @Override public IPair bind( BiFunction> binder) { if(binder == null) throw new NullPointerException("Binder must not be null"); return binder.apply(leftVal, rightVal); } @Override public IPair bindLeft( Function> leftBinder) { if(leftBinder == null) throw new NullPointerException("Left binder must not be null"); if(isLeft) return leftBinder.apply(leftVal); return new Either<>(null, rightVal); } @Override public IPair bindRight( Function> rightBinder) { if(rightBinder == null) throw new NullPointerException("Right binder must not be null"); if(isLeft) return new Either<>(leftVal, null); return rightBinder.apply(rightVal); } @Override public IPair combine( IPair otherPair, BiFunction leftCombiner, BiFunction rightCombiner) { if(otherPair == null) throw new NullPointerException("Other pair must not be null"); else if(leftCombiner == null) throw new NullPointerException("Left combiner must not be null"); else if(rightCombiner == null) throw new NullPointerException("Right combiner must not be null"); if(isLeft) return otherPair.bind((otherLeft, otherRight) -> { return new Either<>(leftCombiner.apply(leftVal, otherLeft), null); }); return otherPair.bind((otherLeft, otherRight) -> { return new Either<>(null, rightCombiner.apply(rightVal, otherRight)); }); } @Override public IPair mapLeft(Function mapper) { if(mapper == null) throw new NullPointerException("Mapper must not be null"); if(isLeft) return new Either<>(mapper.apply(leftVal), null); return new Either<>(null, rightVal); } @Override public IPair mapRight(Function mapper) { if(mapper == null) throw new NullPointerException("Mapper must not be null"); if(isLeft) return new Either<>(leftVal, null); return new Either<>(null, mapper.apply(rightVal)); } @Override public MergedType merge(BiFunction merger) { if(merger == null) throw new NullPointerException("Merger must not be null"); return merger.apply(leftVal, rightVal); } }