package functional;
/**
* Function:
* A function is meant to represent something that takes one input and returns
* one output with no side-effects.
*
* @author Peter Goodman
*
* @param <I> input type
* @param <O> output type
*/
abstract public class F<I,O> {
/**
* Call the function.
*/
abstract public O call(I val);
/**
* Chained function composition combinator.
*/
public <C> F<I,C> followedBy(F<O,C> outer) {
return F.compose(outer, this);
}
/**
* Function composition combinator. The order of arguments is outer(inner( .. )).
*/
static public <A,B,C> F<A,C> compose(final F<B,C> outer, final F<A,B> inner) {
return new F<A,C>() {
public C call(A param) {
return outer.call(inner.call(param));
}
};
}
/**
* Transform a function that takes a pair into a function of two arguments.
* De-structuring the Tuple argument is convenient because it then means we
* can curry either of the elements of the tuple.
*/
static public <A,B,C> F2<A,B,C> destructure(final F<Tuple<A,B>,C> fn) {
return new F2<A,B,C>() {
public C call(A a, B b) {
return fn.call(new Tuple<A,B>(a, b));
}
};
}
}