"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`)
tagged("Functions")
shared Return(*Rest) curry<Return,Argument,First,Rest>
            (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`)
tagged("Functions")
shared Return(*Tuple<Argument,First,Rest>) 
        uncurry<Return,Argument,First,Rest>
            (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));