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

fj.Function 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.data.Option;

/**
 * Transformations on functions.
 *
 * @version %build.number%
 */
public final class Function {
  private Function() {
    throw new UnsupportedOperationException();
  }

  /**
   * Function application with the arguments flipped.
   *
   * @param a The value to apply the function to.
   * @return A function that is partially-applied to the given value.
   */
  public static  F, B> apply(final A a) {
    return new F, B>() {
      public B f(final F k) {
        return k.f(a);
      }
    };
  }

  /**
   * Function composition.
   *
   * @return A function that composes two functions to produce a new function.
   */
  public static  F, F, F>> compose() {
    return new F, F, F>>() {
      public F, F> f(final F f) {
        return new F, F>() {
          public F f(final F g) {
            return compose(f, g);
          }
        };
      }
    };
  }

  /**
   * Function composition.
   *
   * @param f A function to compose with another.
   * @param g A function to compose with another.
   * @return A function that is the composition of the given arguments.
   */
  public static  F compose(final F f, final F g) {
    return a -> f.f(g.f(a));
  }

  /**
   * Function composition.
   *
   * @param f A function to compose with another.
   * @param g A function to compose with another.
   * @return A function that is the composition of the given arguments.
   */
  public static  F> compose2(final F f, final F> g) {
    return a -> b -> f.f(g.f(a).f(b));
  }


  /**
   * Function composition flipped.
   *
   * @return A function that composes two functions to produce a new function.
   */
  public static  F, F, F>> andThen() {
    return g -> f -> Function.andThen(g, f);
  }

  /**
   * Function composition flipped.
   *
   * @param g A function to compose with another.
   * @param f A function to compose with another.
   * @return A function that is the composition of the given arguments.
   */
  public static  F andThen(final F g, final F f) {
    return a -> f.f(g.f(a));
  }

  /**
   * The identity transformation.
   *
   * @return The identity transformation.
   */
  public static  F identity() {
    return a -> a;
  }

  /**
   * Returns a function that given an argument, returns a function that ignores its argument.
   *
   * @return A function that given an argument, returns a function that ignores its argument.
   */
  public static  F> constant() {
    return b -> constant(b);
  }

  /**
   * Returns a function that ignores its argument to constantly produce the given value.
   *
   * @param b The value to return when the returned function is applied.
   * @return A function that ignores its argument to constantly produce the given value.
   */
  public static  F constant(final B b) {
    return a -> b;
  }

  /**
   * Simultaneously covaries and contravaries a function.
   *
   * @param f The function to vary.
   * @return A co- and contravariant function that invokes f on its argument.
   */
  public static  F vary(final F f) {
    return a -> f.f(a);
  }

  /**
   * Simultaneously covaries and contravaries a function.
   *
   * @return A function that varies and covaries a function.
   */
  public static  F, F> vary() {
    return f -> Function.vary(f);
  }

  /**
   * Function argument flipping.
   *
   * @return A function that takes a function and flips its arguments.
   */
  public static  F>, F>> flip() {
    return f -> flip(f);
  }

  /**
   * Function argument flipping.
   *
   * @param f The function to flip.
   * @return The given function flipped.
   */
  public static  F> flip(final F> f) {
    return b -> a -> f.f(a).f(b);
  }

  /**
   * Function argument flipping.
   *
   * @param f The function to flip.
   * @return The given function flipped.
   */
  public static  F2 flip(final F2 f) {
    return (b, a) -> f.f(a, b);
  }

  /**
   * Function argument flipping.
   *
   * @return A function that flips the arguments of a given function.
   */
  public static  F, F2> flip2() {
    return f -> flip(f);
  }

  /**
   * Return a function that inspects the argument of the given function for a null value and if so, does
   * not apply the value, instead returning an empty optional value.
   *
   * @param f The function to check for a null argument.
   * @return A function that inspects the argument of the given function for a null value and if so, does
   * not apply the value, instead returning an empty optional value.
   */
  public static  F> nullable(final F f) {
    return a -> a == null ? Option.none() : Option.some(f.f(a));
  }

