All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fj.F1Functions Maven / Gradle / Ivy

Go to download

Functional Java is an open source library that supports closures for the Java programming language

There is a newer version: 5.0
Show newest version
package fj;

import fj.control.parallel.Actor;
import fj.control.parallel.Promise;
import fj.control.parallel.Strategy;
import fj.data.*;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.TreeSet;
import java.util.concurrent.*;

import static fj.data.Option.some;
import static fj.data.Stream.iterableStream;
import static fj.data.Zipper.fromStream;

/**
 * Created by MarkPerry on 6/04/2014.
 */
public final class F1Functions {


    private F1Functions() {
    }

    /**
     * Function composition
     *
     * @param g A function to compose with this one.
     * @return The composed function such that this function is applied last.
     */
    public static  F o(final F f, final F g) {
        return c -> f.f(g.f(c));
    }

    /**
     * First-class function composition
     *
     * @return A function that composes this function with another.
     */
    public static  F, F> o(final F f) {
        return g -> o(f, g);
    }

    /**
     * Function composition flipped.
     *
     * @param g A function with which to compose this one.
     * @return The composed function such that this function is applied first.
     */
    @SuppressWarnings("unchecked")
    public static  F andThen(final F f, final F g) {
        return o(g, f);
    }

    /**
     * First-class composition flipped.
     *
     * @return A function that invokes this function and then a given function on the result.
     */
    public static  F, F> andThen(final F f) {
        return g -> andThen(f, g);
    }

    /**
     * Binds a given function across this function (Reader Monad).
     *
     * @param g A function that takes the return value of this function as an argument, yielding a new function.
     * @return A function that invokes this function on its argument and then the given function on the result.
     */
    public static  F bind(final F f, final F> g) {
        return a ->  g.f(f.f(a)).f(a);
    }

    /**
     * First-class function binding.
     *
     * @return A function that binds another function across this function.
     */
    public static  F>, F> bind(final F f) {
        return g -> bind(f, g);
    }

    /**
     * Function application in an environment (Applicative Functor).
     *
     * @param g A function with the same argument type as this function, yielding a function that takes the return
     *          value of this function.
     * @return A new function that invokes the given function on its argument, yielding a new function that is then
     *         applied to the result of applying this function to the argument.
     */
    public static  F apply(final F f, final F> g) {
        return a -> g.f(a).f(f.f(a));
    }

    /**
     * First-class function application in an environment.
     *
     * @return A function that applies a given function within the environment of this function.
     */
    public static  F>, F> apply(final F f) {
        return g -> apply(f, g);
    }

    /**
     * Applies this function over the arguments of another function.
     *
     * @param g The function over whose arguments to apply this function.
     * @return A new function that invokes this function on its arguments before invoking the given function.
     */
    public static  F> on(final F f, final F> g) {
        return a1 -> a2 -> g.f(f.f(a1)).f(f.f(a2));
    }



    /**
     * Applies this function over the arguments of another function.
     *
     * @return A function that applies this function over the arguments of another function.
     */
    public static  F>, F>> on(final F f) {
        return g -> on(f, g);
    }

    /**
     * Promotes this function so that it returns its result in a product-1. Kleisli arrow for P1.
     *
     * @return This function promoted to return its result in a product-1.
     */
    public static  F> lazy(final F f) {
       return a -> P.lazy(() -> f.f(a));
    }

    /**
     * Partial application.
     *
     * @param a The A to which to apply this function.
     * @return The function partially applied to the given argument to return a lazy value.
     */
    public static  P1 f(final F f, final A a) {
        return P.lazy(() -> f.f(a));
    }

    /**
     * Promotes this function to map over a product-1.
     *
     * @return This function promoted to map over a product-1.
     */
    public static  F, P1> mapP1(final F f) {
        return p -> p.map(f);
    }

    /**
     * Promotes this function so that it returns its result in an Option. Kleisli arrow for Option.
     *
     * @return This function promoted to return its result in an Option.
     */
    public static  F> optionK(final F f) {
        return a -> some(f.f(a));
    }

    /**
     * Promotes this function to map over an optional value.
     *
     * @return This function promoted to map over an optional value.
     */
    public static  F, Option> mapOption(final F f) {
        return o -> o.map(f);
    }

    /**
     * Promotes this function so that it returns its result in a List. Kleisli arrow for List.
     *
     * @return This function promoted to return its result in a List.
     */
    public static  F> listK(final F f) {
        return a -> List.single(f.f(a));
    }

    /**
     * Promotes this function to map over a List.
     *
     * @return This function promoted to map over a List.
     */
    public static  F, List> mapList(final F f) {
        return x -> x.map(f);
    }

