All patterns would have to be of the same length, and ideally they should be ll(1) patterns, so they could dispatch on the first arg. Or should the pattern matching occur after the function got all of its arguments?
What I would really like to see is currying with partial function application and dispatch on every function argument, so that (my-curried-fun (annotate 'foo val)) is evaluated to a curried function for the type foo. Otherwise the (types|patterns) would have to be compared everytime this function is applied, which may be inefficient, e.g in