/** * Maps this elements to a {@code Monoid} and applies {@code foldLeft}, starting with {@code * monoid.zero()}: * * <pre><code> * foldLeft(monoid.zero(), (ys, x) -> monoid.combine(ys, mapper.apply(x))); * </code></pre> * * @param monoid A Monoid * @param foldable A foldable * @param mapper A mapper * @param <T> type of the foldable elements * @param <U> Component type of the given monoid. * @return the folded monoid value. * @throws NullPointerException if {@code monoid} or {@code mapper} is null */ static <T, U> U foldMap( Monoid<U> monoid, Foldable<T> foldable, Function<? super T, ? extends U> mapper) { Objects.requireNonNull(monoid, "monoid is null"); Objects.requireNonNull(foldable, "foldable is null"); Objects.requireNonNull(mapper, "mapper is null"); return foldable.foldLeft(monoid.zero(), (ys, x) -> monoid.combine(ys, mapper.apply(x))); }
/** * Folds the elements of {@code Foldable} from the left, starting with {@code monoid.zero()} and * successively calling {@code monoid::combine}. * * @param monoid A monoid, providing a {@code zero} and a {@code combine} function. * @param foldable A foldable * @param <T> type of the foldable elements * @return a folded value * @throws NullPointerException if {@code monoid} or {@code foldable} is null */ static <T> T fold(Monoid<T> monoid, Foldable<T> foldable) { Objects.requireNonNull(monoid, "monoid is null"); Objects.requireNonNull(foldable, "foldable is null"); return foldable.foldLeft(monoid.zero(), monoid::combine); }
/** * The monoid of endomorphisms under composition. * * @param <A> Value type * @return The monoid of endomorphisms of type A. */ static <A> Monoid<Function<A, A>> endoMonoid() { return Monoid.of(Function.identity(), Function::compose); }