All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fj.data.optic.PLens Maven / Gradle / Ivy

Go to download

Functional Java is an open source library that supports closures for the Java programming language

The newest version!
package fj.data.optic;

import fj.F;
import fj.Function;
import fj.Monoid;
import fj.P1;
import fj.Semigroup;
import fj.control.Trampoline;
import fj.control.parallel.Promise;
import fj.data.Either;
import fj.data.IO;
import fj.data.IOFunctions;
import fj.data.List;
import fj.data.Option;
import fj.data.Stream;
import fj.data.Validation;
import fj.data.vector.V2;

/**
 * A {@link PLens} can be seen as a pair of functions:
    *
  • {@code get: S => A} i.e. from an {@code S}, we can extract an {@code A}
  • *
  • {@code set: (B, S) => T} i.e. if we replace an {@code A} by a {@code B} in an {@code S}, we obtain a {@code T}
  • *
*

* A {@link PLens} could also be defined as a weaker {@link PIso} where set requires an additional parameter than reverseGet.

*

* {@link PLens} stands for Polymorphic Lens as it set and modify methods change a type {@code A} to {@code B} and {@code S} to {@code T}. {@link Lens} * is a {@link PLens} restricted to monomoprhic updates.

*

* A {@link PLens} is also a valid {@link Getter}, {@link Fold}, {@link POptional}, {@link PTraversal} and {@link PSetter}

*

* Typically a {@link PLens} or {@link Lens} can be defined between a Product (e.g. case class, tuple, HList) and one of it is * component.

* * @param the source of a {@link PLens} * @param the modified source of a {@link PLens} * @param the target of a {@link PLens} * @param the modified target of a {@link PLens} */ public abstract class PLens { PLens() { super(); } /** get the target of a {@link PLens} */ public abstract A get(S s); /** set polymorphically the target of a {@link PLens} using a function */ public abstract F set(B b); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyFunctionF(F> f); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyEitherF(F> f); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyIOF(F> f); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyTrampolineF(F> f); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyPromiseF(F> f); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyListF(F> f); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyOptionF(F> f); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyStreamF(F> f); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyP1F(F> f); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyValidationF(F> f); /** * modify polymorphically the target of a {@link PLens} with an Applicative function */ public abstract F> modifyV2F(F> f); /** modify polymorphically the target of a {@link PLens} using a function */ public abstract F modify(final F f); /** join two {@link PLens} with the same target */ public final PLens, Either, A, B> sum(final PLens other) { return pLens( e -> e.either(this::get, other::get), b -> e -> e.bimap(PLens.this.set(b), other.set(b))); } /***********************************************************/ /** Compose methods between a {@link PLens} and another Optics */ /***********************************************************/ /** compose a {@link PLens} with a {@link Fold} */ public final Fold composeFold(final Fold other) { return asFold().composeFold(other); } /** compose a {@link PLens} with a {@link Getter} */ public final Getter composeGetter(final Getter other) { return asGetter().composeGetter(other); } /** * compose a {@link PLens} with a {@link PSetter} */ public final PSetter composeSetter(final PSetter other) { return asSetter().composeSetter(other); } /** * compose a {@link PLens} with a {@link PTraversal} */ public final PTraversal composeTraversal(final PTraversal other) { return asTraversal().composeTraversal(other); } /** compose a {@link PLens} with an {@link POptional} */ public final POptional composeOptional(final POptional other) { return asOptional().composeOptional(other); } /** compose a {@link PLens} with a {@link PPrism} */ public final POptional composePrism(final PPrism other) { return asOptional().composeOptional(other.asOptional()); } /** compose a {@link PLens} with a {@link PLens} */ public final PLens composeLens(final PLens other) { final PLens self = this; return new PLens() { @Override public C get(final S s) { return other.get(self.get(s)); } @Override public F set(final D d) { return self.modify(other.set(d)); } @Override public F> modifyFunctionF(final F> f) { return self.modifyFunctionF(other.modifyFunctionF(f)); } @Override public F> modifyEitherF(final F> f) { return self.modifyEitherF(other.modifyEitherF(f)); } @Override public F> modifyIOF(final F> f) { return self.modifyIOF(other.modifyIOF(f)); } @Override public F> modifyTrampolineF(final F> f) { return self.modifyTrampolineF(other.modifyTrampolineF(f)); } @Override public F> modifyPromiseF(final F> f) { return self.modifyPromiseF(other.modifyPromiseF(f)); } @Override public F> modifyListF(final F> f) { return self.modifyListF(other.modifyListF(f)); } @Override public F> modifyOptionF(final F> f) { return self.modifyOptionF(other.modifyOptionF(f)); } @Override public F> modifyStreamF(final F> f) { return self.modifyStreamF(other.modifyStreamF(f)); } @Override public F> modifyP1F(final F> f) { return self.modifyP1F(other.modifyP1F(f)); } @Override public F> modifyValidationF(final F> f) { return self.modifyValidationF(other.modifyValidationF(f)); } @Override public F> modifyV2F(final F> f) { return self.modifyV2F(other.modifyV2F(f)); } @Override public F modify(final F f) { return self.modify(other.modify(f)); } }; } /** compose a {@link PLens} with an {@link PIso} */ public final PLens composeIso(final PIso other) { return composeLens(other.asLens()); } /************************************************************************************************/ /** Transformation methods to view a {@link PLens} as another Optics */ /************************************************************************************************/ /** view a {@link PLens} as a {@link Fold} */ public final Fold asFold() { return new Fold() { @Override public F foldMap(final Monoid m, final F f) { return s -> f.f(get(s)); } }; } /** view a {@link PLens} as a {@link Getter} */ public final Getter asGetter() { return new Getter() { @Override public A get(final S s) { return PLens.this.get(s); } }; } /** view a {@link PLens} as a {@link PSetter} */ public PSetter asSetter() { return new PSetter() { @Override public F modify(final F f) { return PLens.this.modify(f); } @Override public F set(final B b) { return PLens.this.set(b); } }; } /** view a {@link PLens} as a {@link PTraversal} */ public PTraversal asTraversal() { final PLens self = this; return new PTraversal() { @Override public F> modifyFunctionF(final F> f) { return self.modifyFunctionF(f); } @Override public F> modifyEitherF(final F> f) { return self.modifyEitherF(f); } @Override public F> modifyIOF(final F> f) { return self.modifyIOF(f); } @Override public F> modifyTrampolineF(final F> f) { return self.modifyTrampolineF(f); } @Override public F> modifyPromiseF(final F> f) { return self.modifyPromiseF(f); } @Override public F> modifyListF(final F> f) { return self.modifyListF(f); } @Override public F> modifyOptionF(final F> f) { return self.modifyOptionF(f); } @Override public F> modifyStreamF(final F> f) { return self.modifyStreamF(f); } @Override public F> modifyP1F(final F> f) { return self.modifyP1F(f); } @Override public F> modifyValidationF(Semigroup s, final F> f) { return self.modifyValidationF(f); } @Override public F> modifyV2F(final F> f) { return self.modifyV2F(f); } @Override public F foldMap(final Monoid monoid, final F f) { return s -> f.f(get(s)); } }; } /** view a {@link PLens} as an {@link POptional} */ public POptional asOptional() { final PLens self = this; return new POptional() { @Override public Either getOrModify(final S s) { return Either.right(self.get(s)); } @Override public F set(final B b) { return self.set(b); } @Override public Option getOption(final S s) { return Option.some(self.get(s)); } @Override public F> modifyFunctionF(final F> f) { return self.modifyFunctionF(f); } @Override public F> modifyEitherF(final F> f) { return self.modifyEitherF(f); } @Override public F> modifyIOF(final F> f) { return self.modifyIOF(f); } @Override public F> modifyTrampolineF(final F> f) { return self.modifyTrampolineF(f); } @Override public F> modifyPromiseF(final F> f) { return self.modifyPromiseF(f); } @Override public F> modifyListF(final F> f) { return self.modifyListF(f); } @Override public F> modifyOptionF(final F> f) { return self.modifyOptionF(f); } @Override public F> modifyStreamF(final F> f) { return self.modifyStreamF(f); } @Override public F> modifyP1F(final F> f) { return self.modifyP1F(f); } @Override public F> modifyValidationF(final F> f) { return self.modifyValidationF(f); } @Override public F> modifyV2F(final F> f) { return self.modifyV2F(f); } @Override public F modify(final F f) { return self.modify(f); } }; } public static PLens pId() { return PIso. pId().asLens(); } /** * create a {@link PLens} using a pair of functions: one to get the target, one to set the target. */ public static PLens pLens(final F get, final F> set) { return new PLens() { @Override public A get(final S s) { return get.f(s); } @Override public F set(final B b) { return set.f(b); } @Override public F> modifyFunctionF(final F> f) { return s -> Function.compose(b -> set.f(b).f(s), f.f(get.f(s))); } @Override public F> modifyEitherF(final F> f) { return s -> f.f(get.f(s)).right().map(a -> set.f(a).f(s)); } @Override public F> modifyIOF(final F> f) { return s -> IOFunctions.map(f.f(get.f(s)), a -> set.f(a).f(s)); } @Override public F> modifyTrampolineF(final F> f) { return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); } @Override public F> modifyPromiseF(final F> f) { return s -> f.f(get.f(s)).fmap(a -> set.f(a).f(s)); } @Override public F> modifyListF(final F> f) { return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); } @Override public F> modifyOptionF(final F> f) { return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); } @Override public F> modifyStreamF(final F> f) { return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); } @Override public F> modifyP1F(final F> f) { return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); } @Override public F> modifyValidationF(final F> f) { return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); } @Override public F> modifyV2F(final F> f) { return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); } @Override public F modify(final F f) { return s -> set.f(f.f(get.f(s))).f(s); } }; } }