fj.data.optic.PTraversal 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.F3;
import fj.F4;
import fj.F5;
import fj.F6;
import fj.F7;
import fj.Function;
import fj.Monoid;
import fj.P;
import fj.P1;
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 PTraversal} can be seen as a {@link POptional} generalised to 0 to n targets where n can be infinite.
*
* {@link PTraversal} stands for Polymorphic Traversal as it set and modify methods change a type `A` to `B` and `S` to `T`.
* {@link Traversal} is a {@link PTraversal} restricted to monomoprhic updates.
*
* @param the source of a {@link PTraversal}
* @param the modified source of a {@link PTraversal}
* @param the target of a {@link PTraversal}
* @param the modified target of a {@link PTraversal}
*/
public abstract class PTraversal {
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyFunctionF(F> f);
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyEitherF(F> f);
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyIOF(F> f);
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyTrampolineF(F> f);
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyPromiseF(F> f);
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyListF(F> f);
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyOptionF(F> f);
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyStreamF(F> f);
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyP1F(F> f);
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyValidationF(F> f);
/**
* modify polymorphically the target of a {@link PTraversal} with an Applicative function
*/
public abstract F> modifyV2F(F> f);
/** map each target to a {@link Monoid} and combine the results */
public abstract F foldMap(Monoid monoid, F f);
/** combine all targets using a target's {@link Monoid} */
public final F fold(final Monoid m) {
return foldMap(m, Function.identity());
}
/** get all the targets of a {@link PTraversal} */
public final List getAll(final S s) {
return foldMap(Monoid.listMonoid(), List::single).f(s);
}
/** find the first target of a {@link PTraversal} matching the predicate */
public final F> find(final F p) {
return foldMap(Monoid.optionMonoid(), a -> p.f(a) ? Option.some(a) : Option.none());
}
/** get the first target of a {@link PTraversal} */
public final Option headOption(final S s) {
return find(Function.constant(Boolean.TRUE)).f(s);
}
/** check if at least one target satisfies the predicate */
public final F exist(final F p) {
return foldMap(Monoid.disjunctionMonoid, p);
}
/** check if all targets satisfy the predicate */
public final F all(final F p) {
return foldMap(Monoid.conjunctionMonoid, p);
}
/** modify polymorphically the target of a {@link PTraversal} with a function */
public final F modify(final F f) {
return s -> this.modifyP1F(a -> P.p(f.f(a))).f(s)._1();
}
/** set polymorphically the target of a {@link PTraversal} with a value */
public final F set(final B b) {
return modify(Function.constant(b));
}
/** join two {@link PTraversal} with the same target */
public final PTraversal, Either, A, B> sum(final PTraversal other) {
final PTraversal self = this;
return new PTraversal, Either, A, B>() {
@Override
public F, F>> modifyFunctionF(final F> f) {
return ss1 -> ss1.either(
s -> Function.compose(Either.left_(), self.modifyFunctionF(f).f(s)),
s1 -> Function.compose(Either.right_(), other.modifyFunctionF(f).f(s1))
);
}
@Override
public F, Either>> modifyEitherF(final F> f) {
return ss1 -> ss1.either(
s -> self.modifyEitherF(f).f(s).right().map(Either.left_()),
s1 -> other.modifyEitherF(f).f(s1).right().map(Either.right_())
);
}
@Override
public F, IO>> modifyIOF(final F> f) {
return ss1 -> ss1.either(
s -> IOFunctions.map(self.modifyIOF(f).f(s), Either.left_()),
s1 -> IOFunctions.map(other.modifyIOF(f).f(s1), Either.right_())
);
}
@Override
public F, Trampoline>> modifyTrampolineF(final F> f) {
return ss1 -> ss1.either(
s -> self.modifyTrampolineF(f).f(s).map(Either.left_()),
s1 -> other.modifyTrampolineF(f).f(s1).map(Either.right_())
);
}
@Override
public F, Promise>> modifyPromiseF(final F> f) {
return ss1 -> ss1.either(
s -> self.modifyPromiseF(f).f(s).fmap(Either.left_()),
s1 -> other.modifyPromiseF(f).f(s1).fmap(Either.right_())
);
}
@Override
public F, List>> modifyListF(final F> f) {
return ss1 -> ss1.either(
s -> self.modifyListF(f).f(s).map(Either.left_()),
s1 -> other.modifyListF(f).f(s1).map(Either.right_())
);
}
@Override
public F, Option>> modifyOptionF(final F> f) {
return ss1 -> ss1.either(
s -> self.modifyOptionF(f).f(s).map(Either.left_()),
s1 -> other.modifyOptionF(f).f(s1).map(Either.right_())
);
}
@Override
public F, Stream>> modifyStreamF(final F> f) {
return ss1 -> ss1.either(
s -> self.modifyStreamF(f).f(s).map(Either.left_()),
s1 -> other.modifyStreamF(f).f(s1).map(Either.right_())
);
}
@Override
public F, P1>> modifyP1F(final F> f) {
return ss1 -> ss1.either(
s -> self.modifyP1F(f).f(s).map(Either.left_()),
s1 -> other.modifyP1F(f).f(s1).map(Either.right_())
);
}
@Override
public F, V2>> modifyV2F(final F> f) {
return ss1 -> ss1.either(
s -> self.modifyV2F(f).f(s).map(Either.left_()),
s1 -> other.modifyV2F(f).f(s1).map(Either.right_())
);
}
@Override
public F, Validation>> modifyValidationF(final F> f) {
return ss1 -> ss1.either(
s -> self.modifyValidationF(f).f(s).map(Either.left_()),
s1 -> other.modifyValidationF(f).f(s1).map(Either.right_())
);
}
@Override
public F, M> foldMap(final Monoid monoid, final F f) {
return ss1 -> ss1.either(
self.foldMap(monoid, f),
other.foldMap(monoid, f)
);
}
};
}
/****************************************************************/
/** Compose methods between a {@link PTraversal} and another Optics */
/****************************************************************/
/** compose a {@link PTraversal} with a {@link Fold} */
public final Fold composeFold(final Fold other) {
return asFold().composeFold(other);
}
//
/** compose a {@link PTraversal} with a {@link Getter} */
public final Fold composeFold(final Getter other) {
return asFold().composeGetter(other);
}
/** compose a {@link PTraversal} with a {@link PSetter} */
public final PSetter composeSetter(final PSetter other) {
return asSetter().composeSetter(other);
}
/** compose a {@link PTraversal} with a {@link PTraversal} */
public final PTraversal composeTraversal(final PTraversal other) {
final PTraversal self = this;
return new PTraversal() {
@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 foldMap(final Monoid monoid, final F f) {
return self.foldMap(monoid, other.foldMap(monoid, f));
}
};
}
/** compose a {@link PTraversal} with a {@link POptional} */
public final PTraversal composeOptional(final POptional other) {
return composeTraversal(other.asTraversal());
}
/** compose a {@link PTraversal} with a {@link PPrism} */
public final PTraversal composePrism(final PPrism other) {
return composeTraversal(other.asTraversal());
}
/** compose a {@link PTraversal} with a {@link PLens} */
public final PTraversal composeLens(final PLens other) {
return composeTraversal(other.asTraversal());
}
/** compose a {@link PTraversal} with a {@link PIso} */
public final PTraversal composeIso(final PIso other) {
return composeTraversal(other.asTraversal());
}
/**********************************************************************/
/** Transformation methods to view a {@link PTraversal} as another Optics */
/**********************************************************************/
/** view a {@link PTraversal} as a {@link Fold} */
public final Fold asFold() {
return new Fold() {
@Override
public F foldMap(final Monoid monoid, final F f) {
return PTraversal.this.foldMap(monoid, f);
}
};
}
/** view a {@link PTraversal} as a {@link PSetter} */
public PSetter asSetter() {
return PSetter.pSetter(this::modify);
}
public static PTraversal pId() {
return PIso. pId().asTraversal();
}
public static PTraversal, Either, S, T> pCodiagonal() {
return new PTraversal, Either, S, T>() {
@Override
public F, F>> modifyFunctionF(final F> f) {
return s -> s.bimap(f, f).either(
f1 -> Function.compose(Either.left_(), f1),
f1 -> Function.compose(Either.right_(), f1)
);
}
@Override
public F, Either>> modifyEitherF(final F> f) {
return s -> s.bimap(f, f).either(
e -> e.right().map(Either.left_()),
e -> e.right().map(Either.right_())
);
}
@Override
public F, IO>> modifyIOF(final F> f) {
return s -> s.bimap(f, f).either(
io -> IOFunctions.map(io, Either.left_()),
io -> IOFunctions.map(io, Either.right_())
);
}
@Override
public F, Trampoline>> modifyTrampolineF(final F> f) {
return s -> s.bimap(f, f).either(
t -> t.map(Either.left_()),
t -> t.map(Either.right_())
);
}
@Override
public F, Promise>> modifyPromiseF(final F> f) {
return s -> s.bimap(f, f).either(
p -> p.fmap(Either.left_()),
p -> p.fmap(Either.right_())
);
}
@Override
public F, List>> modifyListF(final F> f) {
return s -> s.bimap(f, f).either(
l -> l.map(Either.left_()),
l -> l.map(Either.right_())
);
}
@Override
public F, Option>> modifyOptionF(final F> f) {
return s -> s.bimap(f, f).either(
o -> o.map(Either.left_()),
o -> o.map(Either.right_())
);
}
@Override
public F, Stream>> modifyStreamF(final F> f) {
return s -> s.bimap(f, f).either(
stream -> stream.map(Either.left_()),
stream -> stream.map(Either.right_())
);
}
@Override
public F, P1>> modifyP1F(final F> f) {
return s -> s.bimap(f, f).either(
p1 -> p1.map(Either.left_()),
p1 -> p1.map(Either.right_())
);
}
@Override
public F, V2>> modifyV2F(final F> f) {
return s -> s.bimap(f, f).either(
v2 -> v2.map(Either.left_()),
v2 -> v2.map(Either.right_())
);
}
@Override
public F, Validation>> modifyValidationF(final F> f) {
return s -> s.bimap(f, f).either(
v -> v.map(Either.left_()),
v -> v.map(Either.right_())
);
}
@Override
public F, M> foldMap(final Monoid monoid, final F f) {
return s -> s.either(f, f);
}
};
}
public static PTraversal pTraversal(final F get1, final F get2,
final F3 set) {
return new PTraversal() {
@Override
public F> modifyFunctionF(final F> f) {
return s -> Function.apply(Function.compose(b1 -> b2 -> set.f(b1, b2, s), f.f(get1.f(s))), f.f(get2.f(s)));
}
@Override
public F> modifyEitherF(final F> f) {
return s -> f.f(get2.f(s)).right().apply(f.f(get1.f(s)).right().> map(b1 -> b2 -> set.f(b1, b2, s)));
}
@Override
public F> modifyIOF(final F> f) {
return s -> IOFunctions.apply(f.f(get2.f(s)),
IOFunctions.> map(f.f(get1.f(s)), b1 -> b2 -> set.f(b1, b2, s)));
}
@Override
public F> modifyTrampolineF(final F> f) {
return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s)));
}
@Override
public F> modifyPromiseF(final F> f) {
return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> fmap(b1 -> b2 -> set.f(b1, b2, s)));
}
@Override
public F> modifyListF(final F> f) {
return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s)));
}
@Override
public F> modifyOptionF(final F> f) {
return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s)));
}
@Override
public F> modifyStreamF(final F> f) {
return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s)));
}
@Override
public F> modifyP1F(final F> f) {
return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s)));
}
@Override
public F> modifyV2F(final F> f) {
return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s)));
}
@Override
public F> modifyValidationF(final F> f) {
return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s)));
}
@Override
public F foldMap(final Monoid monoid, final F f) {
return s -> monoid.sum(f.f(get1.f(s)), f.f(get2.f(s)));
}
};
}
public static PTraversal pTraversal(final F get1, final F get2, final F