package functional;
/**
* Function:
* A function of two arguments and a single return value.
*
* @author Peter Goodman
*
* @param <I1> input type 1
* @param <I2> input type 2
* @param <O> output type
*/
abstract public class F2<I1,I2,O> {
/**
* Call the function.
*/
abstract public O call(I1 a, I2 b);
/**
* Chainable currying.
*/
public F<I2,O> applyFirst(I1 a) {
return F2.curry1(a, this);
}
/**
* Chainable currying.
*/
public F<I1,O> applySecond(I2 b) {
return F2.curry2(b, this);
}
/**
* Curry the first argument of a two-argument function. This method
* returns a single argument function.
*/
static public <A,B,C> F<B,C> curry1(final A a, final F2<A,B,C> fn) {
return new F<B,C>() {
public C call(B b) {
return fn.call(a, b);
}
};
}
/**
* Curry the second argument of a two-argument function. This method
* returns a single argument function.
*/
static public <A,B,C> F<A,C> curry2(final B b, final F2<A,B,C> fn) {
return new F<A,C>() {
public C call(A a) {
return fn.call(a, b);
}
};
}
/**
* Restructure a function of two arguments into a function of one argument.
* @param <A>
* @param <B>
* @param <C>
* @param fn
* @return
*/
static public <A,B,C> F<Tuple<A,B>,C> restructure(final F2<A,B,C> fn) {
return new F<Tuple<A,B>,C>() {
public C call(Tuple<A,B> a) {
return fn.call(a.first(), a.second());
}
};
}
}