具有类型参数的案例类的Tupled方法

n1r*_*1r3 7 scala case-class

当具有带类型参数的case类时,我看不到如何调用该tupled方法.它似乎与apply和找到unapply.

scala> case class Foo[T](x:T, y:T)
defined class Foo

scala> Foo.apply[Int] _
res1: (Int, Int) => Foo[Int] = <function2>

scala> Foo.unapply[Int] _
res2: Foo[Int] => Option[(Int, Int)] = <function1>

scala> Foo.tupled[Int] _
<console>:10: error: value tupled is not a member of object Foo
              Foo.tupled[Int] _
              ^
Run Code Online (Sandbox Code Playgroud)

对于发生了什么有什么想法?

Gab*_*lla 15

TL;博士

案例类的伴随对象在具有类型参数时不能扩展FunctionN(tupled使用N> = 2 定义).使用

(Foo[Int] _).tupled
Run Code Online (Sandbox Code Playgroud)

讨论

当你有一个香草类如

case class Bar(x: Int, y: Int)
Run Code Online (Sandbox Code Playgroud)

它的构造函数实际上是一个Function2[Int, Int, Bar],因此当编译器生成伴随对象时,Bar它可以方便地扩展它Function2.

然后生成的代码将是

class Bar extends AnyRef with Product with Serializable { ... }
object Bar extends Function2[Int, Int, Bar] with Serializable { ... }
Run Code Online (Sandbox Code Playgroud)

现在考虑

case class Foo[T](x: T, y: T)
Run Code Online (Sandbox Code Playgroud)

如果你尝试应用同样的技巧,你很快就会遇到麻烦:

// this can't compile, what's T?
object Foo extends Function2[T, T, Bar] with Serializable { ... }
Run Code Online (Sandbox Code Playgroud)

由于T未知,编译器无法创建Foo子类,Function2并且它不能比使其扩展更好AnyRef:

class Foo[T] extends AnyRef with Product with Serializable { ... }
object Foo extends AnyRef with Serializable { ... }
Run Code Online (Sandbox Code Playgroud)

以下是上面讨论的内容的快速证明(使用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 {
...
Run Code Online (Sandbox Code Playgroud)

要包装它,当你有类型参数时,你必须获得Function2第一个

val f: Function2[Int, Int, Foo] = Foo[Int] _
Run Code Online (Sandbox Code Playgroud)

然后你可以打电话tupled给它

f.tupled // ((Int, Int)) => Foo[Int]
Run Code Online (Sandbox Code Playgroud)