diff options
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/data')
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)); + }; + } +} |
