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 new F() { public C f(final A a) { return 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 new F>() { public F f(final A a) { return new F() { public D f(final B b) { return 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 new F, F, F>>() { public F, F> f(final F g) { return new F, F>() { public F f(final F f) { return 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 new F() { public C f(final A a) { return f.f(g.f(a)); } }; } /** * The identity transformation. * * @return The identity transformation. */ public static F identity() { return new F() { public A f(final A a) { return 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 new F>() { public F f(final B b) { return 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 new F() { public B f(final A a) { return 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 new F() { public B f(final A a) { return f.f(a); } }; } /** * Simultaneously covaries and contravaries a function. * * @return A function that varies and covaries a function. */ public static F, F> vary() { return new F, F>() { public F f(final F f) { return Function.vary(f); } }; } /** * Function argument flipping. * * @return A function that takes a function and flips its arguments. */ public static F>, F>> flip() { return new F>, F>>() { public F> f(final F> f) { return flip(f); } }; } /** * Function argument flipping. * * @param f The function to flip. * @return The given function flipped. */ public static F> flip(final F> f) { return new F>() { public F f(final B b) { return new F() { public C f(final A a) { return 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 new F2() { public C f(final B b, final A a) { return f.f(a, b); } }; } /** * Function argument flipping. * * @return A function that flips the arguments of a given function. */ public static F, F2> flip2() { return new F, F2>() { public F2 f(final F2 f) { return 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 new F>() { public Option f(final A a) { return 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 new F>() { public F f(final A a) { return new F() { public C f(final B b) { return 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 new F>, F2>() { public F2 f(final F> f) { return 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 new F2() { public C f(final A a, final B b) { return 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 new F>>() { public F> f(final A a) { return new F>() { public F f(final B b) { return new F() { public D f(final C c) { return 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 new F>>, F3>() { public F3 f(final F>> f) { return 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 new F3() { public D f(final A a, final B b, final C c) { return 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 new F>>>() { public F>> f(final A a) { return new F>>() { public F> f(final B b) { return new F>() { public F f(final C c) { return new F() { public E f(final D d) { return 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 new F>>>, F4>() { public F4 f(final F>>> f) { return 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 new F4() { public E f(final A a, final B b, final C c, final D d) { return 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 new F>>>>() { public F>>> f(final A a) { return new F>>>() { public F>> f(final B b) { return new F>>() { public F> f(final C c) { return new F>() { public F f(final D d) { return new F() { public F$ f(final E e) { return 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 new F>>>>, F5>() { public F5 f(final F>>>> f) { return 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 new F5() { public F$ f(final A a, final B b, final C c, final D d, final E e) { return 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 new F>>>>>() { public F>>>> f(final A a) { return new F>>>>() { public F>>> f(final B b) { return new F>>>() { public F>> f(final C c) { return new F>>() { public F> f(final D d) { return new F>() { public F f(final E e) { return new F() { public G f(final F$ f$) { return f.f(a, b, c, d, e, f$); } }; } }; } }; } }; } }; } }; } /** * Uncurry a function of arity-6. * * @return An uncurried function. */ public static F>>>>>, F6> uncurryF6() { return new F>>>>>, F6>() { public F6 f(final F>>>>> f) { return 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 new F6() { public G f(final A a, final B b, final C c, final D d, final E e, final F$ f$) { return 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 new F>>>>>>() { public F>>>>> f(final A a) { return new F>>>>>() { public F>>>> f(final B b) { return new F>>>>() { public F>>> f(final C c) { return new F>>>() { public F>> f(final D d) { return new F>>() { public F> f(final E e) { return new F>() { public F f(final F$ f$) { return new F() { public H f(final G g) { return 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 new F7() { public H f(final A a, final B b, final C c, final D d, final E e, final F$ f$, final G g) { return 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 new F>>>>>>>() { public F>>>>>> f(final A a) { return new F>>>>>>() { public F>>>>> f(final B b) { return new F>>>>>() { public F>>>> f(final C c) { return new F>>>>() { public F>>> f(final D d) { return new F>>>() { public F>> f(final E e) { return new F>>() { public F> f(final F$ f$) { return new F>() { public F f(final G g) { return new F() { public I f(final H h) { return 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 new F>>>>>>>, F8>() { public F8 f(final F>>>>>>> f) { return 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 new F8() { public I f(final A a, final B b, final C c, final D d, final E e, final F$ f$, final G g, final H h) { return 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 new F() { public B f(final C m) { return 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, new F, F>() { public F f(final F f) { return compose(new F() { public B f(final A a) { return 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(new F2, F, F>() { public F f(final F ca, final F cb) { return 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 new F() { public C f(final A a) { return 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 new F>() { public F f(final A a) { return new F() { public D f(final B b) { return 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 new F>>() { public F> f(final A a) { return new F>() { public F f(final B b) { return new F() { public E f(final C c) { return 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 new F>>>() { public F>> f(final A a) { return new F>>() { public F> f(final B b) { return new F>() { public F f(final C c) { return new F() { public F$ f(final D d) { return 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 new F>>>>() { public F>>> f(final A a) { return new F>>>() { public F>> f(final B b) { return new F>>() { public F> f(final C c) { return new F>() { public F f(final D d) { return new F() { public G f(final E e) { return 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 new F>>>>>() { public F>>>> f(final A a) { return new F>>>>() { public F>>> f(final B b) { return new F>>>() { public F>> f(final C c) { return new F>>() { public F> f(final D d) { return new F>() { public F f(final E e) { return new F() { public H f(final F$ f$) { return 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 new F>>>>>>() { public F>>>>> f(final A a) { return new F>>>>>() { public F>>>> f(final B b) { return new F>>>>() { public F>>> f(final C c) { return new F>>>() { public F>> f(final D d) { return new F>>() { public F> f(final E e) { return new F>() { public F f(final F$ f$) { return new F() { public I f(final G g) { return uncurryF8(f).f(a, b, c, d, e, f$, g, h); } }; } }; } }; } }; } }; } }; } }; } }