summaryrefslogtreecommitdiff
path: root/base/src/main/java/bjc/utils/funcdata/theory
diff options
context:
space:
mode:
Diffstat (limited to 'base/src/main/java/bjc/utils/funcdata/theory')
-rw-r--r--base/src/main/java/bjc/utils/funcdata/theory/Bifunctor.java139
-rw-r--r--base/src/main/java/bjc/utils/funcdata/theory/Functor.java39
2 files changed, 178 insertions, 0 deletions
diff --git a/base/src/main/java/bjc/utils/funcdata/theory/Bifunctor.java b/base/src/main/java/bjc/utils/funcdata/theory/Bifunctor.java
new file mode 100644
index 0000000..13c1709
--- /dev/null
+++ b/base/src/main/java/bjc/utils/funcdata/theory/Bifunctor.java
@@ -0,0 +1,139 @@
+package bjc.utils.funcdata.theory;
+
+import java.util.function.Function;
+
+/**
+ * A functor over a pair of heterogeneous types
+ *
+ * @author ben
+ * @param <LeftType>
+ * The type stored on the 'left' of the pair
+ * @param <RightType>
+ * The type stored on the 'right' of the pair
+ *
+ */
+public interface Bifunctor<LeftType, RightType> {
+ /**
+ * Alias for functor mapping.
+ *
+ * @author EVE
+ *
+ * @param <OldLeft>
+ * @param <OldRight>
+ * @param <NewLeft>
+ * @param <NewRight>
+ */
+ public interface BifunctorMap<OldLeft, OldRight, NewLeft, NewRight>
+ extends Function<Bifunctor<OldLeft, OldRight>, Bifunctor<NewLeft, NewRight>> {
+
+ }
+
+ /**
+ * Alias for left functor mapping.
+ *
+ * @author EVE
+ *
+ * @param <OldLeft>
+ * @param <OldRight>
+ * @param <NewLeft>
+ */
+ public interface LeftBifunctorMap<OldLeft, OldRight, NewLeft>
+ extends BifunctorMap<OldLeft, OldRight, NewLeft, OldRight> {
+
+ }
+
+ /**
+ * Alias for right functor mapping.
+ *
+ * @author EVE
+ *
+ * @param <OldLeft>
+ * @param <OldRight>
+ * @param <NewRight>
+ */
+ public interface RightBifunctorMap<OldLeft, OldRight, NewRight>
+ extends BifunctorMap<OldLeft, OldRight, OldLeft, NewRight> {
+
+ }
+
+ /**
+ * Lift a pair of functions to a single function that maps over both
+ * parts of a pair
+ *
+ * @param <OldLeft>
+ * The old left type of the pair
+ * @param <OldRight>
+ * The old right type of the pair
+ * @param <NewLeft>
+ * The new left type of the pair
+ * @param <NewRight>
+ * The new right type of the pair
+ * @param leftFunc
+ * The function that maps over the left of the pair
+ * @param rightFunc
+ * The function that maps over the right of the pair
+ * @return A function that maps over both parts of the pair
+ */
+ public default <OldLeft, OldRight, NewLeft, NewRight> BifunctorMap<OldLeft, OldRight, NewLeft, NewRight> bimap(
+ final Function<OldLeft, NewLeft> leftFunc, final Function<OldRight, NewRight> rightFunc) {
+ final BifunctorMap<OldLeft, OldRight, NewLeft, NewRight> bimappedFunc = (argPair) -> {
+ final LeftBifunctorMap<OldLeft, OldRight, NewLeft> leftMapper = argPair.fmapLeft(leftFunc);
+
+ final Bifunctor<NewLeft, OldRight> leftMappedFunctor = leftMapper.apply(argPair);
+ final RightBifunctorMap<NewLeft, OldRight, NewRight> rightMapper = leftMappedFunctor
+ .fmapRight(rightFunc);
+
+ return rightMapper.apply(leftMappedFunctor);
+ };
+
+ return bimappedFunc;
+ }
+
+ /**
+ * Lift a function to operate over the left part of this pair
+ *
+ * @param <OldLeft>
+ * The old left type of the pair
+ * @param <OldRight>
+ * The old right type of the pair
+ * @param <NewLeft>
+ * The new left type of the pair
+ * @param func
+ * The function to lift to work over the left side of the
+ * pair
+ * @return The function lifted to work over the left side of bifunctors
+ */
+ public <OldLeft, OldRight, NewLeft> LeftBifunctorMap<OldLeft, OldRight, NewLeft> fmapLeft(
+ Function<OldLeft, NewLeft> func);
+
+ /**
+ * Lift a function to operate over the right part of this pair
+ *
+ * @param <OldLeft>
+ * The old left type of the pair
+ * @param <OldRight>
+ * The old right type of the pair
+ * @param <NewRight>
+ * The new right type of the pair
+ * @param func
+ * The function to lift to work over the right side of
+ * the pair
+ * @return The function lifted to work over the right side of bifunctors
+ */
+ public <OldLeft, OldRight, NewRight> RightBifunctorMap<OldLeft, OldRight, NewRight> fmapRight(
+ Function<OldRight, NewRight> func);
+
+ /**
+ * Get the value contained on the left of this bifunctor
+ *
+ * @return The value on the left side of this bifunctor
+ */
+ public LeftType getLeft();
+
+ /**
+ * Get the value contained on the right of this bifunctor
+ *
+ * @return The value on the right of this bifunctor
+ */
+ public RightType getRight();
+}
diff --git a/base/src/main/java/bjc/utils/funcdata/theory/Functor.java b/base/src/main/java/bjc/utils/funcdata/theory/Functor.java
new file mode 100644
index 0000000..1c53284
--- /dev/null
+++ b/base/src/main/java/bjc/utils/funcdata/theory/Functor.java
@@ -0,0 +1,39 @@
+package bjc.utils.funcdata.theory;
+
+import java.util.function.Function;
+
+/**
+ * Represents a container or context some sort usually, but the precise
+ * definition is that it represents exactly what it is defined as
+ *
+ * @author ben
+ * @param <ContainedType>
+ * The value inside the functor
+ */
+public interface Functor<ContainedType> {
+ /**
+ * Converts a normal function to operate over values in a functor.
+ *
+ * N.B: Even though the type signature implies that you can apply the
+ * resulting function to any type of functor, it is only safe to call it
+ * on instances of the type of functor you called fmap on.
+ *
+ * @param <ArgType>
+ * The argument of the function
+ * @param <ReturnType>
+ * The return type of the function
+ * @param func
+ * The function to convert
+ * @return The passed in function converted to work over a particular
+ * type of functors
+ */
+ public <ArgType, ReturnType> Function<Functor<ArgType>, Functor<ReturnType>> fmap(
+ Function<ArgType, ReturnType> func);
+
+ /**
+ * Retrieve the thing inside this functor
+ *
+ * @return The thing inside this functor
+ */
+ public ContainedType getValue();
+}