fj.data.optic.PTraversal Maven / Gradle / Ivy
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