  /**
   * Curry a function of arity-2.
   *
   * @param f The function to curry.
   * @return A curried form of the given function.
   */
  public static  F> curry(final F2 f) {
    return a -> b -> f.f(a, b);
  }

  /**
   * Curry a function of arity-2.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F curry(final F2 f, final A a) {
    return curry(f).f(a);
  }

  /**
   * Uncurry a function of arity-2.
   *
   * @return An uncurried function.
   */
  public static  F>, F2> uncurryF2() {
    return f -> uncurryF2(f);
  }

  /**
   * Uncurry a function of arity-2.
   *
   * @param f The function to uncurry.
   * @return An uncurried function.
   */
  public static  F2 uncurryF2(final F> f) {
    return (a, b) -> f.f(a).f(b);
  }

  /**
   * Curry a function of arity-3.
   *
   * @param f The function to curry.
   * @return A curried form of the given function.
   */
  public static  F>> curry(final F3 f) {
    return a -> b -> c -> f.f(a, b, c);
  }

  /**
   * Curry a function of arity-3.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F> curry(final F3 f, final A a) {
    return curry(f).f(a);
  }

  /**
   * Curry a function of arity-3.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F curry(final F3 f, final A a, final B b) {
    return curry(f, a).f(b);
  }

  /**
   * Uncurry a function of arity-3.
   *
   * @return An uncurried function.
   */
  public static  F>>, F3> uncurryF3() {
    return f -> uncurryF3(f);
  }

  /**
   * Uncurry a function of arity-3.
   *
   * @param f The function to uncurry.
   * @return An uncurried function.
   */
  public static  F3 uncurryF3(final F>> f) {
    return (a, b, c) -> f.f(a).f(b).f(c);
  }

  /**
   * Curry a function of arity-4.
   *
   * @param f The function to curry.
   * @return A curried form of the given function.
   */
  public static  F>>> curry(final F4 f) {
    return a -> b -> c -> d -> f.f(a, b, c, d);
  }

  /**
   * Curry a function of arity-4.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>> curry(final F4 f, final A a) {
    return curry(f).f(a);
  }

  /**
   * Curry a function of arity-4.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F> curry(final F4 f, final A a, final B b) {
    return curry(f).f(a).f(b);
  }

  /**
   * Curry a function of arity-4.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @param c An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F curry(final F4 f, final A a, final B b, final C c) {
    return curry(f).f(a).f(b).f(c);
  }

  /**
   * Uncurry a function of arity-4.
   *
   * @return An uncurried function.
   */
  public static  F>>>, F4> uncurryF4() {
    return f -> uncurryF4(f);
  }

  /**
   * Uncurry a function of arity-4.
   *
   * @param f The function to uncurry.
   * @return An uncurried function.
   */
  public static  F4 uncurryF4(final F>>> f) {
    return (a, b, c, d) -> f.f(a).f(b).f(c).f(d);
  }

  /**
   * Curry a function of arity-5.
   *
   * @param f The function to curry.
   * @return A curried form of the given function.
   */
  public static  F>>>> curry(final F5 f) {
    return a -> b -> c -> d -> e -> f.f(a, b, c, d, e);
  }

  /**
   * Curry a function of arity-5.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>>> curry(final F5 f, final A a) {
    return curry(f).f(a);
  }

  /**
   * Curry a function of arity-5.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>> curry(final F5 f, final A a, final B b) {
    return curry(f).f(a).f(b);
  }

  /**
   * Curry a function of arity-5.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @param c An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F> curry(final F5 f, final A a, final B b,
                                                         final C c) {
    return curry(f).f(a).f(b).f(c);
  }

  /**
   * Curry a function of arity-5.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @param c An argument to the curried function.
   * @param d An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F curry(final F5 f, final A a, final B b, final C c,
                                                   final D d) {
    return curry(f).f(a).f(b).f(c).f(d);
  }

  /**
   * Uncurry a function of arity-5.
   *
   * @return An uncurried function.
   */
  public static  F>>>>, F5> uncurryF5() {
    return f -> uncurryF5(f);
  }

