From 0f958b08b3446a866418aa485bb60c208d952033 Mon Sep 17 00:00:00 2001 From: Ben Culkin Date: Sat, 8 Oct 2022 14:47:21 -0400 Subject: 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 --- src/main/java/bjc/data/CollectionUtils.java | 54 +++++++ src/main/java/bjc/data/Holder.java | 4 +- src/main/java/bjc/functypes/BiContainer.java | 22 --- src/main/java/bjc/functypes/Combinators.java | 40 ++++- src/main/java/bjc/functypes/Const.java | 19 +++ src/main/java/bjc/functypes/Container.java | 22 --- .../java/bjc/functypes/FunctionalIsomorphism.java | 67 --------- src/main/java/bjc/functypes/Isomorphism.java | 71 --------- src/main/java/bjc/functypes/ListC.java | 32 ---- src/main/java/bjc/functypes/Natural.java | 34 ----- src/main/java/bjc/functypes/Predicates.java | 41 ++++++ src/main/java/bjc/functypes/ThrowFunction.java | 2 + src/main/java/bjc/functypes/optics/Lens.java | 30 ---- src/main/java/bjc/functypes/optics/LensX.java | 84 ----------- src/main/java/bjc/functypes/optics/Lenses.java | 164 --------------------- .../java/bjc/functypes/optics/MutableLens.java | 46 ------ src/main/java/bjc/functypes/optics/Optic.java | 32 ---- src/main/java/bjc/functypes/optics/PrismX.java | 22 --- .../bjc/functypes/optics/impl/package-info.java | 18 --- .../java/bjc/functypes/optics/package-info.java | 21 --- src/main/java/bjc/optics/Lens.java | 68 +++++++++ src/main/java/bjc/optics/LensX.java | 84 +++++++++++ src/main/java/bjc/optics/Lenses.java | 164 +++++++++++++++++++++ src/main/java/bjc/optics/MutableLens.java | 46 ++++++ src/main/java/bjc/optics/Optic.java | 32 ++++ src/main/java/bjc/optics/PrismX.java | 22 +++ src/main/java/bjc/optics/impl/package-info.java | 18 +++ src/main/java/bjc/optics/package-info.java | 21 +++ src/main/java/bjc/typeclasses/BiContainer.java | 22 +++ src/main/java/bjc/typeclasses/Container.java | 22 +++ src/main/java/bjc/typeclasses/FunList.java | 55 +++++++ .../bjc/typeclasses/FunctionalIsomorphism.java | 67 +++++++++ src/main/java/bjc/typeclasses/Isomorphism.java | 71 +++++++++ src/main/java/bjc/typeclasses/ListC.java | 32 ++++ src/main/java/bjc/typeclasses/Natural.java | 56 +++++++ src/main/java/bjc/typeclasses/PFLens.java | 18 +++ src/main/java/bjc/typeclasses/package-info.java | 18 +++ src/main/java/bjc/typeclasses/todo | 126 ++++++++++++++++ 38 files changed, 1099 insertions(+), 668 deletions(-) create mode 100644 src/main/java/bjc/data/CollectionUtils.java delete mode 100644 src/main/java/bjc/functypes/BiContainer.java create mode 100644 src/main/java/bjc/functypes/Const.java delete mode 100644 src/main/java/bjc/functypes/Container.java delete mode 100644 src/main/java/bjc/functypes/FunctionalIsomorphism.java delete mode 100644 src/main/java/bjc/functypes/Isomorphism.java delete mode 100644 src/main/java/bjc/functypes/ListC.java delete mode 100644 src/main/java/bjc/functypes/Natural.java create mode 100644 src/main/java/bjc/functypes/Predicates.java delete mode 100644 src/main/java/bjc/functypes/optics/Lens.java delete mode 100644 src/main/java/bjc/functypes/optics/LensX.java delete mode 100644 src/main/java/bjc/functypes/optics/Lenses.java delete mode 100644 src/main/java/bjc/functypes/optics/MutableLens.java delete mode 100644 src/main/java/bjc/functypes/optics/Optic.java delete mode 100644 src/main/java/bjc/functypes/optics/PrismX.java delete mode 100644 src/main/java/bjc/functypes/optics/impl/package-info.java delete mode 100644 src/main/java/bjc/functypes/optics/package-info.java create mode 100644 src/main/java/bjc/optics/Lens.java create mode 100644 src/main/java/bjc/optics/LensX.java create mode 100644 src/main/java/bjc/optics/Lenses.java create mode 100644 src/main/java/bjc/optics/MutableLens.java create mode 100644 src/main/java/bjc/optics/Optic.java create mode 100644 src/main/java/bjc/optics/PrismX.java create mode 100644 src/main/java/bjc/optics/impl/package-info.java create mode 100644 src/main/java/bjc/optics/package-info.java create mode 100644 src/main/java/bjc/typeclasses/BiContainer.java create mode 100644 src/main/java/bjc/typeclasses/Container.java create mode 100644 src/main/java/bjc/typeclasses/FunList.java create mode 100644 src/main/java/bjc/typeclasses/FunctionalIsomorphism.java create mode 100644 src/main/java/bjc/typeclasses/Isomorphism.java create mode 100644 src/main/java/bjc/typeclasses/ListC.java create mode 100644 src/main/java/bjc/typeclasses/Natural.java create mode 100644 src/main/java/bjc/typeclasses/PFLens.java create mode 100644 src/main/java/bjc/typeclasses/package-info.java create mode 100644 src/main/java/bjc/typeclasses/todo (limited to 'src/main') 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 . + */ +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 The type of the values in the map + * @param The type of the keys in the map + * @param 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 Function, Map> indexBy(Function keyFunc, + Function valFunc) { + return (coll) -> { + Map 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 * The type of value held. */ -public interface Holder extends Functor { +public interface Holder extends Functor, Container> { + // 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/BiContainer.java b/src/main/java/bjc/functypes/BiContainer.java deleted file mode 100644 index db822ba..0000000 --- a/src/main/java/bjc/functypes/BiContainer.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes; - -public interface BiContainer> { - // marker -} 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 The input type + * @param The output type + * + * @param f The function + * + * @return The function, taking a supplier as its first function + */ public static Function, Output> lazify(Function f) { return (supp) -> f.apply(supp.get()); } + /** + * Convert a lazy function into an eager one + * + * @param The input type + * @param The output type + * + * @param f A function that takes a supplier as its parameter + * + * @return A function which just takes a value + */ public static Function strictify(Function, Output> f) { return (val) -> f.apply(() -> val); } + + /** + * Convert a pure function into one that mutates a holder. + * + * @param The type of the function. + * + * @param f The function. + * + * @return A function that mutates a holder using the given function + */ + public static Consumer> mutating(UnaryOperator 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 implements Container>{ + private V payload; + + private Const(V payload) { + this.payload = payload; + } + + public static Const of(V val) { + return new Const<>(val); + } + + V get() { + return payload; + } +} diff --git a/src/main/java/bjc/functypes/Container.java b/src/main/java/bjc/functypes/Container.java deleted file mode 100644 index f000705..0000000 --- a/src/main/java/bjc/functypes/Container.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes; - -public interface Container> { - // Marker -} diff --git a/src/main/java/bjc/functypes/FunctionalIsomorphism.java b/src/main/java/bjc/functypes/FunctionalIsomorphism.java deleted file mode 100644 index 43520e3..0000000 --- a/src/main/java/bjc/functypes/FunctionalIsomorphism.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes; - -import java.util.function.Function; - -/** - * A pair of functions to transform between a pair of types. - * - * @author bjculkin - * - * @param - * The source type of the isomorphism. - * - * @param - * The destination type of isomorphism. - */ -public class FunctionalIsomorphism implements Isomorphism -{ - /* The function to the destination type. */ - private Function toFunc; - /* The function to the source type. */ - private Function fromFunc; - - /** - * Create a new isomorphism. - * - * @param to - * The 'forward' function, from the source to the definition. - * - * @param from - * The 'backward' function, from the definition to the source. - */ - public FunctionalIsomorphism(Function to, - Function from) - { - toFunc = to; - fromFunc = from; - } - - @Override - public Dest to(Source val) - { - return toFunc.apply(val); - } - - @Override - public Source from(Dest val) - { - return fromFunc.apply(val); - } -} diff --git a/src/main/java/bjc/functypes/Isomorphism.java b/src/main/java/bjc/functypes/Isomorphism.java deleted file mode 100644 index 3393ed6..0000000 --- a/src/main/java/bjc/functypes/Isomorphism.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes; - -import java.util.function.*; - -/** - * Denotes that two types are essentially equivalent, by providing a means to - * convert between them. - * - * @author Ben Culkin - * - * @param The first type. - * @param The second type. - */ -public interface Isomorphism -{ - - /** - * Apply the isomorphism forward. - * - * @param val - * The source value. - * - * @return The destination value. - */ - Dest to(Source val); - - /** - * Apply the isomorphism backward. - * - * @param val - * The destination value. - * - * @return The source value. - */ - Source from(Dest val); - - /** - * Create an isomorphism from a pair of functions. - * - * @param The source type. - * @param The destination type. - * - * @param forward The function from source to destination. - * @param backward The function from destination to source. - * - * @return An isomorphism between the two types. - */ - static Isomorphism from( - Function forward, - Function backward) - { - return new FunctionalIsomorphism<>(forward, backward); - } -} \ No newline at end of file diff --git a/src/main/java/bjc/functypes/ListC.java b/src/main/java/bjc/functypes/ListC.java deleted file mode 100644 index 78fbb7a..0000000 --- a/src/main/java/bjc/functypes/ListC.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes; - -import java.util.List; - -public class ListC implements Container> { - private List contained; - - public ListC(List contained) { - this.contained = contained; - } - - public List list() { - return contained; - } -} diff --git a/src/main/java/bjc/functypes/Natural.java b/src/main/java/bjc/functypes/Natural.java deleted file mode 100644 index ecf12c4..0000000 --- a/src/main/java/bjc/functypes/Natural.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes; - -@FunctionalInterface -public interface Natural, G extends Container> extends BiContainer> { - Container apply(Container val); - - public static Natural, ListC> listID() { - return new Natural<>() { - @Override - public ListC apply(Container> val) { - ListC lst = (ListC) val; - - return lst; - } - }; - } -} diff --git a/src/main/java/bjc/functypes/Predicates.java b/src/main/java/bjc/functypes/Predicates.java new file mode 100644 index 0000000..3977294 --- /dev/null +++ b/src/main/java/bjc/functypes/Predicates.java @@ -0,0 +1,41 @@ +/* + * 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 . + */ +package bjc.functypes; + +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +/** + * Various utility functions for predicates + * @author bjcul + * + */ +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/functypes/optics/Lens.java b/src/main/java/bjc/functypes/optics/Lens.java deleted file mode 100644 index c56a016..0000000 --- a/src/main/java/bjc/functypes/optics/Lens.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes.optics; - -/** - * A type-invariant var Laarhoven lens. - * - * @author bjcul - * - * @param The item this lens can focus on - * @param The field this lens focuses on - */ -public interface Lens extends LensX { - // Alias type -} diff --git a/src/main/java/bjc/functypes/optics/LensX.java b/src/main/java/bjc/functypes/optics/LensX.java deleted file mode 100644 index 0c78370..0000000 --- a/src/main/java/bjc/functypes/optics/LensX.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes.optics; - -import static bjc.functypes.optics.Lenses.immutable; - -import java.util.function.BiFunction; -import java.util.function.Function; - -/** - * A type-variant lens - * - * @author Ben Culkin - * - * @param The first type the lens is used on - * @param The second 'whole' type - * @param The first 'part' type - * @param The second 'part' type - */ -public interface LensX extends Optic { - /** - * Retrieve the focused value of this lens. - * - * @param source The item to use the lens on. - * - * @return The value from the given whole this lens focuses on. - */ - P1 get(W1 source); - - /** - * Create an updated version of the item this lens focuses on. - * - * @param source The item to use the lens on. - * @param val The new value. - * - * @return The updated item the lens was used on. - */ - W2 set(W1 source, P2 val); - - /** - * Update the focused value. - * - * NOTE: It will often be more efficient to implement this directly. The - * implementation here is provided for convenience. - * - * @param source The item to use the lens on. - * @param action The action to applied to the focused item. - * - * @return The updated item the lens was used on. - */ - default W2 update(W1 source, Function action) { - return set(source, action.apply(get(source))); - } - - /** - * Compose two type-variant lenses together. - * - * @param The first type the second lens focuses on - * @param The second type the second lens focuses on. - * - * @param other The second lens to use. - * - * @return A lens composed from this one and the given one. - */ - default LensX compose(LensX other) { - return immutable((whole) -> other.get(get(whole)), - (whole, val) -> update(whole, (P1 val2) -> other.set(val2, val))); - } -} \ No newline at end of file diff --git a/src/main/java/bjc/functypes/optics/Lenses.java b/src/main/java/bjc/functypes/optics/Lenses.java deleted file mode 100644 index 3c4c688..0000000 --- a/src/main/java/bjc/functypes/optics/Lenses.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes.optics; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Function; - -import bjc.data.Holder; -import bjc.data.Pair; - -/** - * Utility and constructor functions for lenses - * - * @author bjcul - * - */ -public class Lenses { - /** - * Create an immutable lens from a pair of functions. - * - * @param The first type the lens is used on - * @param The second type the lens is used on - * @param The first type the lens focuses on - * @param The second type the lens focuses on. - * - * @param getter The getter for the lens - * @param setter The setter for the lens - * - * @return The lens composed from the two given functions - */ - public static LensX immutable(Function getter, - BiFunction setter) { - return new FunctionalLensX<>(getter, setter); - } - - /** - * Create a mutable lens from a pair of functions. - * - * @param The type the lens is used on - * @param The type the lens is focused on - * - * @param getter The getter for the lens - * @param mutator The mutator for the lens - * - * @return The mutable lens composed from the two given functions - */ - public static MutableLens mutable(Function getter, - BiConsumer mutator) { - return new FunctionalMutableLens<>(getter, mutator); - } - - /** - * Create a lens that reflects over the value in a holder - * - * @param The first type contained in the holder - * @param The second type contained in the holder - * - * @return A lens that focuses on the value of a holder - */ - public static LensX, Holder, Part1, Part2> holder() { - return immutable((hld) -> hld.getValue(), (hld, val) -> hld.map((vl) -> val)); - } - - /** - * Create a lens for updating tagged pairs. - * - * TODO: Should this be on a Tagged class that is isomorphic to pair - * instead? - * - * @param The first data type - * @param The second data type - * @param The tag type - * - * @return A lens that operates on the value of a tagged pair. - */ - public static LensX, Pair, A, B> tagged() { - return immutable((par) -> par.getRight(), (par, val) -> par.mapRight((vl) -> val)); - } - - /** - * Creates a lens which focuses on a piece of internal state. - * - * @param The first state type - * @param The second state type - * - * @param val The initial state value - * - * @return A lens that focuses on the given internal state. - */ - public static LensX state(A val) { - Holder hold = Holder.of(val); - return immutable((whole) -> hold.getValue(), (whole, vl) -> hold.map((arg) -> vl)); - } - - /** - * Creates a lens which focuses on a piece of mutable internal state. - * - * @param The state type - * - * @param val The initial state value - * - * @return A lens that focuses on the given internal state. - */ - public static MutableLens stateM(A val) { - Holder hold = Holder.of(val); - return mutable((whole) -> hold.getValue(), (whole, vl) -> hold.replace(vl)); - } -} - -final class FunctionalLensX implements LensX { - private final BiFunction setter; - private final Function getter; - - FunctionalLensX(Function getter, BiFunction setter) { - this.setter = setter; - this.getter = getter; - } - - @Override - public P1 get(W1 source) { - return getter.apply(source); - } - - @Override - public W2 set(W1 source, P2 val) { - return setter.apply(source, val); - } -} - -final class FunctionalMutableLens implements MutableLens { - private final BiConsumer mutator; - private final Function getter; - - FunctionalMutableLens(Function getter, BiConsumer mutator) { - this.mutator = mutator; - this.getter = getter; - } - - @Override - public Part get(Whole source) { - return getter.apply(source); - } - - @Override - public void mutate(Whole source, Part val) { - mutator.accept(source, val); - } -} diff --git a/src/main/java/bjc/functypes/optics/MutableLens.java b/src/main/java/bjc/functypes/optics/MutableLens.java deleted file mode 100644 index 9c2e635..0000000 --- a/src/main/java/bjc/functypes/optics/MutableLens.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes.optics; - -/** - * A type-invariant lens for mutating objects. - * - * Note that there is no type-variant version, because that wouldn't make much sense. - * - * Also, mixing mutable and immutable lenses may lead to confusion. - * - * @author bjcul - * - * @param The type the lens is used on - * @param The type the lens is focused on - */ -public interface MutableLens extends Lens { - /** - * Apply a mutation to an item. - * - * @param source The item to use the lens on. - * @param val The new value for the focused field. - */ - void mutate(Whole source, Part val); - - @Override - default Whole set(Whole source, Part val) { - mutate(source, val); - return source; - } -} diff --git a/src/main/java/bjc/functypes/optics/Optic.java b/src/main/java/bjc/functypes/optics/Optic.java deleted file mode 100644 index 513e110..0000000 --- a/src/main/java/bjc/functypes/optics/Optic.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes.optics; - -/** - * General interface for optics of varying sorts - * - * @author bjcul - * - * @param The first item the optic is used on - * @param The second item the optic is used on - * @param The first item the optic focuses on - * @param The second item the optic focuses on - */ -public interface Optic { - // Marker interface -} diff --git a/src/main/java/bjc/functypes/optics/PrismX.java b/src/main/java/bjc/functypes/optics/PrismX.java deleted file mode 100644 index b62bce3..0000000 --- a/src/main/java/bjc/functypes/optics/PrismX.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes.optics; - -public interface PrismX extends Optic { - -} diff --git a/src/main/java/bjc/functypes/optics/impl/package-info.java b/src/main/java/bjc/functypes/optics/impl/package-info.java deleted file mode 100644 index 8ca00cf..0000000 --- a/src/main/java/bjc/functypes/optics/impl/package-info.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 . - */ -package bjc.functypes.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/functypes/optics/package-info.java deleted file mode 100644 index a3f656c..0000000 --- a/src/main/java/bjc/functypes/optics/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 . - */ -/** - * - */ -package bjc.functypes.optics; \ No newline at end of file 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 . + */ +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 The item this lens can focus on + * @param The field this lens focuses on + */ +public interface Lens extends LensX, BiContainer> { + /** + * 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 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 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 lift(UnaryOperator f) { + // modify will be more efficient for some lenses + return (whole) -> modify(whole, f); + } +} diff --git a/src/main/java/bjc/optics/LensX.java b/src/main/java/bjc/optics/LensX.java new file mode 100644 index 0000000..d0f83be --- /dev/null +++ b/src/main/java/bjc/optics/LensX.java @@ -0,0 +1,84 @@ +/* + * 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 . + */ +package bjc.optics; + +import static bjc.optics.Lenses.immutable; + +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * A type-variant lens + * + * @author Ben Culkin + * + * @param The first type the lens is used on + * @param The second 'whole' type + * @param The first 'part' type + * @param The second 'part' type + */ +public interface LensX extends Optic { + /** + * Retrieve the focused value of this lens. + * + * @param source The item to use the lens on. + * + * @return The value from the given whole this lens focuses on. + */ + P1 get(W1 source); + + /** + * Create an updated version of the item this lens focuses on. + * + * @param source The item to use the lens on. + * @param val The new value. + * + * @return The updated item the lens was used on. + */ + W2 set(W1 source, P2 val); + + /** + * Update the focused value. + * + * NOTE: It will often be more efficient to implement this directly. The + * implementation here is provided for convenience. + * + * @param source The item to use the lens on. + * @param action The action to applied to the focused item. + * + * @return The updated item the lens was used on. + */ + default W2 update(W1 source, Function action) { + return set(source, action.apply(get(source))); + } + + /** + * Compose two type-variant lenses together. + * + * @param The first type the second lens focuses on + * @param The second type the second lens focuses on. + * + * @param other The second lens to use. + * + * @return A lens composed from this one and the given one. + */ + default LensX compose(LensX other) { + return immutable((whole) -> other.get(get(whole)), + (whole, val) -> update(whole, (P1 val2) -> other.set(val2, val))); + } +} \ No newline at end of file diff --git a/src/main/java/bjc/optics/Lenses.java b/src/main/java/bjc/optics/Lenses.java new file mode 100644 index 0000000..6cebc84 --- /dev/null +++ b/src/main/java/bjc/optics/Lenses.java @@ -0,0 +1,164 @@ +/* + * 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 . + */ +package bjc.optics; + +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; + +import bjc.data.Holder; +import bjc.data.Pair; + +/** + * Utility and constructor functions for lenses + * + * @author bjcul + * + */ +public class Lenses { + /** + * Create an immutable lens from a pair of functions. + * + * @param The first type the lens is used on + * @param The second type the lens is used on + * @param The first type the lens focuses on + * @param The second type the lens focuses on. + * + * @param getter The getter for the lens + * @param setter The setter for the lens + * + * @return The lens composed from the two given functions + */ + public static LensX immutable(Function getter, + BiFunction setter) { + return new FunctionalLensX<>(getter, setter); + } + + /** + * Create a mutable lens from a pair of functions. + * + * @param The type the lens is used on + * @param The type the lens is focused on + * + * @param getter The getter for the lens + * @param mutator The mutator for the lens + * + * @return The mutable lens composed from the two given functions + */ + public static MutableLens mutable(Function getter, + BiConsumer mutator) { + return new FunctionalMutableLens<>(getter, mutator); + } + + /** + * Create a lens that reflects over the value in a holder + * + * @param The first type contained in the holder + * @param The second type contained in the holder + * + * @return A lens that focuses on the value of a holder + */ + public static LensX, Holder, Part1, Part2> holder() { + return immutable((hld) -> hld.getValue(), (hld, val) -> hld.map((vl) -> val)); + } + + /** + * Create a lens for updating tagged pairs. + * + * TODO: Should this be on a Tagged class that is isomorphic to pair + * instead? + * + * @param The first data type + * @param The second data type + * @param The tag type + * + * @return A lens that operates on the value of a tagged pair. + */ + public static LensX, Pair, A, B> tagged() { + return immutable((par) -> par.getRight(), (par, val) -> par.mapRight((vl) -> val)); + } + + /** + * Creates a lens which focuses on a piece of internal state. + * + * @param The first state type + * @param The second state type + * + * @param val The initial state value + * + * @return A lens that focuses on the given internal state. + */ + public static LensX state(A val) { + Holder hold = Holder.of(val); + return immutable((whole) -> hold.getValue(), (whole, vl) -> hold.map((arg) -> vl)); + } + + /** + * Creates a lens which focuses on a piece of mutable internal state. + * + * @param The state type + * + * @param val The initial state value + * + * @return A lens that focuses on the given internal state. + */ + public static MutableLens stateM(A val) { + Holder hold = Holder.of(val); + return mutable((whole) -> hold.getValue(), (whole, vl) -> hold.replace(vl)); + } +} + +final class FunctionalLensX implements LensX { + private final BiFunction setter; + private final Function getter; + + FunctionalLensX(Function getter, BiFunction setter) { + this.setter = setter; + this.getter = getter; + } + + @Override + public P1 get(W1 source) { + return getter.apply(source); + } + + @Override + public W2 set(W1 source, P2 val) { + return setter.apply(source, val); + } +} + +final class FunctionalMutableLens implements MutableLens { + private final BiConsumer mutator; + private final Function getter; + + FunctionalMutableLens(Function getter, BiConsumer mutator) { + this.mutator = mutator; + this.getter = getter; + } + + @Override + public Part get(Whole source) { + return getter.apply(source); + } + + @Override + public void mutate(Whole source, Part val) { + mutator.accept(source, val); + } +} diff --git a/src/main/java/bjc/optics/MutableLens.java b/src/main/java/bjc/optics/MutableLens.java new file mode 100644 index 0000000..88eca04 --- /dev/null +++ b/src/main/java/bjc/optics/MutableLens.java @@ -0,0 +1,46 @@ +/* + * 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 . + */ +package bjc.optics; + +/** + * A type-invariant lens for mutating objects. + * + * Note that there is no type-variant version, because that wouldn't make much sense. + * + * Also, mixing mutable and immutable lenses may lead to confusion. + * + * @author bjcul + * + * @param The type the lens is used on + * @param The type the lens is focused on + */ +public interface MutableLens extends Lens { + /** + * Apply a mutation to an item. + * + * @param source The item to use the lens on. + * @param val The new value for the focused field. + */ + void mutate(Whole source, Part val); + + @Override + default Whole set(Whole source, Part val) { + mutate(source, val); + return source; + } +} diff --git a/src/main/java/bjc/optics/Optic.java b/src/main/java/bjc/optics/Optic.java new file mode 100644 index 0000000..389da21 --- /dev/null +++ b/src/main/java/bjc/optics/Optic.java @@ -0,0 +1,32 @@ +/* + * 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 . + */ +package bjc.optics; + +/** + * General interface for optics of varying sorts + * + * @author bjcul + * + * @param The first item the optic is used on + * @param The second item the optic is used on + * @param The first item the optic focuses on + * @param The second item the optic focuses on + */ +public interface Optic { + // Marker interface +} diff --git a/src/main/java/bjc/optics/PrismX.java b/src/main/java/bjc/optics/PrismX.java new file mode 100644 index 0000000..b4986cf --- /dev/null +++ b/src/main/java/bjc/optics/PrismX.java @@ -0,0 +1,22 @@ +/* + * 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 . + */ +package bjc.optics; + +public interface PrismX extends Optic { + +} diff --git a/src/main/java/bjc/optics/impl/package-info.java b/src/main/java/bjc/optics/impl/package-info.java new file mode 100644 index 0000000..b147877 --- /dev/null +++ b/src/main/java/bjc/optics/impl/package-info.java @@ -0,0 +1,18 @@ +/* + * 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 . + */ +package bjc.optics.impl; \ No newline at end of file diff --git a/src/main/java/bjc/optics/package-info.java b/src/main/java/bjc/optics/package-info.java new file mode 100644 index 0000000..241b565 --- /dev/null +++ b/src/main/java/bjc/optics/package-info.java @@ -0,0 +1,21 @@ +/* + * 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 . + */ +/** + * + */ +package bjc.optics; \ No newline at end of file diff --git a/src/main/java/bjc/typeclasses/BiContainer.java b/src/main/java/bjc/typeclasses/BiContainer.java new file mode 100644 index 0000000..9be00ca --- /dev/null +++ b/src/main/java/bjc/typeclasses/BiContainer.java @@ -0,0 +1,22 @@ +/* + * 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 . + */ +package bjc.typeclasses; + +public interface BiContainer> { + // marker +} diff --git a/src/main/java/bjc/typeclasses/Container.java b/src/main/java/bjc/typeclasses/Container.java new file mode 100644 index 0000000..b1e3e34 --- /dev/null +++ b/src/main/java/bjc/typeclasses/Container.java @@ -0,0 +1,22 @@ +/* + * 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 . + */ +package bjc.typeclasses; + +public interface Container> { + // 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 permits FunList.Done, FunList.More { + public final class Done implements FunList { + private final B val; + + public Done(B val) { + this.val = val; + } + + @Override + public B getB() { + return val; + } + + @Override + public List getAs() { + return new ArrayList<>(); + } + } + + public final class More implements FunList { + private A val; + private FunList> rest; + + public More(A val, FunList> rest) { + this.val = val; + this.rest = rest; + } + + @Override + public B getB() { + return rest.getB().apply(val); + } + + @Override + public List getAs() { + List 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 getAs(); + + // https://twanvl.nl/blog/haskell/non-regular1 +} diff --git a/src/main/java/bjc/typeclasses/FunctionalIsomorphism.java b/src/main/java/bjc/typeclasses/FunctionalIsomorphism.java new file mode 100644 index 0000000..47d060c --- /dev/null +++ b/src/main/java/bjc/typeclasses/FunctionalIsomorphism.java @@ -0,0 +1,67 @@ +/* + * 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 . + */ +package bjc.typeclasses; + +import java.util.function.Function; + +/** + * A pair of functions to transform between a pair of types. + * + * @author bjculkin + * + * @param + * The source type of the isomorphism. + * + * @param + * The destination type of isomorphism. + */ +public class FunctionalIsomorphism implements Isomorphism +{ + /* The function to the destination type. */ + private Function toFunc; + /* The function to the source type. */ + private Function fromFunc; + + /** + * Create a new isomorphism. + * + * @param to + * The 'forward' function, from the source to the definition. + * + * @param from + * The 'backward' function, from the definition to the source. + */ + public FunctionalIsomorphism(Function to, + Function from) + { + toFunc = to; + fromFunc = from; + } + + @Override + public Dest to(Source val) + { + return toFunc.apply(val); + } + + @Override + public Source from(Dest val) + { + return fromFunc.apply(val); + } +} diff --git a/src/main/java/bjc/typeclasses/Isomorphism.java b/src/main/java/bjc/typeclasses/Isomorphism.java new file mode 100644 index 0000000..dd5a740 --- /dev/null +++ b/src/main/java/bjc/typeclasses/Isomorphism.java @@ -0,0 +1,71 @@ +/* + * 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 . + */ +package bjc.typeclasses; + +import java.util.function.*; + +/** + * Denotes that two types are essentially equivalent, by providing a means to + * convert between them. + * + * @author Ben Culkin + * + * @param The first type. + * @param The second type. + */ +public interface Isomorphism +{ + + /** + * Apply the isomorphism forward. + * + * @param val + * The source value. + * + * @return The destination value. + */ + Dest to(Source val); + + /** + * Apply the isomorphism backward. + * + * @param val + * The destination value. + * + * @return The source value. + */ + Source from(Dest val); + + /** + * Create an isomorphism from a pair of functions. + * + * @param The source type. + * @param The destination type. + * + * @param forward The function from source to destination. + * @param backward The function from destination to source. + * + * @return An isomorphism between the two types. + */ + static Isomorphism from( + Function forward, + Function backward) + { + return new FunctionalIsomorphism<>(forward, backward); + } +} \ No newline at end of file diff --git a/src/main/java/bjc/typeclasses/ListC.java b/src/main/java/bjc/typeclasses/ListC.java new file mode 100644 index 0000000..16dca8a --- /dev/null +++ b/src/main/java/bjc/typeclasses/ListC.java @@ -0,0 +1,32 @@ +/* + * 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 . + */ +package bjc.typeclasses; + +import java.util.List; + +public class ListC implements Container> { + private List contained; + + public ListC(List contained) { + this.contained = contained; + } + + public List list() { + return contained; + } +} diff --git a/src/main/java/bjc/typeclasses/Natural.java b/src/main/java/bjc/typeclasses/Natural.java new file mode 100644 index 0000000..d487b9a --- /dev/null +++ b/src/main/java/bjc/typeclasses/Natural.java @@ -0,0 +1,56 @@ +/* + * 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 . + */ +package bjc.typeclasses; + +/** + * A natural transformation; a mapping between two type-containers which + * preserves the contents of the containers. + * + * @author bjcul + * + * @param The actual type of the first container + * @param The actual type of the second container + */ +@FunctionalInterface +public interface Natural, G extends Container> + extends BiContainer> { + /** + * Apply the natural transformation. + * + * @param The type contained in the container + * + * @param val The container to be transformed + * + * @return The value, in the other container type + */ + Container apply(Container val); + + /** + * The simplest possible natural transform, mapping a type to itself. + * + * @return The ID natural transform + */ + public static > Natural ID() { + return new Natural<>() { + @Override + public Container apply(Container 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 + * @param + * @param + * @param + */ +public interface PFLens { + // Container should be Functor once gthat is ironed out + > Function> run(Function> 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 . + */ +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 -- cgit v1.2.3