From 44be6e6cd7671dd243056107ffa6201504f7fbce Mon Sep 17 00:00:00 2001 From: Ben Culkin Date: Sun, 25 Jun 2023 15:50:38 -0400 Subject: Update a number of things --- src/main/java/bjc/optics/Lens.java | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'src/main/java/bjc/optics/Lens.java') diff --git a/src/main/java/bjc/optics/Lens.java b/src/main/java/bjc/optics/Lens.java index be10eef..e8cab84 100644 --- a/src/main/java/bjc/optics/Lens.java +++ b/src/main/java/bjc/optics/Lens.java @@ -17,8 +17,9 @@ */ package bjc.optics; -import java.util.function.Function; -import java.util.function.UnaryOperator; +import static bjc.optics.Lenses.immutable; + +import java.util.function.*; import bjc.typeclasses.BiContainer; @@ -28,21 +29,22 @@ import bjc.typeclasses.BiContainer; * @author bjcul * * @param The item this lens can focus on - * @param The field this lens focuses on + * @param The field this lens focuses on */ -public interface Lens extends LensX, BiContainer> { +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 + * @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. * @@ -53,16 +55,36 @@ public interface Lens extends LensX, BiCo 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. + * @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); } + + /** + * 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 Lens compose(Lens other) { + LensX lensX = immutable((whole) -> other.get(get(whole)), + (whole, part) -> update(whole, (val2) -> other.set(val2, part))); + // Note: if lensX is inlined, then the setter function for the lens has to be + // externalized, otherwise type-inference goes BOOM and everything fails. + // Should ask on stack overflow why that is + return (Lens) lensX; + } } -- cgit v1.2.3