  /**
   * Uncurry a function of arity-6.
   *
   * @param f The function to uncurry.
   * @return An uncurried function.
   */
  public static  F5 uncurryF5(final F>>>> f) {
    return (a, b, c, d, e) -> f.f(a).f(b).f(c).f(d).f(e);
  }

  /**
   * Curry a function of arity-6.
   *
   * @param f The function to curry.
   * @return A curried form of the given function.
   */
  public static  F>>>>> curry(final F6 f) {
    return a -> b -> c -> d -> e -> f$ -> f.f(a, b, c, d, e, f$);
  }

  /**
   * Uncurry a function of arity-6.
   *
   * @return An uncurried function.
   */
  public static  F>>>>>, F6> uncurryF6() {
    return f -> uncurryF6(f);
  }

  /**
   * Uncurry a function of arity-6.
   *
   * @param f The function to uncurry.
   * @return An uncurried function.
   */
  public static  F6 uncurryF6(
      final F>>>>> f) {
    return (a, b, c, d, e, f$) -> f.f(a).f(b).f(c).f(d).f(e).f(f$);
  }

  /**
   * Curry a function of arity-7.
   *
   * @param f The function to curry.
   * @return A curried form of the given function.
   */
  public static  F>>>>>> curry(
      final F7 f) {
    return a -> b -> c -> d -> e -> f$ -> g -> f.f(a, b, c, d, e, f$, g);
  }

  /**
   * Curry a function of arity-7.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>>>>> curry(
      final F7 f, final A a) {
    return curry(f).f(a);
  }

  /**
   * Curry a function of arity-7.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>>>> curry(final F7 f,
                                                                                 final A a, final B b) {
    return curry(f).f(a).f(b);
  }

  /**
   * Curry a function of arity-7.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @param c An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>>> curry(final F7 f,
                                                                           final A a, final B b, final C c) {
    return curry(f).f(a).f(b).f(c);
  }

  /**
   * Curry a function of arity-7.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @param c An argument to the curried function.
   * @param d An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>> curry(final F7 f, final A a,
                                                                     final B b, final C c, final D d) {
    return curry(f).f(a).f(b).f(c).f(d);
  }

  /**
   * Curry a function of arity-7.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @param c An argument to the curried function.
   * @param d An argument to the curried function.
   * @param e An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F> curry(final F7 f, final A a,
                                                               final B b, final C c, final D d, final E e) {
    return curry(f).f(a).f(b).f(c).f(d).f(e);
  }

  /**
   * Curry a function of arity-7.
   *
   * @param f  The function to curry.
   * @param a  An argument to the curried function.
   * @param b  An argument to the curried function.
   * @param c  An argument to the curried function.
   * @param d  An argument to the curried function.
   * @param e  An argument to the curried function.
   * @param f$ An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F curry(final F7 f, final A a, final B b,
                                                        final C c, final D d, final E e, final F$ f$) {
    return curry(f).f(a).f(b).f(c).f(d).f(e).f(f$);
  }

  /**
   * Uncurry a function of arity-7.
   *
   * @return An uncurried function.
   */
  public static  F>>>>>>, F7> uncurryF7() {
    return new F>>>>>>, F7>() {
      public F7 f(final F>>>>>> f) {
        return uncurryF7(f);
      }
    };
  }

