Dotty: Auto Tupling when partial function is expected

Created on 20 Dec 2017  路  5Comments  路  Source: lampepfl/dotty

This currently compiles:

class Test {
  def foo(f: PartialFunction[(Int, Int), Int]) = ???
  foo((a, b) => 1)
}

I don't think we should apply auto-tupling in this case though.

bug revisit

Most helpful comment

I personally think this behavior is intuitive. A total function is a partial function that happens to cover all inputs. I wish Function was a subtype of PartialFunction instead of the other way around, it's one of the biggest warts in the standard library in my opinion.

All 5 comments

I personally think this behavior is intuitive. A total function is a partial function that happens to cover all inputs. I wish Function was a subtype of PartialFunction instead of the other way around, it's one of the biggest warts in the standard library in my opinion.

The documentation says:

Generally, a function value with n > 1 parameters is converted to a pattern-matching closure using case if the expected type is a unary function type of the form ((T_1, ..., T_n)) => U

This actually works because PartialFunction[(T_1, ..., T_n), U] is a subtype of ((T_1, ..., T_n)) => U:

class Test {
  trait Foo extends Function1[(Int, Int), Int]
  def foo(f: Foo) = ???
  foo((a, b) => 1) // OK
}

But then you can write something like:

class Test {
  trait Foo extends Function1[(Int, Int), Int] {
    def bar: Int
  }
  def foo(f: Foo) = f.bar
  foo((a, b) => 1)
}

and get nonsensical errors:

-- [E081] Syntax Error: tests/allan/Test.scala:6:7 -----------------------------
6 |  foo((a, b) => 1)
  |       ^
  |       missing parameter type for parameter a, expected = ?

longer explanation available when compiling with `-explain`
-- [E081] Syntax Error: tests/allan/Test.scala:6:10 ----------------------------
6 |  foo((a, b) => 1)
  |          ^
  |          missing parameter type for parameter b, expected = ?

One more puzzle with partial functions:

class Foo extends Product2[Int, Int] {
  def _1 = 1
  def _2 = 2
  def canEqual(that: Any) = ???
}

val xs: List[Product2[Int, Int]] = List(new Foo)
xs.collect { case (x, y) => x + y } // List()
xs.collect((x, y) => x + y) // List(3)

We decided to disallow auto-tupling for partial functions

I am not sure anymore what the right way is. Anyway, I don't think we should act on this until we have sorted out PartialFunctions. And once we did that, the answer to the question of auto-tupling or not is probably "whatever fits best".

Was this page helpful?
0 / 5 - 0 ratings