## Motivation

Say you have a list of pairs

```
val xs: List[(Int, Int)]
```

and you want to map `xs`

to a list of `Int`

s so that each pair of numbers is mapped to their sum.
Previously, the best way to do this was with a pattern-matching decomposition:

```
xs.map {
case (x, y) => x + y
}
```

While correct, this is inconvenient. Instead, we propose to write it the following way:

```
xs.map {
(x, y) => x + y
}
```

or, equivalently:

```
xs.map(_ + _)
```

Generally, a function value with `n > 1`

parameters can be converted to a function with tupled arguments if the expected type is a unary function type of the form `((T_1, ..., T_n)) => U`

.

## Type Checking

The type checking happens in two steps:

- Check whether parameter untupling is feasible
- Adapt the function and type check it

### Feasibility Check

Suppose a function `f`

of the form `(p1, ..., pn) => e`

(where `n > 1`

), with `p1, ..., pn`

as parameters and `e`

as function body.

If the expected type for checking `f`

is a fully defined function type of the form `TupleN[T1, ..., Tn] => R`

(or an equivalent SAM-type), where each type `Ti`

fits the corresponding parameter `pi`

. Then `f`

is feasible for parameter untupling with the expected type `TupleN[T1, ..., Tn] => R`

.

A type `Ti`

fits a parameter `pi`

if one of the following two cases is `true`

:

`pi`

comes without a type, i.e. it is a simple identifier or`_`

.`pi`

is of the form`x: Ui`

or`_: Ui`

and`Ti <: Ui`

.

Parameter untupling composes with eta-expansion. That is, an n-ary function generated by eta-expansion can in turn be adapted to the expected type with parameter untupling.

### Term adaptation

If the function

```
(p1, ..., pn) => e
```

is feasible for parameter untupling with the expected type `TupleN[T1, ..., Tn] => Te`

, then continue to type check the following adapted function

```
(x: TupleN[T1, ..., Tn]) =>
def p1: T1 = x._1
...
def pn: Tn = x._n
e
```

with the same expected type.

## Migration

Code like this could not be written before, hence the new notation would not be ambiguous after adoption.

Though it is possible that someone has written an implicit conversion form `(T1, ..., Tn) => R`

to `TupleN[T1, ..., Tn] => R`

for some `n`

. This change could be detected and fixed by `Scalafix`

. Furthermore, such conversion would probably
be doing the same translation (semantically) but in a less efficient way.

## Reference

For more information, see Issue #897.