【问题标题】:Scala list of any and list of something extending Any. What is a difference?Scala 的 any 列表和扩展 Any 的东西的列表。有什么区别?
【发布时间】:2021-02-01 15:40:45
【问题描述】:

谁能解释一下: Seq[Any]Seq[_ <: Any] ?
在我看来,我可以将所有内容都放在这两种情况下,因为所有内容都扩展了 Any

【问题讨论】:

  • Any 是糟糕设计的征兆
  • @user 你可以。试试看:val seq1: Seq[_ <: Any] = Seq(1, 2, 3); val seq2 = seq1 :+ "".
  • @cchantep 通常是的,但是对于协变 FF[Any] 与存在类型 F[_] 相同,存在类型不一定是糟糕设计的症状:)
  • @AlexeyRomanov 嗯,这很奇怪。我想我在考虑 Java 的通配符。
  • @user 区别不是因为存在类型与通配符,而是因为:+(和类似的Scala方法)的不同签名和Java中add的变异。

标签: scala generics existential-type


【解决方案1】:

这里没有区别,因为Seq is covariant。所以:

  1. Seq[Any]Seq[_ <: Any] 的子类型,因为_ 可能是Any

  2. Seq[_ <: Any]Seq[Any] 的子类型,因为无论您输入什么而不是 _,您都会得到 Seq[Any] 的子类型。

如果将Seq 替换为一些不变的F(例如Set),Set[Any]Set[_ <: Any] 的子类型,但反之则不然。 Set[_ <: Any]Set[Any]Set[String]Set[Int] 等的通用超类型。

更详细的:

  1. Set[_ <: Any]Set[T] forSome { T <: Any } 的简写。

  2. Set[T] forSome { T <: Any } 是满足T <: Any 的类型T 的所有Set[T] 的超类型。规范says

    存在类型T forSome {Q} 表示的值集是其所有类型实例的值集的并集。

    但那是一回事。

这样的代码

val set1: Set[String] = ??? 
val set2: Set[_ <: Any] = set1

将编译(试试看!)。如果您将String 替换为任何其他类型(_ &lt;: ... 不是类型),它仍然会。但是

val set1: Set[String] = ??? 
val set2: Set[Any] = set1

不会。

【讨论】:

  • 感谢您的回答。让我们考虑java.util.map&lt;K,V&gt;我知道在这种地图的情况下我应该使用:java.util.map&lt;String, _ &lt;: Any&gt;而不是java.util.map&lt;String, Any&gt;
  • 第二个问题:but not vice versa. 为什么?毕竟,一切都扩展(是)scala 是Any
  • “我知道在这种情况下我应该使用这种地图”这很大程度上取决于你想用它做什么。
  • “为什么?毕竟,一切都扩展(是)scala is Any”。因为例如Set[String] 不是 Set[Any] 的子类型。而Set[_ &lt;: Any]Set[Any]Set[String]Set[Int] 等的通用超类型。
  • @tomek.xyz _ &lt;: A, _ &gt;: A 是将不变类型转换为协/逆变的方法:type Foo[A]type CoFoo[+A] = Foo[_ &lt;: A]type ContraFoo[-A] = Foo[_ &gt;: A]。但是Foo 仍然是不变的。
【解决方案2】:

我将在 @AlexeyRomanov 的回答中添加 Scala 规范中特定位置的引用:

3.2.12 存在类型

简化规则

4. 存在类型? forSome { ? } 其中? 包含子句类型?[tps]&gt;:?&lt;:? 等价于类型?′ forSome { ? } 其中?′ 通过替换每个协变量? 产生 在? 中出现? ? 并替换每个 ?? by ? 中的逆变出现。

https://scala-lang.org/files/archive/spec/2.13/03-types.html#simplification-rules

Seq[_ &lt;: Any]Seq[T] forSome { type T &lt;: Any}TSeq[T]中的出现是协变的,因为Seq是协变的,所以Seq[T] forSome { type T &lt;: Any} =:= Seq[Any] forSome { type T &lt;: Any} =:= Seq[Any](最后一步也使用简化规则#2)。

【讨论】:

  • 严格来说这条规则只给你Seq[Any] forSome { type T &lt;: Any }。您还需要包括“可以删除未使用的量化”部分。
猜你喜欢
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 2019-06-07
  • 2015-07-12
  • 2019-11-19
  • 2022-12-03
  • 1970-01-01
  • 2020-05-10
相关资源
最近更新 更多