fj.data.optic.Fold 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.data.Either;
import fj.data.List;
import fj.data.Option;
/**
* A {@link Fold} can be seen as a {@link Getter} with many targets or a weaker {@link PTraversal} which cannot modify its
* target.
*
* {@link Fold} is on the top of the Optic hierarchy which means that {@link Getter}, {@link PTraversal}, {@link POptional},
* {@link PLens}, {@link PPrism} and {@link PIso} are valid {@link Fold}
*
* @param the source of a {@link Fold}
* @param the target of a {@link Fold}
*/
public abstract class Fold {
/**
* map each target to a {@link Monoid} and combine the results underlying representation of {@link Fold}, all {@link Fold}
* methods are defined in terms of foldMap
*/
public abstract F foldMap(Monoid m, 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 Fold} TODO: Shall it return a Stream as there might be an infinite number of targets?
*/
public final List getAll(final S s) {
return foldMap(Monoid.listMonoid(), List::single).f(s);
}
/** find the first target of a {@link Fold} 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 Fold} */
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);
}
/** join two {@link Fold} with the same target */
public final Fold, A> sum(final Fold other) {
return new Fold, A>() {
@Override
public F, B> foldMap(final Monoid m, final F f) {
return s -> s.either(Fold.this.foldMap(m, f), other.foldMap(m, f));
}
};
}
/**********************************************************/
/** Compose methods between a {@link Fold} and another Optics */
/**********************************************************/
/** compose a {@link Fold} with a {@link Fold} */
public final Fold composeFold(final Fold other) {
return new Fold() {
@Override
public F foldMap(final Monoid m, final F f) {
return Fold.this. foldMap(m, other. foldMap(m, f));
}
};
}
/** compose a {@link Fold} with a {@link Getter} */
public final Fold composeGetter(final Getter other) {
return composeFold(other.asFold());
}
/** compose a {@link Fold} with a {@link POptional} */
public final Fold composeOptional(final POptional other) {
return composeFold(other.asFold());
}
/** compose a {@link Fold} with a {@link PPrism} */
public final Fold composePrism(final PPrism other) {
return composeFold(other.asFold());
}
/** compose a {@link Fold} with a {@link PLens} */
public final Fold composeLens(final PLens other) {
return composeFold(other.asFold());
}
/** compose a {@link Fold} with a {@link PIso} */
public final Fold composeIso(final PIso other) {
return composeFold(other.asFold());
}
public static Fold id() {
return PIso. pId().asFold();
}
public static final Fold, A> codiagonal() {
return new Fold, A>() {
@Override
public F, B> foldMap(final Monoid m, final F f) {
return e -> e.either(f, f);
}
};
}
}