summaryrefslogtreecommitdiff
path: root/src/main/java/bjc/data/IHolder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/bjc/data/IHolder.java')
-rw-r--r--src/main/java/bjc/data/IHolder.java163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/main/java/bjc/data/IHolder.java b/src/main/java/bjc/data/IHolder.java
new file mode 100644
index 0000000..e56e23e
--- /dev/null
+++ b/src/main/java/bjc/data/IHolder.java
@@ -0,0 +1,163 @@
+package bjc.data;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.UnaryOperator;
+
+import bjc.data.internals.BoundListHolder;
+import bjc.data.internals.WrappedLazy;
+import bjc.data.internals.WrappedOption;
+import bjc.funcdata.FunctionalList;
+import bjc.funcdata.theory.Functor;
+
+/**
+ * A holder of a single value.
+ *
+ * @author ben
+ *
+ * @param <ContainedType>
+ * The type of value held.
+ */
+public interface IHolder<ContainedType> extends Functor<ContainedType> {
+ /**
+ * Bind a function across the value in this container.
+ *
+ * @param <BoundType>
+ * The type of value in this container.
+ *
+ * @param binder
+ * The function to bind to the value.
+ *
+ * @return A holder from binding the value.
+ */
+ public <BoundType> IHolder<BoundType> bind(Function<ContainedType, IHolder<BoundType>> binder);
+
+ /**
+ * Apply an action to the value.
+ *
+ * @param action
+ * The action to apply to the value.
+ */
+ public default void doWith(final Consumer<? super ContainedType> action) {
+ transform(value -> {
+ action.accept(value);
+
+ return value;
+ });
+ }
+
+ @Override
+ default <ArgType, ReturnType> Function<Functor<ArgType>, Functor<ReturnType>> fmap(
+ final Function<ArgType, ReturnType> func) {
+ return argumentFunctor -> {
+ if(!(argumentFunctor instanceof IHolder<?>)) {
+ final String msg = "This functor only supports mapping over instances of IHolder";
+
+ throw new IllegalArgumentException(msg);
+ }
+
+ final IHolder<ArgType> holder = (IHolder<ArgType>) argumentFunctor;
+
+ return holder.map(func);
+ };
+ }
+
+ @Override
+ public default ContainedType getValue() {
+ return unwrap(value -> value);
+ }
+
+ /**
+ * Lifts a function to bind over 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 <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);
+ }
+
+ /**
+ * Create a new holder with a mapped version of the value in this
+ * holder.
+ *
+ * Does not change the internal state of this holder.
+ *
+ * @param <MappedType>
+ * The type of the mapped value.
+ *
+ * @param mapper
+ * The function to do mapping with.
+ *
+ * @return A holder with the mapped value
+ */
+ public <MappedType> IHolder<MappedType> map(Function<ContainedType, MappedType> mapper);
+
+ /**
+ * Replace the held value with a new one.
+ *
+ * @param newValue
+ * The value to hold instead.
+ *
+ * @return The holder itself.
+ */
+ public default IHolder<ContainedType> replace(final ContainedType newValue) {
+ return transform(oldValue -> {
+ return newValue;
+ });
+ }
+
+ /**
+ * Transform the value held in this holder.
+ *
+ * @param transformer
+ * The function to transform the value with.
+ *
+ * @return The holder itself, for easy chaining.
+ */
+ public IHolder<ContainedType> transform(UnaryOperator<ContainedType> transformer);
+
+ /**
+ * Unwrap the value contained in this holder so that it is no longer
+ * held.
+ *
+ * @param <UnwrappedType>
+ * The type of the unwrapped value.
+ *
+ * @param unwrapper
+ * The function to use to unwrap the value.
+ *
+ * @return The unwrapped held value.
+ */
+ public <UnwrappedType> UnwrappedType unwrap(Function<ContainedType, UnwrappedType> unwrapper);
+}