    /**
     * Promotes this function so that it returns its result in a Stream. Kleisli arrow for Stream.
     *
     * @return This function promoted to return its result in a Stream.
     */
    public static  F> streamK(final F f) {
        return a -> Stream.single(f.f(a));
    }

    /**
     * Promotes this function to map over a Stream.
     *
     * @return This function promoted to map over a Stream.
     */
    public static  F, Stream> mapStream(final F f) {
        return x -> x.map(f);
    }

    /**
     * Promotes this function so that it returns its result in a Array. Kleisli arrow for Array.
     *
     * @return This function promoted to return its result in a Array.
     */
    public static  F> arrayK(final F f) {
        return a -> Array.single(f.f(a));

    }

    /**
     * Promotes this function to map over a Array.
     *
     * @return This function promoted to map over a Array.
     */
    public static  F, Array> mapArray(final F f) {
        return x -> x.map(f);
    }

    /**
     * Returns a function that contramaps over a given actor.
     *
     * @return A function that contramaps over a given actor.
     */
    public static  F, Actor> contramapActor(final F f) {
        return a -> a.contramap(f);
    }

    /**
     * Promotes this function to a concurrent function that returns a Promise of a value.
     *
     * @param s A parallel strategy for concurrent execution.
     * @return A concurrent function that returns a Promise of a value.
     */
    public static  F> promiseK(final F f, final Strategy s) {
        return Promise.promise(s, f);
    }

    /**
     * Promotes this function to map over a Promise.
     *
     * @return This function promoted to map over Promises.
     */
    public static  F, Promise> mapPromise(final F f) {
        return p -> p.fmap(f);
    }

    /**
     * Promotes this function so that it returns its result on the left side of an Either.
     * Kleisli arrow for the Either left projection.
     *
     * @return This function promoted to return its result on the left side of an Either.
     */
    @SuppressWarnings("unchecked")
    public static  F> eitherLeftK(final F f) {
        return o(Either.left_(), f);
    }

    /**
     * Promotes this function so that it returns its result on the right side of an Either.
     * Kleisli arrow for the Either right projection.
     *
     * @return This function promoted to return its result on the right side of an Either.
     */
    @SuppressWarnings("unchecked")
    public static  F> eitherRightK(final F f) {
        return o(Either.right_(), f);
    }

    /**
     * Promotes this function to map over the left side of an Either.
     *
     * @return This function promoted to map over the left side of an Either.
     */
    @SuppressWarnings("unchecked")
    public static  F, Either> mapLeft(final F f) {
        return Either.leftMap_().f(f);
    }

    /**
     * Promotes this function to map over the right side of an Either.
     *
     * @return This function promoted to map over the right side of an Either.
     */
    @SuppressWarnings("unchecked")
    public static  F, Either> mapRight(final F f) {
        return Either.rightMap_().f(f);
    }

    /**
     * Returns a function that returns the left side of a given Either, or this function applied to the right side.
     *
     * @return a function that returns the left side of a given Either, or this function applied to the right side.
     */
    public static  F, B> onLeft(final F f) {
        return e -> e.left().on(f);
    }

    /**
     * Returns a function that returns the right side of a given Either, or this function applied to the left side.
     *
     * @return a function that returns the right side of a given Either, or this function applied to the left side.
     */
    public static  F, B> onRight(final F f) {
        return e -> e.right().on(f);
    }

    /**
     * Promotes this function to return its value in an Iterable.
     *
     * @return This function promoted to return its value in an Iterable.
     */
    @SuppressWarnings("unchecked")
    public static  F> iterableK(final F f) {
        return IterableW.arrow().f(f);
    }

    /**
     * Promotes this function to map over Iterables.
     *
     * @return This function promoted to map over Iterables.
     */
    @SuppressWarnings("unchecked")
    public static  F, IterableW> mapIterable(final F f) {
        return o(IterableW.map().f(f), IterableW.wrap());
    }

    /**
     * Promotes this function to return its value in a NonEmptyList.
     *
     * @return This function promoted to return its value in a NonEmptyList.
     */
    @SuppressWarnings("unchecked")
    public static  F> nelK(final F f) {
        return o(NonEmptyList.nel(), f);
    }

    /**
     * Promotes this function to map over a NonEmptyList.
     *
     * @return This function promoted to map over a NonEmptyList.
     */
    public static  F, NonEmptyList> mapNel(final F f) {
        return list -> list.map(f);
    }

    /**
     * Promotes this function to return its value in a Set.
     *
     * @param o An order for the set.
     * @return This function promoted to return its value in a Set.
     */
    public static  F> setK(final F f, final Ord o
    ) {
        return a -> Set.single(o, f.f(a));
    }

    /**
     * Promotes this function to map over a Set.
     *
     * @param o An order for the resulting set.
     * @return This function promoted to map over a Set.
     */
    public static  F, Set> mapSet(final F f, final Ord o) {
        return s -> s.map(o, f);
    }

