【发布时间】:2021-03-07 21:13:21
【问题描述】:
这很好用:
def echo[A, B](a: A, b: B): A = ???
这样也好:
def echo[A, B](a: A, b: B): B = ???
但是,我们如何实现这一点以返回类型 A 或 B?
// error def echo[A, B](a: A, b: B): A|B = ???
是否有可能拥有通用类型A和B的联合类型? 干杯。
更新1
Either 是一个选项,但并不理想,因为它在处理返回的结果时需要模式匹配。实际上,我想要这个:A <: A|B,B <: A|B,Either 没有实现。
另一个极端,我可以这样做,但是类型太松了:
def echo[A, B](a: A, b: B): Any = ???
更新2
为什么我不想要Either?
(原因 2)
返回的结果实际上是 Spark 的 Dataset,对于不是 Product 子类型的任何类型都需要 Encoder(参见 this topic)。
多次调用此方法时,会导致太多Either相互包裹,例如Either[Either[Either[...]]]。这需要定义太多的编码器。
所以我实际上是这样做的:
def echo[A, B](a: A, b: B): Dataset[A|B] = ???
如果我这样做,由于Either 类型,它需要有许多不同的编码器:
def echo[A, B](a: A, b: B): Dataset[Either[A, B]] = ???
val result1: Either[Cat, Dog] = echo(a: Cat, b: Dog)
val result2: Either[Either[Cat, Dog], Pig] = echo(result1: Either[Cat, Dog], c: Pig)
// we have to define encoders:
implicit encoder1: org.apache.spark.sql.Encoders.kryo[Either[Cat, Dog]]
implicit encoder2: org.apache.spark.sql.Encoders.kryo[Either[Either[Cat, Dog], Pig]]
// if we keep iterating, then too many encoders to define...
【问题讨论】:
-
嗯,有Either
-
听起来像 C++ 的函数专业化在这里会很方便
-
@smac89 谢谢你,很高兴知道。但似乎
@specialized只适用于特定类型,这意味着它不能做def echo[@specialized(A,B) AB](a: A, b: B, ab: AB) = ???(其中A和B是泛型类型)。其次,它似乎无法返回@specialized类型,例如def echo[A, B](a: A, b: B): @specialized(A,B) = ???两个错误! -
@Dima 谢谢!
Either还不错,但是在处理返回的结果时需要进行模式匹配。实际上,我想要这个:A <: A|B,B <: A|B,Either没有实现。 -
联合类型也需要模式匹配。
标签: scala apache-spark generics union-types apache-spark-encoders