scala - 子类型中的压倒性差异

标签 scala higher-kinded-types

有人可以向我解释为什么示例 1 可以编译但示例 2 没有吗?

示例 1:

trait Foo[+A]
trait Bar[A] extends Foo[A]

示例 2:
trait Foo[A[+_]]
trait Bar[A[_]] extends Foo[A]

示例 2 无法编译并出现以下错误消息:“类型参数 (A) 的种类不符合 trait Foo 中类型参数 (类型 A) 的预期类型。A 的类型参数与类型 A 的预期参数不匹配:输入
trait Bar) 是不变的,但类型 _ (在 trait Foo 中) 被声明为协变”

最佳答案

在示例 1 中, +A不受 A 的约束.任何类型都可以是 Foo 的参数。它是对 Foo 的约束。 .表示在Foo的界面中, A只能出现在协变位置(简而言之,它可能是方法结果,但不是方法参数)。

Bar not covariant 表示 Bar 的接口(interface)不满足相同的约束(或者至少不做广告),所以可能在 Bar , 一个带有 A 的方法添加了参数。这很常见。例如有 collection.Seq[+A] , 并由 collection.mutable.Seq[A] 扩展.这不会造成不健全的问题。如果 Y <: X , 一个 Bar[Y]不是 Bar[X] , 但它仍然是 Foo[X] .

另一方面,在示例 2 中, A[+_]是对 A 的约束 .只有具有协变类型参数的类型才可以是 Foo 的参数。 Foo的代码可能会利用该约束,例如分配 A[String]A[Any] Foo 的代码中的某处.

然后允许 Bar用非协变类型实例化是不合理的。继承自 Foo 的代码仍然可以调用并分配 A[String]A[Any] , 当 A不再是协变的。

只要您允许解除对通用参数的约束,就会发生非常相似的可靠性问题。假设您有 Foo[X <: Ordered[X]] (或 Foo[X : ordering] )并且您有一个方法 sortFoo .那么假设Bar[X] extends Foo被允许。 Bar 的代码中可能没有任何内容需要 X订购,但仍然,sort将是可调用的,并且肯定会与无法订购的项目行为不端。

关于您在 Traversable[+Ele​​m, +Col[+_]] 的评论中的问题,并将其扩展为创建一个可变类:

从技术上讲,是的,您可以扩展它并添加一些 var youCanMutateThat : Elem = _里面。我想这不是你要找的。但我想你的计划是允许使用带有可变 Col 的扩展,我认为你不能这样做,原因如上所述。但是,为什么你首先有 Col[+_] 约束?

关于scala - 子类型中的压倒性差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22533184/

相关文章:

scala - 从另一个 RDD 中减去一个 RDD 无法正常工作

Scalalogging 不能在 sbt playproject 中使用,并记录到 stdout

java - 引用 Java Enum 作为 Scala 中的类型参数

scala - 高级类型参数中下划线的使用规则

c# - C# 4.0 中泛型类型参数的变体是否更接近更高种类的类型?

scala - 查看更高级类型的边界

scala - 如何定义与更高种类类型绑定(bind)的上下文(类型构造函数)

python - python 类型注释中的链式引用

Scala 宏 : Define Top Level Object

string - toString.map 和 toString.toArray.map 的性能差异