推断共同的超类型
Infer common super-type
这是我想要做的
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](_)))
基本上,我想 "flatten" 一个 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))
使用类型边界而不是隐式参数对我有用:
def merge[A <: C, B <: C, C](eithers: Either[A,B]*): Seq[C] =
eithers.flatMap(_.fold(Option[C](_), Option[C](_)))
这是我想要做的
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](_)))
基本上,我想 "flatten" 一个 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))
使用类型边界而不是隐式参数对我有用:
def merge[A <: C, B <: C, C](eithers: Either[A,B]*): Seq[C] =
eithers.flatMap(_.fold(Option[C](_), Option[C](_)))