    /**
     * Promotes this function to return its value in a Tree.
     *
     * @return This function promoted to return its value in a Tree.
     */
    public static  F> treeK(final F f) {
        return a -> Tree.leaf(f.f(a));
    }

    /**
     * Promotes this function to map over a Tree.
     *
     * @return This function promoted to map over a Tree.
     */
    @SuppressWarnings("unchecked")
    public static  F, Tree> mapTree(final F f) {
        return Tree.fmap_().f(f);
    }

    /**
     * Returns a function that maps this function over a tree and folds it with the given monoid.
     *
     * @param m The monoid with which to fold the mapped tree.
     * @return a function that maps this function over a tree and folds it with the given monoid.
     */
    public static  F, B> foldMapTree(final F f, final Monoid m) {
        return Tree.foldMap_(f, m);
    }

    /**
     * Promotes this function to return its value in a TreeZipper.
     *
     * @return This function promoted to return its value in a TreeZipper.
     */
    public static  F> treeZipperK(final F f) {
        return andThen(treeK(f), TreeZipper.fromTree());
    }

    /**
     * Promotes this function to map over a TreeZipper.
     *
     * @return This function promoted to map over a TreeZipper.
     */
    public static  F, TreeZipper> mapTreeZipper(final F f) {
        return (z) -> z.map(f);
    }

    /**
     * Promotes this function so that it returns its result on the failure side of a Validation.
     * Kleisli arrow for the Validation failure projection.
     *
     * @return This function promoted to return its result on the failure side of a Validation.
     */
    public static  F> failK(final F f) {
        return a -> Validation.fail(f.f(a));

    }

    /**
     * Promotes this function so that it returns its result on the success side of an Validation.
     * Kleisli arrow for the Validation success projection.
     *
     * @return This function promoted to return its result on the success side of an Validation.
     */
    public static  F> successK(final F f) {
        return a -> Validation.success(f.f(a));
    }

    /**
     * Promotes this function to map over the failure side of a Validation.
     *
     * @return This function promoted to map over the failure side of a Validation.
     */
    public static  F, Validation> mapFail(final F f) {
        return v -> v.f().map(f);
    }

    /**
     * Promotes this function to map over the success side of a Validation.
     *
     * @return This function promoted to map over the success side of a Validation.
     */
    public static  F, Validation> mapSuccess(final F f) {
        return v -> v.map(f);
    }

    /**
     * Returns a function that returns the failure side of a given Validation,
     * or this function applied to the success side.
     *
     * @return a function that returns the failure side of a given Validation,
     *         or this function applied to the success side.
     */
    public static  F, B> onFail(final F f) {
        return v -> v.f().on(f);
    }

    /**
     * Returns a function that returns the success side of a given Validation,
     * or this function applied to the failure side.
     *
     * @return a function that returns the success side of a given Validation,
     *         or this function applied to the failure side.
     */
    public static  F, B> onSuccess(final F f) {
        return v -> v.on(f);
    }

    /**
     * Promotes this function to return its value in a Zipper.
     *
     * @return This function promoted to return its value in a Zipper.
     */
    public static  F> zipperK(final F f) {
        return andThen(streamK(f), s -> fromStream(s).some());
    }

    /**
     * Promotes this function to map over a Zipper.
     *
     * @return This function promoted to map over a Zipper.
     */
    public static  F, Zipper> mapZipper(final F f) {
        return z -> z.map(f);
    }

    /**
     * Promotes this function to map over an Equal as a contravariant functor.
     *
     * @return This function promoted to map over an Equal as a contravariant functor.
     */
    public static  F, Equal> contramapEqual(final F f) {
        return e -> e.contramap(f);
    }

    /**
     * Promotes this function to map over a Hash as a contravariant functor.
     *
     * @return This function promoted to map over a Hash as a contravariant functor.
     */
    public static  F, Hash> contramapHash(final F f) {
        return h -> h.contramap(f);
    }

    /**
     * Promotes this function to map over a Show as a contravariant functor.
     *
     * @return This function promoted to map over a Show as a contravariant functor.
     */
    public static  F, Show> contramapShow(final F f) {
        return s -> s.contramap(f);
    }

    /**
     * Promotes this function to map over the first element of a pair.
     *
     * @return This function promoted to map over the first element of a pair.
     */
    public static  F, P2> mapFst(final F f) {
        return P2.map1_(f);
    }

    /**
     * Promotes this function to map over the second element of a pair.
     *
     * @return This function promoted to map over the second element of a pair.
     */
    public static  F, P2> mapSnd(final F f) {
        return P2.map2_(f);
    }

