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.*; /** * Created by MarkPerry on 22/01/2015. */ public abstract class F1W<A, B> implements F<A, B> { /** * Function composition * * @param g A function to compose with this one. * @return The composed function such that this function is applied last. */ public final <C> F1W<C, B> o(final F<C, A> g) { return lift(F1Functions.o(this, g)); } /** * First-class function composition * * @return A function that composes this function with another. */ public final <C> F1W<F<C, A>, F<C, B>> o() { return lift(F1Functions.o(this)); } /** * 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 final <C> F1W<A, C> andThen(final F<B, C> g) { return lift(F1Functions.andThen(this, g)); } /** * First-class composition flipped. * * @return A function that invokes this function and then a given function on the result. */ public final <C> F1W<F<B, C>, F<A, C>> andThen() { return lift( F1Functions.andThen(this)); } /** * 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 final <C> F1W<A, C> bind(final F<B, F<A, C>> g) { return lift(F1Functions.bind(this, g)); } /** * First-class function binding. * * @return A function that binds another function across this function. */ public final <C> F1W<F<B, F<A, C>>, F<A, C>> bind() { return lift(F1Functions.bind(this)); } /** * 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 final <C> F1W<A, C> apply(final F<A, F<B, C>> g) { return lift(F1Functions.apply(this, g)); } /** * First-class function application in an environment. * * @return A function that applies a given function within the environment of this function. */ public final <C> F1W<F<A, F<B, C>>, F<A, C>> apply() { return lift(F1Functions.apply(this)); } /** * 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 final <C> F1W<A, F<A, C>> on(final F<B, F<B, C>> g) { return lift(F1Functions.on(this, g)); } /** * Applies this function over the arguments of another function. * * @return A function that applies this function over the arguments of another function. */ public final <C> F1W<F<B, F<B, C>>, F<A, F<A, C>>> on() { return lift(F1Functions.on(this)); } /** * 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 final F1W<A, P1<B>> lazy() { return lift(F1Functions.lazy(this)); } /** * Partial application. * * @param a The <code>A</code> to which to apply this function. * @return The function partially applied to the given argument to return a lazy value. */ public final P1<B> lazy(final A a) { return F1Functions.f(this, a); } /** * Promotes this function to map over a product-1. * * @return This function promoted to map over a product-1. */ public final F1W<P1<A>, P1<B>> mapP1() { return lift(F1Functions.mapP1(this)); } /** * 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 final F1W<A, Option<B>> optionK() { return lift(F1Functions.optionK(this)); } /** * Promotes this function to map over an optional value. * * @return This function promoted to map over an optional value. */ public final F1W<Option<A>, Option<B>> mapOption() { return lift(F1Functions.mapOption(this)); } /** * 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 final F1W<A, List<B>> listK() { return lift( F1Functions.listK(this)); } /** * Promotes this function to map over a List. * * @return This function promoted to map over a List. */ public final F1W<List<A>, List<B>> mapList() { return lift(F1Functions.mapList(this)); } /** * 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 final F1W<A, Stream<B>> streamK() { return lift(F1Functions.streamK(this)); } /** * Promotes this function to map over a Stream. * * @return This function promoted to map over a Stream. */ public final F1W<Stream<A>, Stream<B>> mapStream() { return lift(F1Functions.mapStream(this)); } /** * 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 final F1W<A, Array<B>> arrayK() { return lift(F1Functions.arrayK(this)); } /** * Promotes this function to map over a Array. * * @return This function promoted to map over a Array. */ public final F1W<Array<A>, Array<B>> mapArray() { return lift(F1Functions.mapArray(this)); } /** * Returns a function that contramaps over a given actor. * * @return A function that contramaps over a given actor. */ public final F1W<Actor<B>, Actor<A>> contramapActor() { return lift(F1Functions.contramapActor(this)); } /** * 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 final F1W<A, Promise<B>> promiseK(final Strategy<Unit> s) { return lift(F1Functions.promiseK(this, s)); } /** * Promotes this function to map over a Promise. * * @return This function promoted to map over Promises. */ public final F1W<Promise<A>, Promise<B>> mapPromise() { return lift(F1Functions.mapPromise(this)); } /** * 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 final <C> F1W<A, Either<B, C>> eitherLeftK() { return lift(F1Functions.eitherLeftK(this)); } /** * 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 final <C> F1W<A, Either<C, B>> eitherRightK() { return lift(F1Functions.eitherRightK(this)); } /** * 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 final <X> F1W<Either<A, X>, Either<B, X>> mapLeft() { return lift(F1Functions.mapLeft(this)); } /** * 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 final <X> F1W<Either<X, A>, Either<X, B>> mapRight() { return lift(F1Functions.mapRight(this)); } /** * 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 final F1W<Either<B, A>, B> onLeft() { return lift(F1Functions.onLeft(this)); } /** * 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 final F1W<Either<A, B>, B> onRight() { return lift(F1Functions.onRight(this)); } /** * Promotes this function to return its value in an Iterable. * * @return This function promoted to return its value in an Iterable. */ @SuppressWarnings("unchecked") public final F1W<A, IterableW<B>> iterableK() { return lift( F1Functions.iterableK(this)); } /** * Promotes this function to map over Iterables. * * @return This function promoted to map over Iterables. */ @SuppressWarnings("unchecked") public final F1W<Iterable<A>, IterableW<B>> mapIterable() { return lift( F1Functions.mapIterable(this)); } /** * Promotes this function to return its value in a NonEmptyList. * * @return This function promoted to return its value in a NonEmptyList. */ @SuppressWarnings("unchecked") public final F1W<A, NonEmptyList<B>> nelK() { return lift(F1Functions.nelK(this)); } /** * Promotes this function to map over a NonEmptyList. * * @return This function promoted to map over a NonEmptyList. */ public final F1W<NonEmptyList<A>, NonEmptyList<B>> mapNel() { return lift(F1Functions.mapNel(this)); } /** * 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 final F1W<A, Set<B>> setK(final Ord<B> o) { return lift(F1Functions.setK(this, o)); } /** * 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 final F1W<Set<A>, Set<B>> mapSet(final Ord<B> o) { return lift(F1Functions.mapSet(this, o)); } /** * Promotes this function to return its value in a Tree. * * @return This function promoted to return its value in a Tree. */ public final F1W<A, Tree<B>> treeK() { return lift(F1Functions.treeK(this)); } /** * Promotes this function to map over a Tree. * * @return This function promoted to map over a Tree. */ @SuppressWarnings("unchecked") public final F1W<Tree<A>, Tree<B>> mapTree() { return lift(F1Functions.mapTree(this)); } /** * 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 final F1W<Tree<A>, B> foldMapTree(final Monoid<B> m) { return lift(F1Functions.foldMapTree(this, m)); } /** * Promotes this function to return its value in a TreeZipper. * * @return This function promoted to return its value in a TreeZipper. */ public final F1W<A, TreeZipper<B>> treeZipperK() { return lift(F1Functions.treeZipperK(this)); } /** * Promotes this function to map over a TreeZipper. * * @return This function promoted to map over a TreeZipper. */ public final F1W<TreeZipper<A>, TreeZipper<B>> mapTreeZipper() { return lift(F1Functions.mapTreeZipper(this)); } /** * 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 final <C> F1W<A, Validation<B, C>> failK() { return lift(F1Functions.failK(this)); } /** * 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 final <C> F1W<A, Validation<C, B>> successK() { return lift( F1Functions.successK(this)); } /** * 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 final <X> F1W<Validation<A, X>, Validation<B, X>> mapFail() { return lift(F1Functions.mapFail(this)); } /** * 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 final <X> F1W<Validation<X, A>, Validation<X, B>> mapSuccess() { return lift(F1Functions.mapSuccess(this)); } /** * 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 final F1W<Validation<B, A>, B> onFail() { return lift(F1Functions.onFail(this)); } /** * 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 final F1W<Validation<A, B>, B> onSuccess() { return lift(F1Functions.onSuccess(this)); } /** * Promotes this function to return its value in a Zipper. * * @return This function promoted to return its value in a Zipper. */ public final F1W<A, Zipper<B>> zipperK() { return lift(F1Functions.zipperK(this)); } /** * Promotes this function to map over a Zipper. * * @return This function promoted to map over a Zipper. */ public final F1W<Zipper<A>, Zipper<B>> mapZipper() { return lift(F1Functions.mapZipper(this)); } /** * 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 final F1W<Equal<B>, Equal<A>> contramapEqual() { return lift(F1Functions.contramapEqual(this)); } /** * 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 final F1W<Hash<B>, Hash<A>> contramapHash() { return lift(F1Functions.contramapHash(this)); } /** * 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 final F1W<Show<B>, Show<A>> contramapShow() { return lift(F1Functions.contramapShow(this)); } /** * 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 final <C> F1W<P2<A, C>, P2<B, C>> mapFst() { return lift(F1Functions.mapFst(this)); } /** * 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 final <C> F1W<P2<C, A>, P2<C, B>> mapSnd() { return lift(F1Functions.mapSnd(this)); } /** * Promotes this function to map over both elements of a pair. * * @return This function promoted to map over both elements of a pair. */ public final F1W<P2<A, A>, P2<B, B>> mapBoth() { return lift(F1Functions.mapBoth(this)); } /** * 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 final SynchronousQueue<B> mapJ(final SynchronousQueue<A> as) { return F1Functions.mapJ(this, as); } /** * 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 final PriorityBlockingQueue<B> mapJ(final PriorityBlockingQueue<A> as) { return F1Functions.mapJ(this, as); } /** * 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 final LinkedBlockingQueue<B> mapJ(final LinkedBlockingQueue<A> as) { return F1Functions.mapJ(this, as); } /** * 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 final CopyOnWriteArraySet<B> mapJ(final CopyOnWriteArraySet<A> as) { return F1Functions.mapJ(this, as); } /** * 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 final CopyOnWriteArrayList<B> mapJ(final CopyOnWriteArrayList<A> as) { return F1Functions.mapJ(this, as); } /** * 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 final ConcurrentLinkedQueue<B> mapJ(final ConcurrentLinkedQueue<A> as) { return F1Functions.mapJ(this, as); } /** * 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 final ArrayBlockingQueue<B> mapJ(final ArrayBlockingQueue<A> as) { return F1Functions.mapJ(this, as); } /** * 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 final TreeSet<B> mapJ(final TreeSet<A> as) { return F1Functions.mapJ(this, as); } /** * 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 final PriorityQueue<B> mapJ(final PriorityQueue<A> as) { return F1Functions.mapJ(this, as); } /** * 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 final LinkedList<B> mapJ(final LinkedList<A> as) { return F1Functions.mapJ(this, as); } /** * 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 final ArrayList<B> mapJ(final ArrayList<A> as) { return F1Functions.mapJ(this, as); } public final <C> F1W<A, C> map(F<B, C> f) { return lift(F1Functions.map(this, f)); } public final <C> F1W<C, B> contramap(F<C, A> f) { return lift(F1Functions.contramap(this, f)); } public static class F1WFunc<A, B> extends F1W<A, B> { final F<A, B> func; public F1WFunc(F<A, B> f) { func = f; } @Override public final B f(A a) { return func.f(a); } } /** * Lifts the function into the fully featured function wrapper */ public static <A, B> F1W<A, B> lift(final F<A, B> f) { return new F1WFunc<>(f); } }