【问题标题】:Returning immutable.Map with covariant type返回具有协变类型的 immutable.Map
【发布时间】:2013-02-06 03:54:59
【问题描述】:

我有一个容器类型,它的类型参数是协变的。

  class Container[+T](val map: Map[Int, T] = Map.empty[Int, T]){
    def add[B >: T](i: Int, b: B) = new Container(map + (i->b))
//    lazy val freqs = (map.toList groupBy (x=>x._2) mapValues(_.size))
//    lazy val uniq = map.toSet
      lazy val keySet = map.keySet
  }

我在想我在尝试使用 freqs 或 uniq uncommented 进行编译时出错的原因与 Spiewak 先生在他的回答中所写的内容有关,Sets 和 Maps 在相关参数中是不变的.

Why is Scala's immutable Set not covariant in its type?

但是我有点惊讶地发现包含 keySet 没有问题,它返回一个类型为 T 的Set

我可以通过写作部分解决这个问题

lazy val freqs:Map[_ <: Any, Int] = 
  (map.toList groupBy (x=>x._2) mapValues(_.size))

但这并不理想,因为键类型显示为 Any。我也想说

lazy val uniqueValues = freqs.keySet

并获得Set[T] 而不是Set[Any]

  • 我怎样才能最好地实现上述freqs
  • keySet 如何在其他方法失败时返回 Set[T]?
  • 如何在 Map 中获取 Set[T] 的唯一值?
  • 为什么 _ <: any>

谢谢!

【问题讨论】:

  • 看起来Map 是落后的。知道频率都是不同的吗?
  • 这里提到了两张地图,都没有落后。第一个 Map 是 Container 参数,一个 Map[Int, T]:每个 Int 是一个 T 的别名。第二个映射是 freqs 的返回类型, Map[T, Int] 是别名数量的计数对于每个 T。

标签: scala collections types covariance


【解决方案1】:

但是我有点惊讶地发现包含 keySet 并返回一个类型为 T 的 Set 没有问题

不,它没有。 mapMap[Int, T] 类型,因此虽然它的 T 类型,但它的 Int 类型。所以这里的keySetSet[Int] 类型(并且不是 Set[T]),这意味着T 的协方差没有问题。

其他方法失败时keySet如何返回Set[T]?

它没有(见上文)

如何在 Map 中获得一组唯一值的 Set[T]?

鉴于Set 在其类型参数中是不变的,根本无法在Container 中包含任何Set[T] 类型的值,除非将这些值标记为private[this],或使Container 不变在T

我怎样才能最好地实现上述频率?

和上面一样的问题。

为什么 _ <: any>

因为当明确声明 freqMap[_ &lt;: Any, Int] 类型时,您删除了对 T 的任何依赖,因此就方差而言没有问题。如果您没有明确说明 freq 的类型,scala(正确地)将类型推断为 Map[T, Int],这确实取决于 T 在一个不变的位置。

【讨论】:

  • 感谢您的建议,但添加 private[this] 似乎没有帮助。 class Container[+T](val map: Map[Int, T] = Map.empty[Int, T]){ def add[B &gt;: T](i: Int, b: B) = new Container(map + (i-&gt;b)); private[this] lazy val freqs = (map.toList groupBy (x=&gt;x._2) mapValues(_.size)) }
  • 您使用的是哪个版本的 scala,您可以尝试使用更新的版本吗?
  • 我检查了它,确实它在 scala 2.10 中有效,但在 scala 2.9 中无效。显然在 scala 2.9 中,T 类型的 private[this] val 可以工作,但是如果您将类型更改为在 T 中不变的类(而不是简单地 being T)例如Set[T],它不再起作用了。对我来说,这看起来像是 scala 2.9 的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
相关资源
最近更新 更多