Tupled method for case class having a type parameter

自闭症网瘾萝莉.ら 提交于 2019-12-05 05:17:26

tl;dr

Companion objects of case classes cannot extend FunctionN (which defines tupled, with N >= 2) when they have type parameters. Use

(Foo[Int] _).tupled

discussion

When you have a vanilla class such as

case class Bar(x: Int, y: Int)

its constructor is effectively a Function2[Int, Int, Bar], hence when the compiler generates the companion object Bar it can conveniently make it extend Function2.

The generated code will then be

class Bar extends AnyRef with Product with Serializable { ... }
object Bar extends Function2[Int, Int, Bar] with Serializable { ... }

Now consider

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

If you try to apply the same trick, you'll find yourself in trouble very soon:

// this can't compile, what's T?
object Foo extends Function2[T, T, Bar] with Serializable { ... }

Since T is unknown, the compiler can't make Foo a subclass of Function2 and it can't do much better than make it extend AnyRef:

class Foo[T] extends AnyRef with Product with Serializable { ... }
object Foo extends AnyRef with Serializable { ... }

Here's a quick proof of what discussed above (using 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 {
...

To wrap it up, when you have type parameters, you have to obtain a Function2 first

val f: Function2[Int, Int, Foo] = Foo[Int] _

and then you can call tupled on it

f.tupled // ((Int, Int)) => Foo[Int]
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!