[英]Scala higher-kinded existential type
我具有以下层次结构,我想定义任何Description
的列表,但无法确定其参数类型。
abstract class Context
class Local extends Context
class Browsing extends Context
abstract class Fruit[C <: Context]
class Apple[C <: Context](id: Int) extends Fruit[C]
class Banana[C <: Context](id: Int) extends Fruit[C]
abstract class Description[U[X <: Context] <: Fruit[X]] // U can't be covariant
class Apples extends Description[Apple]
class Bananas extends Description[Banana]
基本上,我想要这样的东西(它不能按原样编译):
val l: List[Description[_]] = List(
new Apples,
new Bananas
)
有什么办法可以做到这一点?
您需要做的是:
abstract class Description[+U[X <: Context] <: Fruit[X]]
然后它将起作用:
scala> List(new Apples, new Bananas)
res40: List[Description[Fruit]] = List(Apples@6a808ae5, Bananas@4f4d77e8)
您的案例失败的原因是:当您执行List(new Apples, new Bananas)
,因为编译器会尝试查找Apples
和Banana
的最小上限(LUB)。 即LUB用于Description[Apple]
和Description[Banana]
。 因此,您需要的是Description[_ >: Banana with Apple <: Fruit]
。
正如编译器错误正确地指出的那样: Apple <: Fruit
(当然还有Apple>:Banana with Apple)。 但是,如果Description
在其type参数中是协变的,则Description[Apple]
将仅是Description[_ >: Banana with Apple <: Fruit]
的子类型。
PS:协方差使我们具有以下能力:如果A <: B
,然后对于M[+T]
,则M[A] <: M[B]
。
对于逆方差M[-T]
, M[A] >: M[B]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.