summaryrefslogtreecommitdiff
path: root/src/main/java/bjc
diff options
context:
space:
mode:
authorBen Culkin <scorpress@gmail.com>2020-12-14 18:22:24 -0500
committerBen Culkin <scorpress@gmail.com>2020-12-14 18:22:24 -0500
commit8e3df549064103a03917b193ed4369a9d50383c7 (patch)
tree3dcdfb48e87a9babac2daaf56305ac7c60c7ac56 /src/main/java/bjc
parent0a8f34c27c6ef93c5c94d17728af62c7607e225f (diff)
Either no longer implements Pair
From a conceptual stand-point, this never really made sense.
Diffstat (limited to 'src/main/java/bjc')
-rw-r--r--src/main/java/bjc/data/Either.java221
1 files changed, 118 insertions, 103 deletions
diff --git a/src/main/java/bjc/data/Either.java b/src/main/java/bjc/data/Either.java
index e4bc63d..75447f2 100644
--- a/src/main/java/bjc/data/Either.java
+++ b/src/main/java/bjc/data/Either.java
@@ -1,7 +1,7 @@
package bjc.data;
-import java.util.function.BiFunction;
-import java.util.function.Function;
+import java.util.*;
+import java.util.function.*;
/**
* Represents a pair where only one side has a value.
@@ -15,7 +15,7 @@ import java.util.function.Function;
* The type that could be on the right.
*
*/
-public class Either<LeftType, RightType> implements Pair<LeftType, RightType> {
+public class Either<LeftType, RightType> {
/**
* Create a new either with the left value occupied.
*
@@ -72,123 +72,138 @@ public class Either<LeftType, RightType> implements Pair<LeftType, RightType> {
}
}
- @Override
- public <BoundLeft, BoundRight> Pair<BoundLeft, BoundRight> bind(
- final BiFunction<LeftType, RightType, Pair<BoundLeft, BoundRight>> binder) {
- if (binder == null) throw new NullPointerException("Binder must not be null");
-
- return binder.apply(leftVal, rightVal);
+ /**
+ * Perform a mapping over this either.
+ *
+ * @param <NewLeft> The new left type.
+ * @param <NewRight> The new right type.
+ *
+ * @param leftFunc The function to apply if this is a left either.
+ * @param rightFunc The function to apply if this is a right either.
+ *
+ * @return A new either, containing a value transformed by the appropriate function.
+ */
+ public <NewLeft, NewRight> Either<NewLeft, NewRight> map(
+ Function<LeftType, NewLeft> leftFunc,
+ Function<RightType, NewRight> rightFunc)
+ {
+ if (isLeft) return left(leftFunc.apply(leftVal));
+ else return right(rightFunc.apply(rightVal));
}
-
- @Override
- public <BoundLeft> Pair<BoundLeft, RightType>
- bindLeft(final Function<LeftType, Pair<BoundLeft, RightType>> leftBinder) {
- if (leftBinder == null) throw new NullPointerException("Left binder must not be null");
-
- if (isLeft) return leftBinder.apply(leftVal);
- else return new Either<>(null, rightVal);
+
+ /**
+ * Extract the value from this Either.
+ *
+ * @param <Common> The common type to extract.
+ *
+ * @param leftHandler The function to handle left-values.
+ * @param rightHandler The function to handle right-values.
+ *
+ * @return The result of applying the proper function.
+ */
+ public <Common> Common extract(
+ Function<LeftType, Common> leftHandler,
+ Function<RightType, Common> rightHandler)
+ {
+ if (isLeft) return leftHandler.apply(leftVal);
+ else return rightHandler.apply(rightVal);
}
-
- @Override
- public <BoundRight> Pair<LeftType, BoundRight> bindRight(
- final Function<RightType, Pair<LeftType, BoundRight>> rightBinder) {
- if (rightBinder == null) throw new NullPointerException("Right binder must not be null");
-
- if (isLeft) return new Either<>(leftVal, null);
- else return rightBinder.apply(rightVal);
+
+ /**
+ * Perform an action on this either.
+ *
+ * @param leftHandler The handler of left values.
+ * @param rightHandler The handler of right values.
+ */
+ public void pick(
+ Consumer<LeftType> leftHandler, Consumer<RightType> rightHandler)
+ {
+ if (isLeft) leftHandler.accept(leftVal);
+ else rightHandler.accept(rightVal);
}
- @Override
- public <OtherLeft, OtherRight, CombinedLeft, CombinedRight>
- Pair<CombinedLeft, CombinedRight>
- combine(final Pair<OtherLeft, OtherRight> otherPair,
- final BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner,
- final BiFunction<RightType, OtherRight,
- CombinedRight> 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) -> {
- CombinedLeft cLeft = leftCombiner.apply(leftVal, otherLeft);
+ /**
+ * Check if this either is left-aligned (has the left value filled,
+ * not the right value).
+ *
+ * @return Whether this either is left-aligned.
+ */
+ public boolean isLeft() {
+ return isLeft;
+ }
- return new Either<>(cLeft, null);
- });
- } else {
- return otherPair.bind((otherLeft, otherRight) -> {
- CombinedRight cRight = rightCombiner.apply(rightVal, otherRight);
+ /**
+ * Get the left value of this either if there is one.
+ *
+ * @return An optional containing the left value, if there is one.
+ */
+ public Optional<LeftType> getLeft() {
+ return Optional.ofNullable(leftVal);
+ }
- return new Either<>(null, cRight);
- });
+ /**
+ * Get the left value of this either, or get a {@link NoSuchElementException}
+ * if there isn't one.
+ *
+ * @return The left value of this either.
+ *
+ * @throws NoSuchElementException If this either doesn't have a left value.
+ */
+ public LeftType forceLeft() {
+ if (isLeft)
+ {
+ return leftVal;
+ } else
+ {
+ throw new NoSuchElementException("Either has no left value, is right value");
}
}
- @Override
- public <NewLeft> Pair<NewLeft, RightType>
- mapLeft(final Function<LeftType, NewLeft> mapper) {
- if (mapper == null) throw new NullPointerException("Mapper must not be null");
-
- if (isLeft) return new Either<>(mapper.apply(leftVal), null);
- else return new Either<>(null, rightVal);
- }
-
- @Override
- public <NewRight> Pair<LeftType, NewRight>
- mapRight(final Function<RightType, NewRight> mapper) {
- if (mapper == null) throw new NullPointerException("Mapper must not be null");
-
- if (isLeft) return new Either<>(leftVal, null);
- else return new Either<>(null, mapper.apply(rightVal));
+ /**
+ * Get the right value of this either if there is one.
+ *
+ * @return An optional containing the right value, if there is one.
+ */
+ public Optional<RightType> getRight() {
+ return Optional.ofNullable(rightVal);
}
-
- @Override
- public <MergedType> MergedType
- merge(final BiFunction<LeftType, RightType, MergedType> merger) {
- if (merger == null) throw new NullPointerException("Merger must not be null");
-
- return merger.apply(leftVal, rightVal);
+
+ /**
+ * Get the right value of this either, or get a {@link NoSuchElementException}
+ * if there isn't one.
+ *
+ * @return The right value of this either.
+ *
+ * @throws NoSuchElementException If this either doesn't have a right value.
+ */
+ public RightType forceRight() {
+ if (isLeft)
+ {
+ throw new NoSuchElementException("Either has no right value, has left value");
+ } else
+ {
+ return rightVal;
+ }
}
-
+
+ // Misc. overrides
+
@Override
public int hashCode() {
- final int prime = 31;
-
- int result = 1;
- result = prime * result + (isLeft ? 1231 : 1237);
- result = prime * result + (leftVal == null ? 0 : leftVal.hashCode());
- result = prime * result + (rightVal == null ? 0 : rightVal.hashCode());
-
- return result;
+ return Objects.hash(isLeft, leftVal, rightVal);
}
@Override
- public boolean equals(final Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (!(obj instanceof Either<?, ?>)) return false;
-
- final Either<?, ?> other = (Either<?, ?>) obj;
-
- if (isLeft != other.isLeft) return false;
-
- if (leftVal == null) {
- if (other.leftVal != null) return false;
- } else if (!leftVal.equals(other.leftVal)) {
- return false;
- }
-
- if (rightVal == null) {
- if (other.rightVal != null) return false;
- } else if (!rightVal.equals(other.rightVal)) {
- return false;
- }
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+
+ Either<?, ?> other = (Either<?, ?>) obj;
- return true;
+ return isLeft == other.isLeft
+ && Objects.equals(leftVal, other.leftVal)
+ && Objects.equals(rightVal, other.rightVal);
}
@Override