  /**
   * Uncurry a function of arity-7.
   *
   * @param f The function to uncurry.
   * @return An uncurried function.
   */
  public static  F7 uncurryF7(
      final F>>>>>> f) {
    return (a, b, c, d, e, f$, g) -> f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g);
  }

  /**
   * Curry a function of arity-8.
   *
   * @param f The function to curry.
   * @return A curried form of the given function.
   */
  public static  F>>>>>>> curry(
      final F8 f) {
    return a -> b -> c -> d -> e -> f$ -> g -> h -> f.f(a, b, c, d, e, f$, g, h);
  }

  /**
   * Curry a function of arity-8.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>>>>>> curry(
      final F8 f, final A a) {
    return curry(f).f(a);
  }

  /**
   * Curry a function of arity-8.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>>>>> curry(
      final F8 f, final A a, final B b) {
    return curry(f).f(a).f(b);
  }

  /**
   * Curry a function of arity-8.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @param c An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>>>> curry(
      final F8 f, final A a, final B b, final C c) {
    return curry(f).f(a).f(b).f(c);
  }

  /**
   * Curry a function of arity-8.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @param c An argument to the curried function.
   * @param d An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>>> curry(final F8 f,
                                                                              final A a, final B b, final C c,
                                                                              final D d) {
    return curry(f).f(a).f(b).f(c).f(d);
  }

  /**
   * Curry a function of arity-8.
   *
   * @param f The function to curry.
   * @param a An argument to the curried function.
   * @param b An argument to the curried function.
   * @param c An argument to the curried function.
   * @param d An argument to the curried function.
   * @param e An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F>> curry(final F8 f,
                                                                        final A a, final B b, final C c, final D d,
                                                                        final E e) {
    return curry(f).f(a).f(b).f(c).f(d).f(e);
  }

  /**
   * Curry a function of arity-8.
   *
   * @param f  The function to curry.
   * @param a  An argument to the curried function.
   * @param b  An argument to the curried function.
   * @param c  An argument to the curried function.
   * @param d  An argument to the curried function.
   * @param e  An argument to the curried function.
   * @param f$ An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F> curry(final F8 f, final A a,
                                                                 final B b, final C c, final D d, final E e,
                                                                 final F$ f$) {
    return curry(f).f(a).f(b).f(c).f(d).f(e).f(f$);
  }

  /**
   * Curry a function of arity-7.
   *
   * @param f  The function to curry.
   * @param a  An argument to the curried function.
   * @param b  An argument to the curried function.
   * @param c  An argument to the curried function.
   * @param d  An argument to the curried function.
   * @param e  An argument to the curried function.
   * @param f$ An argument to the curried function.
   * @param g  An argument to the curried function.
   * @return A curried form of the given function.
   */
  public static  F curry(final F8 f, final A a, final B b,
                                                           final C c, final D d, final E e, final F$ f$, final G g) {
    return curry(f).f(a).f(b).f(c).f(d).f(e).f(f$).f(g);
  }

  /**
   * Uncurry a function of arity-8.
   *
   * @return An uncurried function.
   */
  public static  F>>>>>>>, F8> uncurryF8() {
    return f -> uncurryF8(f);
  }

  /**
   * Uncurry a function of arity-8.
   *
   * @param f The function to uncurry.
   * @return An uncurried function.
   */
  public static  F8 uncurryF8(
      final F>>>>>>> f) {
    return (a, b, c, d, e, f$, g, h) -> f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g).f(h);
  }

  /**
   * Binds the function in the second argument to the function in the first argument.
   *
   * @param ma A function whose argument type is the same as the argument type of the return value.
   * @param f  A function whose argument type is the same as the return type of ma,
   *           and yields the return value.
   * @return A function that chains the given functions together such that the result of applying
   *         ma to the argument is given to f, yielding a function
   *         that is applied to the argument again.
   */
  public static  F bind(final F ma, final F> f) {
    return m -> f.f(ma.f(m)).f(m);
  }

  /**
   * Performs function application within a higher-order function (applicative functor pattern).
   *
   * @param cab The higher-order function to apply a function to.
   * @param ca  A function to apply within a higher-order function.
   * @return A new function after applying the given higher-order function to the given function.
   */
  public static  F apply(final F> cab, final F ca) {
    return bind(cab, f -> compose(a -> f.f(a), ca));
  }

  /**
   * Binds the given function f to the values of the given functions, with a final join.
   *
   * @param ca A function to bind f function to.
   * @param cb A function to bind f function to.
   * @param f  The bound function to be composed with ca and then applied with cb
   * @return A new function after performing the composition, then application.
   */
  public static  F bind(final F ca, final F cb, final F> f) {
    return apply(compose(f, ca), cb);
  }

  /**
   * Applies a given function over the arguments of another function of arity-2.
   *
   * @param a The function whose arguments to apply another function over.
   * @param f The function to apply over the arguments of another function.
   * @return A function whose arguments are fed through function f, before being passed to function a.
   */
  public static  F> on(final F> a, final F f) {
    return compose(compose(Function.andThen().f(f), a), f);
  }

  /**
   * Promotes a function of arity-2 to a higher-order function.
   *
   * @param f The function to promote.
   * @return A function of arity-2 promoted to compose with two functions.
   */
  public static  F, F, F>> lift(final F> f) {
    return curry((ca, cb) -> bind(ca, cb, f));
  }

  /**
   * Joins two arguments of a function of arity-2 into one argument, yielding a function of arity-1.
   *
   * @param f A function whose arguments to join.
   * @return A function of arity-1 whose argument is substituted for both parameters of f.
   */
  public static  F join(final F> f) {
    return bind(f, Function.>identity());
  }


  /**
   * Partial application of the second argument to the supplied function to get a function of type
   * A -> C. Same as flip(f).f(b).
   *
   * @param f The function to partially apply.
   * @param b The value to apply to the function.
   * @return A new function based on f with its second argument applied.
   */
  public static  F partialApply2(final F> f, final B b) {
    return a -> uncurryF2(f).f(a, b);
  }

  /**
   * Partial application of the third argument to the supplied function to get a function of type
   * A -> B -> D.
   *
   * @param f The function to partially apply.
   * @param c The value to apply to the function.
   * @return A new function based on f with its third argument applied.
   */
  public static  F> partialApply3(final F>> f, final C c) {
    return a -> b -> uncurryF3(f).f(a, b, c);
  }

  /**
   * Partial application of the fourth argument to the supplied function to get a function of type
   * A -> B -> C -> E.
   *
   * @param f The function to partially apply.
   * @param d The value to apply to the function.
   * @return A new function based on f with its fourth argument applied.
   */
  public static  F>> partialApply4(final F>>> f, final D d) {
    return a -> b -> c -> uncurryF4(f).f(a, b, c, d);
  }

  /**
   * Partial application of the fifth argument to the supplied function to get a function of type
   * A -> B -> C -> D -> F$.
   *
   * @param f The function to partially apply.
   * @param e The value to apply to the function.
   * @return A new function based on f with its fifth argument applied.
   */
  public static  F>>> partialApply5(final F>>>> f,
                                                                             final E e) {
    return a -> b -> c -> d -> uncurryF5(f).f(a, b, c, d, e);
  }

  /**
   * Partial application of the sixth argument to the supplied function to get a function of type
   * A -> B -> C -> D -> E -> G.
   *
   * @param f  The function to partially apply.
   * @param f$ The value to apply to the function.
   * @return A new function based on f with its sixth argument applied.
   */
  public static  F>>>> partialApply6(
      final F>>>>> f, final F$ f$) {
    return a -> b -> c -> d -> e -> uncurryF6(f).f(a, b, c, d, e, f$);
  }

  /**
   * Partial application of the seventh argument to the supplied function to get a function of type
   * A -> B -> C -> D -> E -> F$ -> H.
   *
   * @param f The function to partially apply.
   * @param g The value to apply to the function.
   * @return A new function based on f with its seventh argument applied.
   */
  public static  F>>>>> partialApply7(
      final F>>>>>> f, final G g) {
    return a -> b -> c -> d -> e -> f$ -> uncurryF7(f).f(a, b, c, d, e, f$, g);
  }

  /**
   * Partial application of the eigth argument to the supplied function to get a function of type
   * A -> B -> C -> D -> E -> F$ -> G -> I.
   *
   * @param f The function to partially apply.
   * @param h The value to apply to the function.
   * @return A new function based on f with its eigth argument applied.
   */
  public static  F>>>>>> partialApply8(
      final F>>>>>>> f, final H h) {
    return a -> b -> c -> d -> e -> f$ -> g -> uncurryF8(f).f(a, b, c, d, e, f$, g, h);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy