diff options
| author | Ben Culkin <scorpress@gmail.com> | 2022-10-08 14:47:21 -0400 |
|---|---|---|
| committer | Ben Culkin <scorpress@gmail.com> | 2022-10-08 14:47:21 -0400 |
| commit | 0f958b08b3446a866418aa485bb60c208d952033 (patch) | |
| tree | 2a54b64036bacb2f1fbc60d17511eb904b15fe7d /src/main/java/bjc/optics/LensX.java | |
| parent | 08885862bee89602d7edc55144ea9b6af780bfa4 (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
Diffstat (limited to 'src/main/java/bjc/optics/LensX.java')
| -rw-r--r-- | src/main/java/bjc/optics/LensX.java | 84 |
1 files changed, 84 insertions, 0 deletions
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 <https://www.gnu.org/licenses/>. + */ +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 <W1> The first type the lens is used on + * @param <W2> The second 'whole' type + * @param <P1> The first 'part' type + * @param <P2> The second 'part' type + */ +public interface LensX<W1, W2, P1, P2> extends Optic<W1, W2, P1, P2> { + /** + * 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<P1, P2> action) { + return set(source, action.apply(get(source))); + } + + /** + * Compose two type-variant lenses together. + * + * @param <V1> The first type the second lens focuses on + * @param <V2> 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 <V1, V2> LensX<W1, W2, V1, V2> compose(LensX<P1, P2, V1, V2> other) { + return immutable((whole) -> other.get(get(whole)), + (whole, val) -> update(whole, (P1 val2) -> other.set(val2, val))); + } +}
\ No newline at end of file |
