【问题标题】:Union generic type without Either Scala没有 Scala 的联合泛型类型
【发布时间】: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 = ???

是否有可能拥有通用类型AB联合类型? 干杯。


更新1

Either 是一个选项,但并不理想,因为它在处理返回的结果时需要模式匹配。实际上,我想要这个:A <: A|BB <: A|BEither 没有实现。

另一个极端,我可以这样做,但是类型太松了:

def echo[A, B](a: A, b: B): Any = ???

更新2
为什么我不想要Either

(原因 2)

返回的结果实际上是 SparkDataset,对于不是 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) = ???(其中AB 是泛型类型)。其次,它似乎无法返回 @specialized 类型,例如def echo[A, B](a: A, b: B): @specialized(A,B) = ??? 两个错误!
  • @Dima 谢谢! Either 还不错,但是在处理返回的结果时需要进行模式匹配。实际上,我想要这个:A <: A|BB <: A|BEither 没有实现。
  • 联合类型也需要模式匹配。

标签: scala apache-spark generics union-types apache-spark-encoders


【解决方案1】:

即将发布的 Scala 3 拥有它。

def echo[A, B](a: A, b: B): A|B = ???  //this compiles

可以在this Scastie session中看到。

【讨论】:

  • 感谢您与我们联系。在 Scala 2.11 中仍然无法编译,有没有办法实现这个?
猜你喜欢
  • 1970-01-01
  • 2015-07-09
  • 2020-03-27
  • 1970-01-01
  • 1970-01-01
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多