这是我想要做的

  def merge[A, B, C](eithers: Either[A,B]*)(implicit ev1: A <:< C, ev2: B <:< C): Seq[C] =
     eithers.flatMap(_.fold(Option[C](_), Option[C](_)))


基本上,我想将Either[A,B]的列表“平化”为Seq[C],其中C是A和B(显然是Any以外)的常见超类型。

例如:

  trait Foo
  class Bar extends Foo
  class Baz extends Foo

  merge(Left[Bar, Baz](new Bar), Right[Bar, Baz](new Baz))


这不起作用:(
它说Cannot prove that Baz <:< C

但是,这确实有效:

  merge[Bar, Baz, Foo](Left[Bar, Baz](new Bar), Right[Bar, Baz](new Baz))
  res7: Seq[Foo] = ArrayBuffer(Bar@613f7eb7, Baz@565aa4ac)


因此,问题是有人可以用某种技巧来推断出普通的超级类型,这样我就不必这样拼写出来了吗?
或者,至少,一种仅使用一个类型参数来执行此操作的方法(我不必介意指定结果的类型,因为我必须拼出输入数据的类型)。

我知道的一种方法是将其分配给变量:

val merged: Seq[Foo] = merge(Left[Bar, Baz](new Bar), Right[Bar, Baz](new Baz))


这行得通,但对我来说还不算什么,因为我讨厌声明仅使用一次的变量。理想情况下,我希望这样做:

merge(input)
  .filter(doILikeIt)
  .map(doSomethingInteresting)
// etc.


有任何想法吗?

最佳答案

有一个简单的解决方案,使用方差:

def merge[C](eithers: Either[C, C]*): Seq[C] = eithers.map(_.fold(x => x, x => x))

关于scala - 推断普通父类(super class)型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42981897/

10-12 19:22