
fj.data.optic.PIso Maven / Gradle / Ivy
package fj.data.optic;
import fj.F;
import fj.Function;
import fj.Monoid;
import fj.P;
import fj.P1;
import fj.P2;
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 PIso} defines an isomorphism between types S, A and B, T:
*
* {@code
* get reverse.get
* --------------------> -------------------->
* S A T B
* <-------------------- <--------------------
* reverse.reverseGet reverseGet
* }
*
* In addition, if f and g forms an isomorphism between {@code A} and {@code B}, i.e. if {@code f . g = id} and {@code g . f = id}, then a {@link PIso}
* defines an isomorphism between {@code S} and {@code T}:
*
* {@code
* 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(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(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, ...):
*
* {@code
* 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;
}
};
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy