fj.data.optic.PIso Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of functionaljava Show documentation
Show all versions of functionaljava Show documentation
Functional Java is an open source library that supports closures for the Java programming language
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;
}
};
}
};
}
}