import java.util.concurrent.Callable;

class NotBoundFunctionException extends Exception { }
class FunctionUndefinedException extends Exception { }

abstract class Function<A,R> {
    public abstract R call(final A arg);
}

class CallableFunction<A,R> implements Callable<R> {
    private A _arg;
    public A arg() { return this._arg;}
    public void arg(A arg) { this._arg = arg; }

    private Function<A,R> _fun;
    public Function<A,R> fun() { return this._fun; }
    public void fun(Function<A,R> fun) { this._fun = fun; }

    public CallableFunction() { }
    public CallableFunction(A arg) { this.arg(arg); }
    public CallableFunction(Function<A,R> fun) { this.fun(fun); }
    public CallableFunction(Function<A,R> fun, A arg) {
        this.fun(fun);
        this.arg(arg);
    }

    public Callable<R> bind(A arg) { this.arg(arg); return this; }

    public R call() throws Exception {
        if ( this.arg() == null) { throw new NotBoundFunctionException(); }
        if ( this.fun() == null) { throw new FunctionUndefinedException(); }
        return this.fun().call(this.arg());
    }
    public R call(A arg) throws Exception {
        return this.bind(arg).call();
    }
}


class CurryComposed {
    public static void main(String[] args) {
        Function<Integer,Function<Integer,Integer>> add = new Function<Integer,Function<Integer,Integer>>(){
            public Function<Integer,Integer> call(final Integer a) {
                return new Function<Integer,Integer>(){
                    public Integer call(final Integer b) {
                        return a + b;
                    }
                };
            }
        };

        try {

            System.out.println(add.call(21).call(21));

            Function<Integer,Integer> partialAdd = add.call(21);
            System.out.println(partialAdd.call(21));

            CallableFunction<Integer,Integer> callableAdd = new CallableFunction<Integer,Integer>(partialAdd);
            System.out.println(callableAdd.call(21));

            System.out.println(callableAdd.bind(1316).call());

            System.out.println((new CallableFunction<Integer,Integer>(add.call(668))).bind(669).call());

        } catch (Exception e) { System.exit(1); }
    }
}
