abra-lang icon indicating copy to clipboard operation
abra-lang copied to clipboard

Support "lower arity" functions passed as arguments

Open kengorab opened this issue 3 years ago • 0 comments

Let's say there's a function which accepts another function as an argument:

func doOp(a: Int, b: Int, fn: (Int, Int) => Int): Int {
  fn(a, b)
}

This function expects to be called with 3 parameters, 2 of which are Ints, and the last of which is a function which accepts 2 Ints and returns an Int. Some example calls are:

doOp(1, 2, (a, b) => a + b) // => 3
doOp(3, 4, (a, b) => a * b) // => 12
// etc

However, this enforces a limitation that doesn't need to exist. What if, for example, we don't really care about the second argument to the function that we pass as a parameter? What if, instead of doing any kind of mathematical operation, we just want to return a constant value? This does not pass typechecking:

doOp(1, 2, x => -x)
//         ^^^^^^^ Error, expected (Int, Int) => Int, got (Int) => Int

There's no reason that this should fail typechecking from a user's perspective. I could provide a function with two arguments and just disregard the second one:

doOp(1, 2, (x, y) => -x)
// or
doOp(1, 2, (x, _) => -x)

but that's just inconvenient and noisy.

A function passed as an argument should satisfy a type requirement if its n param types match the first n param types of the type requirement.

kengorab avatar Jul 28 '22 03:07 kengorab