tl;博士
案例类的伴随对象在具有类型参数时不能扩展FunctionN(定义tupled,使用N >= 2)。使用
(Foo[Int] _).tupled
讨论
当你有一个普通的类时
case class Bar(x: Int, y: Int)
它的构造函数实际上是一个Function2[Int, Int, Bar],因此当编译器生成伴随对象Bar时,它可以方便地使其扩展Function2。
生成的代码将是
class Bar extends AnyRef with Product with Serializable { ... }
object Bar extends Function2[Int, Int, Bar] with Serializable { ... }
现在考虑
case class Foo[T](x: T, y: T)
如果你尝试使用同样的技巧,你很快就会发现自己有麻烦了:
// this can't compile, what's T?
object Foo extends Function2[T, T, Bar] with Serializable { ... }
由于T 是未知的,编译器不能使Foo 成为Function2 的子类,它不能做得比扩展AnyRef 更好:
class Foo[T] extends AnyRef with Product with Serializable { ... }
object Foo extends AnyRef with Serializable { ... }
这是上面讨论的快速证明(使用scala -Xprint:typer):
scala> case class Bar(x: Int, y: Int)
...
<synthetic> object Bar extends scala.runtime.AbstractFunction2[Int,Int,Bar] with Serializable {
...
scala> case class Foo[T](x: T, y: T)
...
<synthetic> object Foo extends AnyRef with Serializable {
...
总结一下,当你有类型参数时,你必须先获得一个Function2
val f: Function2[Int, Int, Foo] = Foo[Int] _
然后你可以拨打tupled就可以了
f.tupled // ((Int, Int)) => Foo[Int]