summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java/bjc/utils/data
diff options
context:
space:
mode:
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/data')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/BoundLazy.java8
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java60
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java61
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java52
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java82
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/IPair.java72
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/Identity.java8
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java9
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java48
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java79
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/Option.java74
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/Pair.java16
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/WrappedLazy.java69
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/WrappedOption.java89
14 files changed, 702 insertions, 25 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazy.java
index ce47eb9..9ab3c05 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazy.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazy.java
@@ -96,4 +96,12 @@ class BoundLazy<OldType, BoundContainedType>
return boundHolder.unwrap(unwrapper);
}
+
+ @Override
+ public <NewType> Function<BoundContainedType, IHolder<NewType>> lift(
+ Function<BoundContainedType, NewType> func) {
+ return (val) -> {
+ return new Lazy<>(func.apply(val));
+ };
+ }
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java
index a49bb9a..1635e06 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java
@@ -90,8 +90,8 @@ class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight>
}
@Override
- public <MergedType> MergedType merge(
- BiFunction<NewLeft, NewRight, MergedType> merger) {
+ public <MergedType> MergedType
+ merge(BiFunction<NewLeft, NewRight, MergedType> merger) {
if (!pairBound) {
boundPair = binder.apply(leftSupplier.get(),
rightSupplier.get());
@@ -110,4 +110,60 @@ class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight>
return "(un-materialized)";
}
+
+ @Override
+ public <NewLeftType> IPair<NewLeftType, NewRight>
+ mapLeft(Function<NewLeft, NewLeftType> mapper) {
+ Supplier<NewLeftType> leftSupp = () -> {
+ if (!pairBound) {
+ NewLeft leftVal = binder
+ .apply(leftSupplier.get(), rightSupplier.get())
+ .getLeft();
+
+ return mapper.apply(leftVal);
+ }
+
+ return mapper.apply(boundPair.getLeft());
+ };
+
+ Supplier<NewRight> rightSupp = () -> {
+ if (!pairBound) {
+ return binder
+ .apply(leftSupplier.get(), rightSupplier.get())
+ .getRight();
+ }
+
+ return boundPair.getRight();
+ };
+
+ return new LazyPair<>(leftSupp, rightSupp);
+ }
+
+ @Override
+ public <NewRightType> IPair<NewLeft, NewRightType>
+ mapRight(Function<NewRight, NewRightType> mapper) {
+ Supplier<NewLeft> leftSupp = () -> {
+ if (!pairBound) {
+ return binder
+ .apply(leftSupplier.get(), rightSupplier.get())
+ .getLeft();
+ }
+
+ return boundPair.getLeft();
+ };
+
+ Supplier<NewRightType> rightSupp = () -> {
+ if (!pairBound) {
+ NewRight rightVal = binder
+ .apply(leftSupplier.get(), rightSupplier.get())
+ .getRight();
+
+ return mapper.apply(rightVal);
+ }
+
+ return mapper.apply(boundPair.getRight());
+ };
+
+ return new LazyPair<>(leftSupp, rightSupp);
+ }
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java
new file mode 100644
index 0000000..fcb62f6
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java
@@ -0,0 +1,61 @@
+package bjc.utils.data;
+
+import java.util.function.Function;
+import java.util.function.UnaryOperator;
+
+import bjc.utils.funcdata.IFunctionalList;
+
+class BoundListHolder<ContainedType> implements IHolder<ContainedType> {
+ private IFunctionalList<IHolder<ContainedType>> heldHolders;
+
+ public BoundListHolder(
+ IFunctionalList<IHolder<ContainedType>> toHold) {
+ heldHolders = toHold;
+ }
+
+ @Override
+ public <BoundType> IHolder<BoundType> bind(
+ Function<ContainedType, IHolder<BoundType>> binder) {
+ IFunctionalList<IHolder<BoundType>> boundHolders = heldHolders
+ .map((containedHolder) -> {
+ return containedHolder.bind(binder);
+ });
+
+ return new BoundListHolder<>(boundHolders);
+ }
+
+ @Override
+ public <MappedType> IHolder<MappedType> map(
+ Function<ContainedType, MappedType> mapper) {
+ IFunctionalList<IHolder<MappedType>> mappedHolders = heldHolders
+ .map((containedHolder) -> {
+ return containedHolder.map(mapper);
+ });
+
+ return new BoundListHolder<>(mappedHolders);
+ }
+
+ @Override
+ public IHolder<ContainedType> transform(
+ UnaryOperator<ContainedType> transformer) {
+ heldHolders.forEach((containedHolder) -> {
+ containedHolder.transform(transformer);
+ });
+
+ return this;
+ }
+
+ @Override
+ public <UnwrappedType> UnwrappedType unwrap(
+ Function<ContainedType, UnwrappedType> unwrapper) {
+ return heldHolders.randItem().unwrap(unwrapper);
+ }
+
+ @Override
+ public <NewType> Function<ContainedType, IHolder<NewType>> lift(
+ Function<ContainedType, NewType> func) {
+ return (val) -> {
+ return new ListHolder<>(func.apply(val));
+ };
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java
index 037dddf..9e26924 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java
@@ -80,8 +80,8 @@ class HalfBoundLazyPair<OldType, NewLeft, NewRight>
}
@Override
- public <MergedType> MergedType merge(
- BiFunction<NewLeft, NewRight, MergedType> merger) {
+ public <MergedType> MergedType
+ merge(BiFunction<NewLeft, NewRight, MergedType> merger) {
if (!pairBound) {
boundPair = binder.apply(oldSupplier.get());
@@ -90,4 +90,52 @@ class HalfBoundLazyPair<OldType, NewLeft, NewRight>
return boundPair.merge(merger);
}
+
+ @Override
+ public <NewLeftType> IPair<NewLeftType, NewRight>
+ mapLeft(Function<NewLeft, NewLeftType> mapper) {
+ Supplier<NewLeftType> leftSupp = () -> {
+ if (pairBound) {
+ return mapper.apply(boundPair.getLeft());
+ }
+
+ NewLeft leftVal = binder.apply(oldSupplier.get()).getLeft();
+
+ return mapper.apply(leftVal);
+ };
+
+ Supplier<NewRight> rightSupp = () -> {
+ if (pairBound) {
+ return boundPair.getRight();
+ }
+
+ return binder.apply(oldSupplier.get()).getRight();
+ };
+
+ return new LazyPair<>(leftSupp, rightSupp);
+ }
+
+ @Override
+ public <NewRightType> IPair<NewLeft, NewRightType>
+ mapRight(Function<NewRight, NewRightType> mapper) {
+ Supplier<NewLeft> leftSupp = () -> {
+ if (pairBound) {
+ return boundPair.getLeft();
+ }
+
+ return binder.apply(oldSupplier.get()).getLeft();
+ };
+
+ Supplier<NewRightType> rightSupp = () -> {
+ if (pairBound) {
+ return mapper.apply(boundPair.getRight());
+ }
+
+ NewRight rightVal = binder.apply(oldSupplier.get()).getRight();
+
+ return mapper.apply(rightVal);
+ };
+
+ return new LazyPair<>(leftSupp, rightSupp);
+ }
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java
index ecf3f14..58ae5db 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java
@@ -4,6 +4,9 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.UnaryOperator;
+import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.theory.Functor;
+
/**
* A holder of a single value.
*
@@ -12,7 +15,7 @@ import java.util.function.UnaryOperator;
* @param <ContainedType>
* The type of value held
*/
-public interface IHolder<ContainedType> {
+public interface IHolder<ContainedType> extends Functor<ContainedType> {
/**
* Bind a function across the value in this container
*
@@ -22,8 +25,8 @@ public interface IHolder<ContainedType> {
* The function to bind to the value
* @return A holder from binding the value
*/
- public <BoundType> IHolder<BoundType> bind(
- Function<ContainedType, IHolder<BoundType>> binder);
+ public <BoundType> IHolder<BoundType>
+ bind(Function<ContainedType, IHolder<BoundType>> binder);
/**
* Apply an action to the value
@@ -31,7 +34,7 @@ public interface IHolder<ContainedType> {
* @param action
* The action to apply to the value
*/
- public default void doWith(Consumer<ContainedType> action) {
+ public default void doWith(Consumer<? super ContainedType> action) {
transform((value) -> {
action.accept(value);
@@ -39,13 +42,64 @@ public interface IHolder<ContainedType> {
});
}
+ @Override
+ default <ArgType, ReturnType>
+ Function<Functor<ArgType>, Functor<ReturnType>>
+ fmap(Function<ArgType, ReturnType> func) {
+ return (argumentFunctor) -> {
+ if (!(argumentFunctor instanceof IHolder<?>)) {
+ throw new IllegalArgumentException(
+ "This functor only supports mapping over instances of IHolder");
+ }
+
+ IHolder<ArgType> holder = (IHolder<ArgType>) argumentFunctor;
+
+ return holder.map(func);
+ };
+ }
+
+ @Override
+ public default ContainedType getValue() {
+ return unwrap((value) -> value);
+ }
+
/**
- * Get the value contained in this holder without changing it.
+ * Lifts a function to bind over this holder
*
- * @return The value held in this holder
+ * @param <NewType>
+ * The type of the functions return
+ * @param func
+ * The function to lift over the holder
+ * @return The function lifted over the holder
*/
- public default ContainedType getValue() {
- return unwrap((value) -> value);
+ public <NewType> Function<ContainedType, IHolder<NewType>>
+ lift(Function<ContainedType, NewType> func);
+
+ /**
+ * Make this holder lazy
+ *
+ * @return A lazy version of this holder
+ */
+ public default IHolder<ContainedType> makeLazy() {
+ return new WrappedLazy<>(this);
+ }
+
+ /**
+ * Make this holder a list
+ *
+ * @return A list version of this holder
+ */
+ public default IHolder<ContainedType> makeList() {
+ return new BoundListHolder<>(new FunctionalList<>(this));
+ }
+
+ /**
+ * Make this holder optional
+ *
+ * @return An optional version of this holder
+ */
+ public default IHolder<ContainedType> makeOptional() {
+ return new WrappedOption<>(this);
}
/**
@@ -60,8 +114,8 @@ public interface IHolder<ContainedType> {
* The function to do mapping with
* @return A holder with the mapped value
*/
- public <MappedType> IHolder<MappedType> map(
- Function<ContainedType, MappedType> mapper);
+ public <MappedType> IHolder<MappedType>
+ map(Function<ContainedType, MappedType> mapper);
/**
* Replace the held value with a new one
@@ -83,8 +137,8 @@ public interface IHolder<ContainedType> {
* The function to transform the value with
* @return The holder itself, for easy chaining
*/
- public IHolder<ContainedType> transform(
- UnaryOperator<ContainedType> transformer);
+ public IHolder<ContainedType>
+ transform(UnaryOperator<ContainedType> transformer);
/**
* Unwrap the value contained in this holder so that it is no longer
@@ -96,6 +150,6 @@ public interface IHolder<ContainedType> {
* The function to use to unwrap the value
* @return The unwrapped held value
*/
- public <UnwrappedType> UnwrappedType unwrap(
- Function<ContainedType, UnwrappedType> unwrapper);
+ public <UnwrappedType> UnwrappedType
+ unwrap(Function<ContainedType, UnwrappedType> unwrapper);
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java
index 316074e..707724b 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java
@@ -4,6 +4,8 @@ import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
+import bjc.utils.funcdata.theory.Bifunctor;
+
/**
* Represents a pair of values
*
@@ -14,7 +16,8 @@ import java.util.function.Function;
* The type of the right side of the pair
*
*/
-public interface IPair<LeftType, RightType> {
+public interface IPair<LeftType, RightType>
+ extends Bifunctor<LeftType, RightType> {
/**
* Bind a function across the values in this pair
*
@@ -68,11 +71,45 @@ public interface IPair<LeftType, RightType> {
});
}
+ @Override
+ default <OldLeft, OldRight, NewLeft>
+ Function<Bifunctor<OldLeft, OldRight>, Bifunctor<NewLeft, OldRight>>
+ fmapLeft(Function<OldLeft, NewLeft> func) {
+ return (argumentPair) -> {
+ if (!(argumentPair instanceof IPair<?, ?>)) {
+ throw new IllegalArgumentException(
+ "This function can only be applied to instances of IPair");
+ }
+
+ IPair<OldLeft, OldRight> argPair = (IPair<OldLeft, OldRight>) argumentPair;
+
+ return argPair.mapLeft(func);
+ };
+ }
+
+ @Override
+ default <OldLeft, OldRight, NewRight>
+ Function<Bifunctor<OldLeft, OldRight>, Bifunctor<OldLeft, NewRight>>
+
+ fmapRight(Function<OldRight, NewRight> func) {
+ return (argumentPair) -> {
+ if (!(argumentPair instanceof IPair<?, ?>)) {
+ throw new IllegalArgumentException(
+ "This function can only be applied to instances of IPair");
+ }
+
+ IPair<OldLeft, OldRight> argPair = (IPair<OldLeft, OldRight>) argumentPair;
+
+ return argPair.mapRight(func);
+ };
+ }
+
/**
* Get the value on the left side of the pair
*
* @return The value on the left side of the pair
*/
+ @Override
public default LeftType getLeft() {
return merge((leftValue, rightValue) -> leftValue);
}
@@ -82,11 +119,40 @@ public interface IPair<LeftType, RightType> {
*
* @return The value on the right side of the pair
*/
+ @Override
public default RightType getRight() {
return merge((leftValue, rightValue) -> rightValue);
}
/**
+ * Transform the value on the left side of the pair. Doesn't modify the
+ * pair
+ *
+ * @param <NewLeft>
+ * The new type of the left part of the pair
+ * @param mapper
+ * The function to use to transform the left part of the
+ * pair
+ * @return The pair, with its left part transformed
+ */
+ public <NewLeft> IPair<NewLeft, RightType>
+ mapLeft(Function<LeftType, NewLeft> mapper);
+
+ /**
+ * Transform the value on the right side of the pair. Doesn't modify
+ * the pair
+ *
+ * @param <NewRight>
+ * The new type of the right part of the pair
+ * @param mapper
+ * The function to use to transform the right part of the
+ * pair
+ * @return The pair, with its right part transformed
+ */
+ public <NewRight> IPair<LeftType, NewRight>
+ mapRight(Function<RightType, NewRight> mapper);
+
+ /**
* Merge the two values in this pair into a single value
*
* @param <MergedType>
@@ -95,6 +161,6 @@ public interface IPair<LeftType, RightType> {
* The function to use for merging
* @return The pair, merged into a single value
*/
- public <MergedType> MergedType merge(
- BiFunction<LeftType, RightType, MergedType> merger);
+ public <MergedType> MergedType
+ merge(BiFunction<LeftType, RightType, MergedType> merger);
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java b/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java
index dcc7bef..f42ceb7 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java
@@ -112,4 +112,12 @@ public class Identity<ContainedType> implements IHolder<ContainedType> {
Function<ContainedType, UnwrappedType> unwrapper) {
return unwrapper.apply(heldValue);
}
+
+ @Override
+ public <NewType> Function<ContainedType, IHolder<NewType>> lift(
+ Function<ContainedType, NewType> func) {
+ return (val) -> {
+ return new Identity<>(func.apply(val));
+ };
+ }
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java
index 061486e..62b0bb0 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java
@@ -133,4 +133,13 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> {
return unwrapper.apply(heldValue);
}
+
+ @Override
+ public <NewType> Function<ContainedType, IHolder<NewType>> lift(
+ Function<ContainedType, NewType> func) {
+ // TODO Auto-generated method stub
+ return (val) -> {
+ return new Lazy<>(func.apply(val));
+ };
+ }
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java
index b02d9cb..6f1be10 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java
@@ -115,8 +115,8 @@ public class LazyPair<LeftType, RightType>
}
@Override
- public <MergedType> MergedType merge(
- BiFunction<LeftType, RightType, MergedType> merger) {
+ public <MergedType> MergedType
+ merge(BiFunction<LeftType, RightType, MergedType> merger) {
if (!leftMaterialized) {
leftValue = leftSupplier.get();
@@ -154,4 +154,48 @@ public class LazyPair<LeftType, RightType>
return sb.toString();
}
+
+ @Override
+ public <NewLeft> IPair<NewLeft, RightType>
+ mapLeft(Function<LeftType, NewLeft> mapper) {
+ Supplier<NewLeft> leftSupp = () -> {
+ if (leftMaterialized) {
+ return mapper.apply(leftValue);
+ }
+
+ return mapper.apply(leftSupplier.get());
+ };
+
+ Supplier<RightType> rightSupp = () -> {
+ if (rightMaterialized) {
+ return rightValue;
+ }
+
+ return rightSupplier.get();
+ };
+
+ return new LazyPair<>(leftSupp, rightSupp);
+ }
+
+ @Override
+ public <NewRight> IPair<LeftType, NewRight>
+ mapRight(Function<RightType, NewRight> mapper) {
+ Supplier<LeftType> leftSupp = () -> {
+ if (leftMaterialized) {
+ return leftValue;
+ }
+
+ return leftSupplier.get();
+ };
+
+ Supplier<NewRight> rightSupp = () -> {
+ if (rightMaterialized) {
+ return mapper.apply(rightValue);
+ }
+
+ return mapper.apply(rightSupplier.get());
+ };
+
+ return new LazyPair<>(leftSupp, rightSupp);
+ }
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java
new file mode 100644
index 0000000..8dc33d3
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java
@@ -0,0 +1,79 @@
+package bjc.utils.data;
+
+import java.util.function.Function;
+import java.util.function.UnaryOperator;
+
+import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
+
+/**
+ * A holder that represents a set of non-deterministic computations
+ *
+ * @author ben
+ *
+ * @param <ContainedType>
+ * The type of contained value
+ */
+public class ListHolder<ContainedType> implements IHolder<ContainedType> {
+ private IFunctionalList<ContainedType> heldValues;
+
+ private ListHolder(IFunctionalList<ContainedType> toHold) {
+ heldValues = toHold;
+ }
+
+ /**
+ * Create a new list holder
+ *
+ * @param values
+ * The possible values for the computation
+ */
+ @SafeVarargs
+ public ListHolder(ContainedType... values) {
+ heldValues = new FunctionalList<>();
+
+ if (values != null) {
+ for (ContainedType containedValue : values) {
+ heldValues.add(containedValue);
+ }
+ }
+ }
+
+ @Override
+ public <BoundType> IHolder<BoundType> bind(
+ Function<ContainedType, IHolder<BoundType>> binder) {
+ IFunctionalList<IHolder<BoundType>> boundValues = heldValues
+ .map(binder);
+
+ return new BoundListHolder<>(boundValues);
+ }
+
+ @Override
+ public <MappedType> IHolder<MappedType> map(
+ Function<ContainedType, MappedType> mapper) {
+ IFunctionalList<MappedType> mappedValues = heldValues.map(mapper);
+
+ return new ListHolder<>(mappedValues);
+ }
+
+ @Override
+ public IHolder<ContainedType> transform(
+ UnaryOperator<ContainedType> transformer) {
+ heldValues = heldValues.map(transformer);
+
+ return this;
+ }
+
+ @Override
+ public <UnwrappedType> UnwrappedType unwrap(
+ Function<ContainedType, UnwrappedType> unwrapper) {
+ return unwrapper.apply(heldValues.randItem());
+ }
+
+ @Override
+ public <NewType> Function<ContainedType, IHolder<NewType>> lift(
+ Function<ContainedType, NewType> func) {
+ return (val) -> {
+ return new ListHolder<>(new FunctionalList<>(func.apply(val)));
+ };
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Option.java b/BJC-Utils2/src/main/java/bjc/utils/data/Option.java
new file mode 100644
index 0000000..9f6d448
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/Option.java
@@ -0,0 +1,74 @@
+package bjc.utils.data;
+
+import java.util.function.Function;
+import java.util.function.UnaryOperator;
+
+/**
+ * A holder that may or may not contain a value
+ *
+ * @author ben
+ *
+ * @param <ContainedType>
+ * The type of the value that may or may not be held
+ */
+public class Option<ContainedType> implements IHolder<ContainedType> {
+ private ContainedType held;
+
+ /**
+ * Create a new optional, using the given initial value
+ *
+ * @param seedValue
+ * The initial value for the optional
+ */
+ public Option(ContainedType seedValue) {
+ held = seedValue;
+ }
+
+ @Override
+ public <BoundType> IHolder<BoundType> bind(
+ Function<ContainedType, IHolder<BoundType>> binder) {
+ if (held == null) {
+ return new Option<>(null);
+ }
+
+ return binder.apply(held);
+ }
+
+ @Override
+ public <MappedType> IHolder<MappedType> map(
+ Function<ContainedType, MappedType> mapper) {
+ if (held == null) {
+ return new Option<>(null);
+ }
+
+ return new Option<>(mapper.apply(held));
+ }
+
+ @Override
+ public IHolder<ContainedType> transform(
+ UnaryOperator<ContainedType> transformer) {
+ if (held != null) {
+ held = transformer.apply(held);
+ }
+
+ return this;
+ }
+
+ @Override
+ public <UnwrappedType> UnwrappedType unwrap(
+ Function<ContainedType, UnwrappedType> unwrapper) {
+ if (held == null) {
+ return null;
+ }
+
+ return unwrapper.apply(held);
+ }
+
+ @Override
+ public <NewType> Function<ContainedType, IHolder<NewType>> lift(
+ Function<ContainedType, NewType> func) {
+ return (val) -> {
+ return new Option<>(func.apply(val));
+ };
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
index 05955b6..0d2c1b0 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
@@ -56,8 +56,8 @@ public class Pair<LeftType, RightType>
}
@Override
- public <MergedType> MergedType merge(
- BiFunction<LeftType, RightType, MergedType> merger) {
+ public <MergedType> MergedType
+ merge(BiFunction<LeftType, RightType, MergedType> merger) {
return merger.apply(leftValue, rightValue);
}
@@ -66,4 +66,16 @@ public class Pair<LeftType, RightType>
return "pair[l=" + leftValue.toString() + ", r="
+ rightValue.toString() + "]";
}
+
+ @Override
+ public <NewLeft> IPair<NewLeft, RightType>
+ mapLeft(Function<LeftType, NewLeft> mapper) {
+ return new Pair<>(mapper.apply(leftValue), rightValue);
+ }
+
+ @Override
+ public <NewRight> IPair<LeftType, NewRight>
+ mapRight(Function<RightType, NewRight> mapper) {
+ return new Pair<>(leftValue, mapper.apply(rightValue));
+ }
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/WrappedLazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/WrappedLazy.java
new file mode 100644
index 0000000..737482c
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/WrappedLazy.java
@@ -0,0 +1,69 @@
+package bjc.utils.data;
+
+import java.util.function.Function;
+import java.util.function.UnaryOperator;
+
+class WrappedLazy<ContainedType> implements IHolder<ContainedType> {
+ private IHolder<IHolder<ContainedType>> held;
+
+ // This has an extra parameter, because otherwise it erases to the same
+ // as the public one
+ private WrappedLazy(IHolder<IHolder<ContainedType>> wrappedHolder,
+ @SuppressWarnings("unused") boolean dummy) {
+ held = wrappedHolder;
+ }
+
+ public WrappedLazy(IHolder<ContainedType> wrappedHolder) {
+ held = new Lazy<>(wrappedHolder);
+ }
+
+ @Override
+ public <BoundType> IHolder<BoundType> bind(
+ Function<ContainedType, IHolder<BoundType>> binder) {
+ IHolder<IHolder<BoundType>> newHolder = held
+ .map((containedHolder) -> {
+ return containedHolder.bind(binder);
+ });
+
+ return new WrappedLazy<>(newHolder, false);
+ }
+
+ @Override
+ public <MappedType> IHolder<MappedType> map(
+ Function<ContainedType, MappedType> mapper) {
+ IHolder<IHolder<MappedType>> newHolder = held
+ .map((containedHolder) -> {
+ return containedHolder.map(mapper);
+ });
+
+ return new WrappedLazy<>(newHolder, false);
+ }
+
+ @Override
+ public IHolder<ContainedType> transform(
+ UnaryOperator<ContainedType> transformer) {
+ // FIXME this smells bad to me, but I can't figure out how else to
+ // do it
+ held.transform((containedHolder) -> {
+ return containedHolder.transform(transformer);
+ });
+
+ return this;
+ }
+
+ @Override
+ public <UnwrappedType> UnwrappedType unwrap(
+ Function<ContainedType, UnwrappedType> unwrapper) {
+ return held.unwrap((containedHolder) -> {
+ return containedHolder.unwrap(unwrapper);
+ });
+ }
+
+ @Override
+ public <NewType> Function<ContainedType, IHolder<NewType>> lift(
+ Function<ContainedType, NewType> func) {
+ return (val) -> {
+ return new Lazy<>(func.apply(val));
+ };
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/WrappedOption.java b/BJC-Utils2/src/main/java/bjc/utils/data/WrappedOption.java
new file mode 100644
index 0000000..c36cafa
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/WrappedOption.java
@@ -0,0 +1,89 @@
+package bjc.utils.data;
+
+import java.util.function.Function;
+import java.util.function.UnaryOperator;
+
+class WrappedOption<ContainedType> implements IHolder<ContainedType> {
+ private IHolder<IHolder<ContainedType>> held;
+
+ private WrappedOption(IHolder<IHolder<ContainedType>> toHold,
+ @SuppressWarnings("unused") boolean dummy) {
+ held = toHold;
+ }
+
+ public WrappedOption(IHolder<ContainedType> seedValue) {
+ held = new Option<>(seedValue);
+ }
+
+ @Override
+ public <BoundType> IHolder<BoundType> bind(
+ Function<ContainedType, IHolder<BoundType>> binder) {
+ IHolder<IHolder<BoundType>> newHolder = held
+ .map((containedHolder) -> {
+ return containedHolder.bind((containedValue) -> {
+ if (containedValue == null) {
+ return new Option<>(null);
+ }
+
+ return binder.apply(containedValue);
+ });
+ });
+
+ return new WrappedOption<>(newHolder, false);
+ }
+
+ @Override
+ public <MappedType> IHolder<MappedType> map(
+ Function<ContainedType, MappedType> mapper) {
+ IHolder<IHolder<MappedType>> newHolder = held
+ .map((containedHolder) -> {
+ return containedHolder.map((containedValue) -> {
+ if (containedValue == null) {
+ return null;
+ }
+
+ return mapper.apply(containedValue);
+ });
+ });
+
+ return new WrappedOption<>(newHolder, false);
+ }
+
+ @Override
+ public IHolder<ContainedType> transform(
+ UnaryOperator<ContainedType> transformer) {
+ held.transform((containedHolder) -> {
+ return containedHolder.transform((containedValue) -> {
+ if (containedValue == null) {
+ return null;
+ }
+
+ return transformer.apply(containedValue);
+ });
+ });
+
+ return this;
+ }
+
+ @Override
+ public <UnwrappedType> UnwrappedType unwrap(
+ Function<ContainedType, UnwrappedType> unwrapper) {
+ return held.unwrap((containedHolder) -> {
+ return containedHolder.unwrap((containedValue) -> {
+ if (containedValue == null) {
+ return null;
+ }
+
+ return unwrapper.apply(containedValue);
+ });
+ });
+ }
+
+ @Override
+ public <NewType> Function<ContainedType, IHolder<NewType>> lift(
+ Function<ContainedType, NewType> func) {
+ return (val) -> {
+ return new Option<>(func.apply(val));
+ };
+ }
+}