summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Culkin <scorpress@gmail.com>2022-10-08 14:47:21 -0400
committerBen Culkin <scorpress@gmail.com>2022-10-08 14:47:21 -0400
commit0f958b08b3446a866418aa485bb60c208d952033 (patch)
tree2a54b64036bacb2f1fbc60d17511eb904b15fe7d
parent08885862bee89602d7edc55144ea9b6af780bfa4 (diff)
Add a whole bunch of Optics
This adds a whole bunch of types/functions related to optics. With this batch, I've mainly gone for the concrete representation types, instead of var Laarhoven or profunctor representations. The concrete ones require less infrastructure, though they are not as easy to compose There's also a number of misc. things in here
-rw-r--r--src/main/java/bjc/data/CollectionUtils.java54
-rw-r--r--src/main/java/bjc/data/Holder.java4
-rw-r--r--src/main/java/bjc/functypes/Combinators.java40
-rw-r--r--src/main/java/bjc/functypes/Const.java19
-rw-r--r--src/main/java/bjc/functypes/Predicates.java (renamed from src/main/java/bjc/functypes/optics/Lens.java)29
-rw-r--r--src/main/java/bjc/functypes/ThrowFunction.java2
-rw-r--r--src/main/java/bjc/optics/Lens.java68
-rw-r--r--src/main/java/bjc/optics/LensX.java (renamed from src/main/java/bjc/functypes/optics/LensX.java)4
-rw-r--r--src/main/java/bjc/optics/Lenses.java (renamed from src/main/java/bjc/functypes/optics/Lenses.java)2
-rw-r--r--src/main/java/bjc/optics/MutableLens.java (renamed from src/main/java/bjc/functypes/optics/MutableLens.java)2
-rw-r--r--src/main/java/bjc/optics/Optic.java (renamed from src/main/java/bjc/functypes/optics/Optic.java)2
-rw-r--r--src/main/java/bjc/optics/PrismX.java (renamed from src/main/java/bjc/functypes/optics/PrismX.java)2
-rw-r--r--src/main/java/bjc/optics/impl/package-info.java (renamed from src/main/java/bjc/functypes/optics/impl/package-info.java)2
-rw-r--r--src/main/java/bjc/optics/package-info.java (renamed from src/main/java/bjc/functypes/optics/package-info.java)2
-rw-r--r--src/main/java/bjc/typeclasses/BiContainer.java (renamed from src/main/java/bjc/functypes/BiContainer.java)2
-rw-r--r--src/main/java/bjc/typeclasses/Container.java (renamed from src/main/java/bjc/functypes/Container.java)2
-rw-r--r--src/main/java/bjc/typeclasses/FunList.java55
-rw-r--r--src/main/java/bjc/typeclasses/FunctionalIsomorphism.java (renamed from src/main/java/bjc/functypes/FunctionalIsomorphism.java)2
-rw-r--r--src/main/java/bjc/typeclasses/Isomorphism.java (renamed from src/main/java/bjc/functypes/Isomorphism.java)2
-rw-r--r--src/main/java/bjc/typeclasses/ListC.java (renamed from src/main/java/bjc/functypes/ListC.java)2
-rw-r--r--src/main/java/bjc/typeclasses/Natural.java (renamed from src/main/java/bjc/functypes/Natural.java)36
-rw-r--r--src/main/java/bjc/typeclasses/PFLens.java18
-rw-r--r--src/main/java/bjc/typeclasses/package-info.java18
-rw-r--r--src/main/java/bjc/typeclasses/todo126
-rw-r--r--src/test/java/bjc/test/functypes/optics/LensesTest.java2
25 files changed, 464 insertions, 33 deletions
diff --git a/src/main/java/bjc/data/CollectionUtils.java b/src/main/java/bjc/data/CollectionUtils.java
new file mode 100644
index 0000000..08ef711
--- /dev/null
+++ b/src/main/java/bjc/data/CollectionUtils.java
@@ -0,0 +1,54 @@
+/*
+ * esodata - data structures of varying utility
+ * Copyright 2022, Ben Culkin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package bjc.data;
+
+import java.util.*;
+import java.util.function.Function;
+
+/**
+ * Various utilities for dealing w/ collections
+ * @author bjcul
+ *
+ */
+public class CollectionUtils {
+ /**
+ * Create a function that converts a collection into a map.
+ *
+ * @param <Val> The type of the values in the map
+ * @param <Idx> The type of the keys in the map
+ * @param <Ent> The type of the values in the collection
+ *
+ * @param keyFunc The function that determines keys
+ * @param valFunc The function that determines values
+ *
+ * @return A function which uses the provided function to create a map from a
+ * collection.
+ */
+ public static <Val, Idx, Ent> Function<Collection<Ent>, Map<Idx, Val>> indexBy(Function<Ent, Idx> keyFunc,
+ Function<Ent, Val> valFunc) {
+ return (coll) -> {
+ Map<Idx, Val> mep = new HashMap<>();
+
+ for (Ent ent : coll) {
+ mep.put(keyFunc.apply(ent), valFunc.apply(ent));
+ }
+
+ return mep;
+ };
+ }
+}
diff --git a/src/main/java/bjc/data/Holder.java b/src/main/java/bjc/data/Holder.java
index 4a1de75..57a5d6c 100644
--- a/src/main/java/bjc/data/Holder.java
+++ b/src/main/java/bjc/data/Holder.java
@@ -26,6 +26,7 @@ import bjc.data.internals.WrappedLazy;
import bjc.data.internals.WrappedOption;
import bjc.funcdata.FunctionalList;
import bjc.funcdata.theory.Functor;
+import bjc.typeclasses.Container;
/**
* A holder of a single value.
@@ -35,7 +36,8 @@ import bjc.funcdata.theory.Functor;
* @param <ContainedType>
* The type of value held.
*/
-public interface Holder<ContainedType> extends Functor<ContainedType> {
+public interface Holder<ContainedType> extends Functor<ContainedType>, Container<ContainedType, Holder<ContainedType>> {
+ // note: to really work, this should also take the binding parameter
/**
* Bind a function across the value in this container.
*
diff --git a/src/main/java/bjc/functypes/Combinators.java b/src/main/java/bjc/functypes/Combinators.java
index 0b157bb..14af611 100644
--- a/src/main/java/bjc/functypes/Combinators.java
+++ b/src/main/java/bjc/functypes/Combinators.java
@@ -301,14 +301,50 @@ public class Combinators {
// TODO: write a switch-like combinator that uses a KeyedList to get the desired
// fallthrough semantics
-
+
// TODO: non-shortcircuiting boolean combinators
-
+
+ /**
+ * Convert a function into one that takes a supplier as its parameter
+ *
+ * Note this is not as useful as the reverse, as we need to evaluate the
+ * supplier to call the function.
+ *
+ * @param <Input> The input type
+ * @param <Output> The output type
+ *
+ * @param f The function
+ *
+ * @return The function, taking a supplier as its first function
+ */
public static <Input, Output> Function<Supplier<Input>, Output> lazify(Function<Input, Output> f) {
return (supp) -> f.apply(supp.get());
}
+ /**
+ * Convert a lazy function into an eager one
+ *
+ * @param <Input> The input type
+ * @param <Output> The output type
+ *
+ * @param f A function that takes a supplier as its parameter
+ *
+ * @return A function which just takes a value
+ */
public static <Input, Output> Function<Input, Output> strictify(Function<Supplier<Input>, Output> f) {
return (val) -> f.apply(() -> val);
}
+
+ /**
+ * Convert a pure function into one that mutates a holder.
+ *
+ * @param <Input> The type of the function.
+ *
+ * @param f The function.
+ *
+ * @return A function that mutates a holder using the given function
+ */
+ public static <Input> Consumer<Holder<Input>> mutating(UnaryOperator<Input> f) {
+ return (hld) -> hld.transform(f);
+ }
} \ No newline at end of file
diff --git a/src/main/java/bjc/functypes/Const.java b/src/main/java/bjc/functypes/Const.java
new file mode 100644
index 0000000..2fc1606
--- /dev/null
+++ b/src/main/java/bjc/functypes/Const.java
@@ -0,0 +1,19 @@
+package bjc.functypes;
+
+import bjc.typeclasses.Container;
+
+public class Const<V, A> implements Container<V, Const<V, ?>>{
+ private V payload;
+
+ private Const(V payload) {
+ this.payload = payload;
+ }
+
+ public static <V, A> Const<V, A> of(V val) {
+ return new Const<>(val);
+ }
+
+ V get() {
+ return payload;
+ }
+}
diff --git a/src/main/java/bjc/functypes/optics/Lens.java b/src/main/java/bjc/functypes/Predicates.java
index c56a016..3977294 100644
--- a/src/main/java/bjc/functypes/optics/Lens.java
+++ b/src/main/java/bjc/functypes/Predicates.java
@@ -1,5 +1,6 @@
/*
- * esodata - data structures and other things, of varying utility
+ * esodata - data structures of varying utility
+ *
* Copyright 2022, Ben Culkin
*
* This program is free software: you can redistribute it and/or modify
@@ -15,16 +16,26 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes.optics;
+package bjc.functypes;
+
+import java.util.function.BiPredicate;
+import java.util.function.Predicate;
/**
- * A type-invariant var Laarhoven lens.
- *
+ * Various utility functions for predicates
* @author bjcul
*
- * @param <Whole> The item this lens can focus on
- * @param <Part> The field this lens focuses on
*/
-public interface Lens<Whole, Part> extends LensX<Whole, Whole, Part, Part> {
- // Alias type
-}
+public class Predicates {
+ /**
+ * A predicate for logical implication (!x || y)
+ *
+ * @param x The LHS
+ * @param y The RHS
+ *
+ * @return Whether the LHS implies the RHS
+ */
+ public static boolean implies(boolean x, boolean y) {
+ return !x || y;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/bjc/functypes/ThrowFunction.java b/src/main/java/bjc/functypes/ThrowFunction.java
index 2ec5bea..5c61161 100644
--- a/src/main/java/bjc/functypes/ThrowFunction.java
+++ b/src/main/java/bjc/functypes/ThrowFunction.java
@@ -20,6 +20,8 @@ package bjc.functypes;
import java.util.*;
import java.util.function.*;
+import bjc.typeclasses.Isomorphism;
+
/**
* An instance of {@link Function} that can throw an exception.
*
diff --git a/src/main/java/bjc/optics/Lens.java b/src/main/java/bjc/optics/Lens.java
new file mode 100644
index 0000000..be10eef
--- /dev/null
+++ b/src/main/java/bjc/optics/Lens.java
@@ -0,0 +1,68 @@
+/*
+ * esodata - data structures and other things, of varying utility
+ * Copyright 2022, Ben Culkin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package bjc.optics;
+
+import java.util.function.Function;
+import java.util.function.UnaryOperator;
+
+import bjc.typeclasses.BiContainer;
+
+/**
+ * A type-invariant var Laarhoven lens.
+ *
+ * @author bjcul
+ *
+ * @param <Whole> The item this lens can focus on
+ * @param <Part> The field this lens focuses on
+ */
+public interface Lens<Whole, Part> extends LensX<Whole, Whole, Part, Part>, BiContainer<Whole, Part, Lens<Whole, Part>> {
+ /**
+ * Modify a given whole using an operation
+ *
+ * @param source The whole to modify.
+ * @param mod The operation to use for modifying a part
+ *
+ * @return A modified whole
+ */
+ default Whole modify(Whole source, UnaryOperator<Part> mod) {
+ return set(source, mod.apply(get(source)));
+ }
+
+ /**
+ * Create a function which sets the part of a given whole.
+ *
+ * @param part The part to set
+ *
+ * @return A function that sets the given part on a whole.
+ */
+ default Function<Whole, Whole> setting(Part part) {
+ return (whole) -> set(whole, part);
+ }
+
+ /**
+ * Lift a function that modifies parts to one that modifies wholes.
+ *
+ * @param f The function which operates on parts
+ *
+ * @return A corresponding function which applies the given modification to a part.
+ */
+ default Function<Whole, Whole> lift(UnaryOperator<Part> f) {
+ // modify will be more efficient for some lenses
+ return (whole) -> modify(whole, f);
+ }
+}
diff --git a/src/main/java/bjc/functypes/optics/LensX.java b/src/main/java/bjc/optics/LensX.java
index 0c78370..d0f83be 100644
--- a/src/main/java/bjc/functypes/optics/LensX.java
+++ b/src/main/java/bjc/optics/LensX.java
@@ -15,9 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes.optics;
+package bjc.optics;
-import static bjc.functypes.optics.Lenses.immutable;
+import static bjc.optics.Lenses.immutable;
import java.util.function.BiFunction;
import java.util.function.Function;
diff --git a/src/main/java/bjc/functypes/optics/Lenses.java b/src/main/java/bjc/optics/Lenses.java
index 3c4c688..6cebc84 100644
--- a/src/main/java/bjc/functypes/optics/Lenses.java
+++ b/src/main/java/bjc/optics/Lenses.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes.optics;
+package bjc.optics;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
diff --git a/src/main/java/bjc/functypes/optics/MutableLens.java b/src/main/java/bjc/optics/MutableLens.java
index 9c2e635..88eca04 100644
--- a/src/main/java/bjc/functypes/optics/MutableLens.java
+++ b/src/main/java/bjc/optics/MutableLens.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes.optics;
+package bjc.optics;
/**
* A type-invariant lens for mutating objects.
diff --git a/src/main/java/bjc/functypes/optics/Optic.java b/src/main/java/bjc/optics/Optic.java
index 513e110..389da21 100644
--- a/src/main/java/bjc/functypes/optics/Optic.java
+++ b/src/main/java/bjc/optics/Optic.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes.optics;
+package bjc.optics;
/**
* General interface for optics of varying sorts
diff --git a/src/main/java/bjc/functypes/optics/PrismX.java b/src/main/java/bjc/optics/PrismX.java
index b62bce3..b4986cf 100644
--- a/src/main/java/bjc/functypes/optics/PrismX.java
+++ b/src/main/java/bjc/optics/PrismX.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes.optics;
+package bjc.optics;
public interface PrismX<W1, W2, P1, P2> extends Optic<W1, W2, P1, P2> {
diff --git a/src/main/java/bjc/functypes/optics/impl/package-info.java b/src/main/java/bjc/optics/impl/package-info.java
index 8ca00cf..b147877 100644
--- a/src/main/java/bjc/functypes/optics/impl/package-info.java
+++ b/src/main/java/bjc/optics/impl/package-info.java
@@ -15,4 +15,4 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes.optics.impl; \ No newline at end of file
+package bjc.optics.impl; \ No newline at end of file
diff --git a/src/main/java/bjc/functypes/optics/package-info.java b/src/main/java/bjc/optics/package-info.java
index a3f656c..241b565 100644
--- a/src/main/java/bjc/functypes/optics/package-info.java
+++ b/src/main/java/bjc/optics/package-info.java
@@ -18,4 +18,4 @@
/**
*
*/
-package bjc.functypes.optics; \ No newline at end of file
+package bjc.optics; \ No newline at end of file
diff --git a/src/main/java/bjc/functypes/BiContainer.java b/src/main/java/bjc/typeclasses/BiContainer.java
index db822ba..9be00ca 100644
--- a/src/main/java/bjc/functypes/BiContainer.java
+++ b/src/main/java/bjc/typeclasses/BiContainer.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes;
+package bjc.typeclasses;
public interface BiContainer<L, R, C extends BiContainer<?, ?, C>> {
// marker
diff --git a/src/main/java/bjc/functypes/Container.java b/src/main/java/bjc/typeclasses/Container.java
index f000705..b1e3e34 100644
--- a/src/main/java/bjc/functypes/Container.java
+++ b/src/main/java/bjc/typeclasses/Container.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes;
+package bjc.typeclasses;
public interface Container<T, C extends Container<?, C>> {
// Marker
diff --git a/src/main/java/bjc/typeclasses/FunList.java b/src/main/java/bjc/typeclasses/FunList.java
new file mode 100644
index 0000000..cd16c82
--- /dev/null
+++ b/src/main/java/bjc/typeclasses/FunList.java
@@ -0,0 +1,55 @@
+package bjc.typeclasses;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+public sealed interface FunList<A, B> permits FunList.Done<A, B>, FunList.More<A, B> {
+ public final class Done<A, B> implements FunList<A, B> {
+ private final B val;
+
+ public Done(B val) {
+ this.val = val;
+ }
+
+ @Override
+ public B getB() {
+ return val;
+ }
+
+ @Override
+ public List<A> getAs() {
+ return new ArrayList<>();
+ }
+ }
+
+ public final class More<A, B> implements FunList<A, B> {
+ private A val;
+ private FunList<A, Function<A, B>> rest;
+
+ public More(A val, FunList<A, Function<A, B>> rest) {
+ this.val = val;
+ this.rest = rest;
+ }
+
+ @Override
+ public B getB() {
+ return rest.getB().apply(val);
+ }
+
+ @Override
+ public List<A> getAs() {
+ List<A> as = rest.getAs();
+ // Note: this is kinda inefficient. Should we instead say that it returns the As
+ // in reverse order
+ as.add(0, val);
+ return as;
+ }
+ }
+
+ public B getB();
+
+ public List<A> getAs();
+
+ // https://twanvl.nl/blog/haskell/non-regular1
+}
diff --git a/src/main/java/bjc/functypes/FunctionalIsomorphism.java b/src/main/java/bjc/typeclasses/FunctionalIsomorphism.java
index 43520e3..47d060c 100644
--- a/src/main/java/bjc/functypes/FunctionalIsomorphism.java
+++ b/src/main/java/bjc/typeclasses/FunctionalIsomorphism.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes;
+package bjc.typeclasses;
import java.util.function.Function;
diff --git a/src/main/java/bjc/functypes/Isomorphism.java b/src/main/java/bjc/typeclasses/Isomorphism.java
index 3393ed6..dd5a740 100644
--- a/src/main/java/bjc/functypes/Isomorphism.java
+++ b/src/main/java/bjc/typeclasses/Isomorphism.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes;
+package bjc.typeclasses;
import java.util.function.*;
diff --git a/src/main/java/bjc/functypes/ListC.java b/src/main/java/bjc/typeclasses/ListC.java
index 78fbb7a..16dca8a 100644
--- a/src/main/java/bjc/functypes/ListC.java
+++ b/src/main/java/bjc/typeclasses/ListC.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes;
+package bjc.typeclasses;
import java.util.List;
diff --git a/src/main/java/bjc/functypes/Natural.java b/src/main/java/bjc/typeclasses/Natural.java
index ecf12c4..d487b9a 100644
--- a/src/main/java/bjc/functypes/Natural.java
+++ b/src/main/java/bjc/typeclasses/Natural.java
@@ -15,19 +15,41 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package bjc.functypes;
+package bjc.typeclasses;
+/**
+ * A natural transformation; a mapping between two type-containers which
+ * preserves the contents of the containers.
+ *
+ * @author bjcul
+ *
+ * @param <F> The actual type of the first container
+ * @param <G> The actual type of the second container
+ */
@FunctionalInterface
-public interface Natural<F extends Container<?, F>, G extends Container<?, G>> extends BiContainer<F, G, Natural<?, ?>> {
+public interface Natural<F extends Container<?, F>, G extends Container<?, G>>
+ extends BiContainer<F, G, Natural<?, ?>> {
+ /**
+ * Apply the natural transformation.
+ *
+ * @param <X> The type contained in the container
+ *
+ * @param val The container to be transformed
+ *
+ * @return The value, in the other container type
+ */
<X> Container<X, G> apply(Container<X, F> val);
- public static Natural<ListC<?>, ListC<?>> listID() {
+ /**
+ * The simplest possible natural transform, mapping a type to itself.
+ *
+ * @return The ID natural transform
+ */
+ public static <C extends Container<?, C>> Natural<C, C> ID() {
return new Natural<>() {
@Override
- public <X> ListC<X> apply(Container<X, ListC<?>> val) {
- ListC<X> lst = (ListC<X>) val;
-
- return lst;
+ public <X> Container<X, C> apply(Container<X, C> val) {
+ return val;
}
};
}
diff --git a/src/main/java/bjc/typeclasses/PFLens.java b/src/main/java/bjc/typeclasses/PFLens.java
new file mode 100644
index 0000000..0468efb
--- /dev/null
+++ b/src/main/java/bjc/typeclasses/PFLens.java
@@ -0,0 +1,18 @@
+package bjc.typeclasses;
+
+import java.util.function.Function;
+
+/**
+ * A profunctor lens
+ *
+ * @author bjcul
+ *
+ * @param <Whole1>
+ * @param <Whole2>
+ * @param <Part1>
+ * @param <Part2>
+ */
+public interface PFLens<Whole1, Whole2, Part1, Part2> {
+ // Container should be Functor once gthat is ironed out
+ <A, B, F extends Container<?, F>> Function<Whole1, Container<Whole2, F>> run(Function<Part1, Container<Part2, F>> f);
+}
diff --git a/src/main/java/bjc/typeclasses/package-info.java b/src/main/java/bjc/typeclasses/package-info.java
new file mode 100644
index 0000000..86ea3c1
--- /dev/null
+++ b/src/main/java/bjc/typeclasses/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * esodata - Data structures of varying utility
+ * Copyright 2022, Ben Culkin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package bjc.typeclasses; \ No newline at end of file
diff --git a/src/main/java/bjc/typeclasses/todo b/src/main/java/bjc/typeclasses/todo
new file mode 100644
index 0000000..55dd77d
--- /dev/null
+++ b/src/main/java/bjc/typeclasses/todo
@@ -0,0 +1,126 @@
+https://bartoszmilewski.com/2014/01/14/functors-are-containers/
+ Note that I've not quite ironed out the whole deal w/ BiContainer yet, and type classes which take two parameters
+
+For lenses, name the class Iso as Mirror instead, to keep with the theme
+
+A profunctor value of the type p a b could then be considered a container of bs that are keyed by elements of type a.
+
+class (Profunctor p) => TamModule (ten :: * -> * -> *) p where
+ leftAction :: p a b -> p (c `ten` a) (c `ten` b)
+ rightAction :: p a b -> p (a `ten` c) (b `ten` c)
+
+type TamOptic ten s t a b
+ = forall p. TamModule ten p => p a b -> p s t
+data Optic ten s t a b
+ = forall c. Optic (s -> c `ten` a) (c `ten` b -> t)
+
+type TamProd p = TamModule (,) p
+type TamSum p = TamModule Either p
+
+data Pastro p a b where
+ Pastro :: ((y, z) -> b) -> p x y -> (a -> (x, z))
+ -> Pastro p a b
+data Copastro p a b where
+ Copastro :: (Either y z -> b) -> p x y -> (a -> Either x z)
+ -> Copastro p a b
+// https://bartoszmilewski.com/2017/07/07/profunctor-optics-the-categorical-view/
+
+https://r6research.livejournal.com/28338.html?utm_source=3userpost - A new case for the pointed functor class
+https://r6research.livejournal.com/28050.html - Grate: A new kind of Optic
+https://r6research.livejournal.com/27476.html - Profunctor hierarchy for objects
+
+class Functor c => Naperian c where
+ zipFWith :: Functor f => (f a -> b) -> f (c a) -> (c b)
+
+class (Traversable v, Naperian v) => FiniteVector v where
+ naperianTraverse :: (Functor f, Applicative g) => (f a -> g b) -> f (v a) -> g (v b)
+
+-- A simple example to get people started.
+instance FiniteVector Triple where
+ naperianTraverse h fv = Triple <$> h (one <$> fv) <*> h (two <$> fv) <*> h (three <$> fv)
+ where
+ one (Triple x y z) = x
+ two (Triple x y z) = y
+ three (Triple x y z) = z
+vectorSize :: FiniteVector v => Proxy (Constant () (v a)) -> Integer
+vectorSize p = getSum . getConstant $ naperianTraverse (const (Constant (Sum 1)) (Constant () `asProxyTypeOf` p)
+class Profunctor p => Power p where
+ waddle :: FiniteVector v => p a b -> p (v a) (v b)
+type FiniteGrate s t a b = Power p => p a b -> p s t
+
+type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s
+
+// Create lens for a Hours/Minutes/Seconds time type, which does the right thing
+
+data SLens α γ β = SLens {putR :: (α, γ) → (β , γ), putL :: (β , γ) → (α, γ), missing :: γ }
+
+(;) :: (SLens α σ1 β ) → (SLens β σ2 γ) → (SLens α (σ1,σ2) γ)
+l1 ; l2 = SLens putR putL (l1.missing, l2.missing)
+ where putR (a, (s1, s2)) =
+ let (b, s′1) = putR (a, s1)
+ (c, s′2) = putR (b, s2)
+ in (c, (s′1, s′2))
+ putL (c, (s1, s2)) =
+ let (b, s′2) = putL (c, s2)
+ (a, s′1) = putL (b, s1)
+ in (a, (s′1, s′2))
+idLensS :: SLens X () X
+idLensS = SLens id id ()
+
+type StateT σ τ α = σ → τ (α, σ)
+instance Monad τ ⇒ Monad (StateT σ τ ) where
+ return a = λs. return (a, s)
+ m >>= k = λs. do {(a, s′) ← m s; k a s′
+
+get :: Monad τ ⇒ StateT σ τ σ
+get = λs. return (s, s)
+set :: Monad τ ⇒ σ → StateT σ τ ()
+set s′ = λs. return ((), s′)
+
+lift :: Monad τ ⇒ τ α → StateT σ τ α
+lift m = λs. do {a ← m; return (a, s)}
+
+gets :: Monad τ ⇒ (σ → α) → StateT σ τ α
+gets f = do {s ← get; return (f s)}
+eval :: Monad τ ⇒ StateT σ τ α → σ → τ α
+eval m s = do {(a, s′) ← m s; return a }
+exec :: Monad τ ⇒ StateT σ τ α → σ → τ σ
+exec m s = do {(a, s′) ← m s; return s′ }
+
+data Codec g p x a = Codec { get :: g a, put :: x -> p a }
+instance (Functor g, Functor p) => Profunctor (Codec g p)
+instance (Monad g, Monad p) => Monad (Codec g p x)
+
+http://oleg.fi/gists/posts/2017-03-20-affine-traversal.html
+
+data Kiosk a b s t = Kiosk (s -> Either t a) (s -> b -> t)
+sellKiosk :: Kiosk a b a b
+sellKiosk = Kiosk Right (\_ -> id)
+instance Profunctor (Kiosk u v) where
+ dimap f g (Kiosk getter setter) = Kiosk
+ (\a -> first g $ getter (f a))
+ (\a v -> g (setter (f a) v))
+instance Strong (Kiosk u v) where
+ first' (Kiosk getter setter) = Kiosk
+ (\(a, c) -> first (,c) $ getter a)
+ (\(a, c) v -> (setter a v, c))
+instance Choice (Kiosk u v) where
+ right' (Kiosk getter setter) = Kiosk
+ (\eca -> assoc (second getter eca))
+ (\eca v -> second (`setter` v) eca)
+ where
+ assoc :: Either a (Either b c) -> Either (Either a b) c
+ assoc (Left a) = Left (Left a)
+ assoc (Right (Left b)) = Left (Right b)
+ assoc (Right (Right c)) = Right c
+
+newtype Kiask a b t = Kiask { runKiask :: (Either t a, b -> t) }
+sellKiask :: a -> Kiask a b b
+sellKiask a = Kiask (Right a, id)
+instance Functor (Kiask a b) where
+ fmap f (Kiask (Left t, g)) = Kiask (Left (f t), f . g)
+ fmap f (Kiask (Right a, g)) = Kiask (Right a, f . g)
+instance Pointed (Kiask a b) where
+ point x = Kiask (Left x, const x)
+
+http://oleg.fi/gists/posts/2021-01-08-indexed-optics-dilemma.html \ No newline at end of file
diff --git a/src/test/java/bjc/test/functypes/optics/LensesTest.java b/src/test/java/bjc/test/functypes/optics/LensesTest.java
index ff13a42..c431c2f 100644
--- a/src/test/java/bjc/test/functypes/optics/LensesTest.java
+++ b/src/test/java/bjc/test/functypes/optics/LensesTest.java
@@ -5,7 +5,7 @@ import static org.junit.Assert.*;
import org.junit.Test;
import bjc.data.Holder;
-import bjc.functypes.optics.Lenses;
+import bjc.optics.Lenses;
public class LensesTest {