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

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

Go to download

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

There is a newer version: 5.0
Show newest version
package fj.data.optic;

import fj.F;
import fj.Function;
import fj.Monoid;
import fj.P;
import fj.P1;
import fj.P2;
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 PIso} defines an isomorphism between types S, A and B, T:
 *
 * 
 *              get                           reverse.get
 *     -------------------->             -------------------->
 *   S                       A         T                       B
 *     <--------------------             <--------------------
 *       reverse.reverseGet                   reverseGet
 * 
* * In addition, if f and g forms an isomorphism between `A` and `B`, i.e. if `f . g = id` and `g . f = id`, then a {@link PIso} * defines an isomorphism between `S` and `T`: * *
 *     S           T                                   S           T
 *     |           |                                   |           |
 *     |           |                                   |           |
 * get |           | reverseGet     reverse.reverseGet |           | reverse.get
 *     |           |                                   |           |
 *     |     f     |                                   |     g     |
 *     A --------> B                                   A <-------- B
 * 
* * A {@link PIso} is also a valid {@link Getter}, {@link Fold}, {@link PLens}, {@link PPrism}, {@link POptional}, * {@link PTraversal} and {@link PSetter} * * @param the source of a {@link PIso} * @param the modified source of a {@link PIso} * @param the target of a {@link PIso} * @param the modified target of a {@link PIso} */ public abstract class PIso { PIso() { super(); } /** get the target of a {@link PIso} */ public abstract A get(S s); /** get the modified source of a {@link PIso} */ public abstract T reverseGet(B b); /** reverse a {@link PIso}: the source becomes the target and the target becomes the source */ public abstract PIso reverse(); /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyFunctionF(final F> f) { return s -> Function.compose(this::reverseGet, f.f(get(s))); } /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyEitherF(final F> f) { return s -> f.f(get(s)).right().map(this::reverseGet); } /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyIOF(final F> f) { return s -> IOFunctions.map(f.f(get(s)), this::reverseGet); } /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyTrampolineF(final F> f) { return s -> f.f(get(s)).map(this::reverseGet); } /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyPromiseF(final F> f) { return s -> f.f(get(s)).fmap(this::reverseGet); } /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyListF(final F> f) { return s -> f.f(get(s)).map(this::reverseGet); } /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyOptionF(final F> f) { return s -> f.f(get(s)).map(this::reverseGet); } /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyStreamF(final F> f) { return s -> f.f(get(s)).map(this::reverseGet); } /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyP1F(final F> f) { return s -> f.f(get(s)).map(this::reverseGet); } /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyValidationF(final F> f) { return s -> f.f(get(s)).map(this::reverseGet); } /** modify polymorphically the target of a {@link PIso} with an Applicative function */ public final F> modifyV2F(final F> f) { return s -> f.f(get(s)).map(this::reverseGet); } /** modify polymorphically the target of a {@link PIso} with a function */ public final F modify(final F f) { return s -> reverseGet(f.f(get(s))); } /** set polymorphically the target of a {@link PIso} with a value */ public final F set(final B b) { return Function.constant(reverseGet(b)); } /** pair two disjoint {@link PIso} */ public final PIso, P2, P2, P2> product(final PIso other) { return pIso( ss1 -> P.p(get(ss1._1()), other.get(ss1._2())), bb1 -> P.p(reverseGet(bb1._1()), other.reverseGet(bb1._2()))); } public PIso, P2, P2, P2> first() { return pIso( sc -> P.p(get(sc._1()), sc._2()), bc -> P.p(reverseGet(bc._1()), bc._2())); } public PIso, P2, P2, P2> second() { return pIso( cs -> P.p(cs._1(), get(cs._2())), cb -> P.p(cb._1(), reverseGet(cb._2()))); } /**********************************************************/ /** Compose methods between a {@link PIso} and another Optics */ /**********************************************************/ /** compose a {@link PIso} with a {@link Fold} */ public final Fold composeFold(final Fold other) { return asFold().composeFold(other); } /** compose a {@link PIso} with a {@link Getter} */ public final Getter composeGetter(final Getter other) { return asGetter().composeGetter(other); } /** compose a {@link PIso} with a {@link PSetter} */ public final PSetter composeSetter(final PSetter other) { return asSetter().composeSetter(other); } /** compose a {@link PIso} with a {@link PTraversal} */ public final PTraversal composeTraversal(final PTraversal other) { return asTraversal().composeTraversal(other); } /** compose a {@link PIso} with a {@link POptional} */ public final POptional composeOptional(final POptional other) { return asOptional().composeOptional(other); } /** compose a {@link PIso} with a {@link PPrism} */ public final PPrism composePrism(final PPrism other) { return asPrism().composePrism(other); } /** compose a {@link PIso} with a {@link PLens} */ public final PLens composeLens(final PLens other) { return asLens().composeLens(other); } /** compose a {@link PIso} with a {@link PIso} */ public final PIso composeIso(final PIso other) { final PIso self = this; return new PIso() { @Override public C get(final S s) { return other.get(self.get(s)); } @Override public T reverseGet(final D d) { return self.reverseGet(other.reverseGet(d)); } @Override public PIso reverse() { final PIso composeSelf = this; return new PIso() { @Override public T get(final D d) { return self.reverseGet(other.reverseGet(d)); } @Override public C reverseGet(final S s) { return other.get(self.get(s)); } @Override public PIso reverse() { return composeSelf; } }; } }; } /****************************************************************/ /** Transformation methods to view a {@link PIso} as another Optics */ /****************************************************************/ /** view a {@link PIso} 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(PIso.this.get(s)); } }; } /** view a {@link PIso} as a {@link Getter} */ public final Getter asGetter() { return new Getter() { @Override public A get(final S s) { return PIso.this.get(s); } }; } /** view a {@link PIso} as a {@link Setter} */ public PSetter asSetter() { return new PSetter() { @Override public F modify(final F f) { return PIso.this.modify(f); } @Override public F set(final B b) { return PIso.this.set(b); } }; } /** view a {@link PIso} as a {@link PTraversal} */ public PTraversal asTraversal() { final PIso 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(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(self.get(s)); } }; } /** view a {@link PIso} as a {@link POptional} */ public POptional asOptional() { final PIso self = this; return new POptional() { @Override public Either getOrModify(final S s) { return Either.right(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 set(final B b) { return self.set(b); } @Override public Option getOption(final S s) { return Option.some(self.get(s)); } @Override public F modify(final F f) { return self.modify(f); } }; } /** view a {@link PIso} as a {@link PPrism} */ public PPrism asPrism() { final PIso self = this; return new PPrism() { @Override public Either getOrModify(final S s) { return Either.right(self.get(s)); } @Override public T reverseGet(final B b) { return self.reverseGet(b); } @Override public Option getOption(final S s) { return Option.some(self.get(s)); } }; } /** view a {@link PIso} as a {@link PLens} */ public PLens asLens() { final PIso self = this; return new PLens() { @Override public A get(final S s) { return self.get(s); } @Override public F set(final B b) { return self.set(b); } @Override public F modify(final F f) { return self.modify(f); } @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); } }; } /** create a {@link PIso} using a pair of functions: one to get the target and one to get the source. */ public static PIso pIso(final F get, final F reverseGet) { return new PIso() { @Override public A get(final S s) { return get.f(s); } @Override public T reverseGet(final B b) { return reverseGet.f(b); } @Override public PIso reverse() { final PIso self = this; return new PIso() { @Override public T get(final B b) { return reverseGet.f(b); } @Override public A reverseGet(final S s) { return get.f(s); } @Override public PIso reverse() { return self; } }; } }; } /** * create a {@link PIso} between any type and itself. id is the zero element of optics composition, for all optics o of type O * (e.g. Lens, Iso, Prism, ...): * *
   *  o composeIso Iso.id == o
   *  Iso.id composeO o == o
   * 
* * (replace composeO by composeLens, composeIso, composePrism, ...) */ public static PIso pId() { return new PIso() { @Override public S get(final S s) { return s; } @Override public T reverseGet(final T t) { return t; } @Override public PIso reverse() { final PIso self = this; return new PIso() { @Override public T get(final T t) { return t; } @Override public S reverseGet(final S s) { return s; } @Override public PIso reverse() { return self; } }; } }; } }