首页 > 解决方案 > 为什么将 Seq 转换为 Set 然后在同一行上调用 map 无法编译

问题描述

假设我定义了以下代码:

val x: Seq[String] = Seq()
val y = x.toSet.map(s => (s, true))

这不会编译,给我一个缺少参数类型的错误。

但是,如果我这样分解:

val x: Seq[String] = Seq()
val y = x.toSet
val z = y.map(s => (s, true))

它编译得很好。为什么是这样?

标签: scala

解决方案


请注意如何有多种选择适合哪些类型

x.toSet[Any].map[(Any, Boolean]]((s: Any) => (s, true))
x.toSet[AnyRef].map[(AnyRef, Boolean]]((s: AnyRef) => (s, true))
x.toSet[String].map[(String, Boolean]]((s: String) => (s, true))

正如Rex 解释的那样, Scala 2 应该

...选择最具体的值。但是由于函数的参数是逆变的,所以当它们以 anAny作为参数时它们是最具体的,因此编译器无法决定。

例如考虑如何因为参数逆变函数Any => _String => _

implicitly[(Any => _) <:< (String => _)]   // ok

推断Any从来都不是理想的,因此编译器会向程序员寻求明确的帮助。

现在 Scala 3 似乎已经实现了 Rex 的建议

可能存在打破平局的规则(“更喜欢早期假设”),但没有实施。

这使它编译

scala> Seq.empty[String].toSet.map(s => (s, true))
val res0: Set[(String, Boolean)] = Set()

推荐阅读