"Curries a function, returning a function with two 
 parameter lists, given a function with at least
 one parameter. The first parameter list of the 
 returned function has just the first parameter
 of the original function, and the second parameter
 list has the remaining parameters.
 
 That is, if `fun` has type `W(X,Y,Z)` then 
 `curry(fun)` has type `W(Y,Z)(X)`."
see (`function uncurry`, `function compose`)
shared Callable<Return,Rest> curry<Return,Argument,First,Rest>
            (Callable<Return,Tuple<Argument,First,Rest>> f)
            (First first)
        given First satisfies Argument 
        given Rest satisfies Argument[] 
                => flatten((Rest args) 
                        => unflatten(f)(Tuple(first, args)));

"Uncurries a function, returning a function with 
 one parameter list, given a function with two
 parameter lists, where the first parameter list
 has exactly one parameter. The parameter list
 of the returned function has the parameter of
 the first parameter list of the original
 function, followed by all parameters of the
 second parameter list.
 
 That is, if `fun` has type `W(Y,Z)(X)` then 
 `uncurry(fun)` has type `W(X,Y,Z)`."
see (`function curry`, `function compose`)
shared Callable<Return,Tuple<Argument,First,Rest>> 
        uncurry<Return,Argument,First,Rest>
            (Callable<Return,Rest> f(First first))
        given First satisfies Argument 
        given Rest satisfies Argument[] 
                => flatten((Tuple<Argument,First,Rest> args) 
                        => unflatten(f(args.first))(args.rest));