这是我想要做的
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/