【问题标题】:Weird behavior of & function in SetSet 中 & 函数的奇怪行为
【发布时间】:2013-08-03 05:45:21
【问题描述】:

Set 定义为Set[A]。它需要一个 in-variant 参数。当我们传递协变参数时,按照预期执行以下操作:

scala> val a = Set(new Object)
a: scala.collection.immutable.Set[Object] = Set(java.lang.Object@118c38f)

scala> val b = Set("hi")
b: scala.collection.immutable.Set[String] = Set(hi)

scala> a & b
<console>:10: error: type mismatch;
 found   : scala.collection.immutable.Set[String]
 required: scala.collection.GenSet[Object]
Note: String <: Object, but trait GenSet is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: Object`. (SLS 3.2.10)
              a & b

但以下工作:

scala> Set(new Object) & Set("hi")
res1: scala.collection.immutable.Set[Object] = Set()

如我所见,scala 编译器将Set("hi") 转换为Set[Object] 类型并因此工作。

类型推断在这里做什么?有人可以链接到说明该行为的规范以及它通常何时发生吗?对于这种情况,它不应该引发编译时错误吗?作为相同操作类型的 2 个不同输出。

【问题讨论】:

    标签: scala generics


    【解决方案1】:

    不确定,但我认为您要查找的内容在“本地类型推断”下的 the language spec 中进行了描述(在撰写本文时,第 100 页的第 6.26.4 节)。

    本地类型推断推断要传递给多态类型表达式的类型参数。说 e 的类型是 [ a1 >: L1<: u>1, .. ., an >: Ln <: u>n ] T 并且没有显式类型 给定参数。

    本地类型推断将此表达式转换为类型应用程序e [ T1, ..., Tn ]。类型参数 T1, ..., Tn 的选择取决于表达式出现的上下文和预期的类型pt。三种情况。

    [...]

    如果表达式 e 以值的形式出现而没有应用于值参数,则类型参数是通过求解将表达式的类型 T 与预期类型 pt。不失一般性,我们可以假设 T 是一个值类型;如果它是一种方法类型,我们应用 eta-expansion 将其转换为函数类型。求解意味着找到类型参数 ai 的类型 Ti 的替换 σ > 这样

    • 所有推断类型 Ti 都不是单例类型

    • 遵守所有类型参数界限,即 σ Li<: a>iσ ai <: u>i for i = 1, ..., n.

    • 表达式的类型符合预期的类型,即σ T <: pt>。

    如果不存在这样的替换,则会出现编译时错误。如果存在多个替换,局部类型推断将为每个类型变量 ai 选择最小或最大类型 Ti em> 的解决方案空间。如果类型参数 ai 以逆变方式出现在类型 中,则将选择最大类型 Ti表达式的 T。在所有其他情况下,将选择最小类型 Ti,即如果变量在类型 T 中出现协变、非变或根本不出现.我们称这种替换为类型 T 的给定约束系统的最优解。

    简而言之:Scalac 必须为您省略的泛型类型选择值,并在结果编译的约束下选择最具体的选择。

    【讨论】:

    • 由于指定的链接而接受答案:在提到的示例中解释得很好。
    【解决方案2】:

    表达式Set("hi") 可以是scala.collection.immutable.Set[String]scala.collection.immutable.Set[Object],具体取决于上下文的要求。 (当然,String 是有效的Object。)当你写这个时:

    Set(new Object) & Set("hi")
    

    上下文需要Set[Object],所以这是推断的类型;但是当你写这个时:

    val b = Set("hi")
    

    上下文未指定,因此选择了更具体的类型 Set[String],这(如您所料)然后使 a &amp; b 类型错误。

    【讨论】:

    • 是的。正如我在问题中解释的那样,我理解这种行为。但我想知道它是在什么时候、在什么情况下这样做的?
    • 我已经编辑了这个问题,让自己更清楚。之前的道歉。
    • @Jatin:哦,我明白了。让我失望的是您使用“转换”一词:我以为您是在说一种情况允许将Set[String] 转换为Set[Object],而另一种情况则不允许;而实际的区别在于,一种情况涉及Set[String],而另一种情况则没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 2011-06-14
    • 2020-01-31
    相关资源
    最近更新 更多