    /**
     * Promotes this function to map over both elements of a pair.
     *
     * @return This function promoted to map over both elements of a pair.
     */
    public static  F, P2> mapBoth(final F f) {
        return p2 -> P2.map(f, p2);
    }

    /**
     * Maps this function over a SynchronousQueue.
     *
     * @param as A SynchronousQueue to map this function over.
     * @return A new SynchronousQueue with this function applied to each element.
     */
    public static  SynchronousQueue mapJ(final F f, final SynchronousQueue as) {
        final SynchronousQueue bs = new SynchronousQueue<>();
        bs.addAll(iterableStream(as).map(f).toCollection());
        return bs;
    }


    /**
     * Maps this function over a PriorityBlockingQueue.
     *
     * @param as A PriorityBlockingQueue to map this function over.
     * @return A new PriorityBlockingQueue with this function applied to each element.
     */
    public static  PriorityBlockingQueue mapJ(final F f, final PriorityBlockingQueue as) {
        return new PriorityBlockingQueue<>(iterableStream(as).map(f).toCollection());
    }

    /**
     * Maps this function over a LinkedBlockingQueue.
     *
     * @param as A LinkedBlockingQueue to map this function over.
     * @return A new LinkedBlockingQueue with this function applied to each element.
     */
    public static  LinkedBlockingQueue mapJ(final F f, final LinkedBlockingQueue as) {
        return new LinkedBlockingQueue<>(iterableStream(as).map(f).toCollection());
    }

    /**
     * Maps this function over a CopyOnWriteArraySet.
     *
     * @param as A CopyOnWriteArraySet to map this function over.
     * @return A new CopyOnWriteArraySet with this function applied to each element.
     */
    public static  CopyOnWriteArraySet mapJ(final F f, final CopyOnWriteArraySet as) {
        return new CopyOnWriteArraySet<>(iterableStream(as).map(f).toCollection());
    }

    /**
     * Maps this function over a CopyOnWriteArrayList.
     *
     * @param as A CopyOnWriteArrayList to map this function over.
     * @return A new CopyOnWriteArrayList with this function applied to each element.
     */
    public static  CopyOnWriteArrayList mapJ(final F f, final CopyOnWriteArrayList as) {
        return new CopyOnWriteArrayList<>(iterableStream(as).map(f).toCollection());
    }

    /**
     * Maps this function over a ConcurrentLinkedQueue.
     *
     * @param as A ConcurrentLinkedQueue to map this function over.
     * @return A new ConcurrentLinkedQueue with this function applied to each element.
     */
    public static  ConcurrentLinkedQueue mapJ(final F f, final ConcurrentLinkedQueue as) {
        return new ConcurrentLinkedQueue<>(iterableStream(as).map(f).toCollection());
    }

    /**
     * Maps this function over an ArrayBlockingQueue.
     *
     * @param as An ArrayBlockingQueue to map this function over.
     * @return A new ArrayBlockingQueue with this function applied to each element.
     */
    public static  ArrayBlockingQueue mapJ(final F f, final ArrayBlockingQueue as) {
        final ArrayBlockingQueue bs = new ArrayBlockingQueue<>(as.size());
        bs.addAll(iterableStream(as).map(f).toCollection());
        return bs;
    }


    /**
     * Maps this function over a TreeSet.
     *
     * @param as A TreeSet to map this function over.
     * @return A new TreeSet with this function applied to each element.
     */
    public static  TreeSet mapJ(final F f, final TreeSet as) {
        return new TreeSet<>(iterableStream(as).map(f).toCollection());
    }

    /**
     * Maps this function over a PriorityQueue.
     *
     * @param as A PriorityQueue to map this function over.
     * @return A new PriorityQueue with this function applied to each element.
     */
    public static  PriorityQueue mapJ(final F f, final PriorityQueue as) {
        return new PriorityQueue<>(iterableStream(as).map(f).toCollection());
    }

    /**
     * Maps this function over a LinkedList.
     *
     * @param as A LinkedList to map this function over.
     * @return A new LinkedList with this function applied to each element.
     */
    public static  LinkedList mapJ(final F f, final LinkedList as) {
        return new LinkedList<>(iterableStream(as).map(f).toCollection());
    }

    /**
     * Maps this function over an ArrayList.
     *
     * @param as An ArrayList to map this function over.
     * @return A new ArrayList with this function applied to each element.
     */
    public static  ArrayList mapJ(final F f, final ArrayList as) {
        return new ArrayList<>(iterableStream(as).map(f).toCollection());
    }

    public static  F map(F target, F f) {
        return o(f, target);
    }

    public static  F contramap(F target, F f) {
        return o(target, f);
    }

    /**
     * Both map (with g) and contramap (with f) the target function. (Profunctor pattern)
     */
    public static  F dimap(F target, F f, F g) {
        return c -> g.f(target.f(f.f(c)));
    }

}