奇怪的行为&函数在Set中 [英] Weird behavior of & function in Set

查看:82
本文介绍了奇怪的行为&函数在Set中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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>一个& b
< console>:10:error:type mismatch;
found:scala.collection.immutable.Set [String]
required:scala.collection.GenSet [Object]
注意:String<:Object,但特征GenSet在类型A中不变。
您可能希望调查通配符类型,例如`_<:Object`。 (SLS 3.2.10)
a& b

但下面的工作:

 阶>设置(新对象)& Set(hi)
res1:scala.collection.immutable.Set [Object] = Set()

在我看来,scala编译器将 Set(hi)转换为 Set [Object] 类型,因此工作。



在这里做什么类型推断?有人可以链接到解释行为的规范,什么时候发生?它不应该为这种情况抛出编译时错误吗?作为相同操作类型的2个不同输出。

解决方案

不确定,但我认为您要查找的是Local Type Inference下的语言规范(在撰写本文时,


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



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

[...]



如果表达式 e 显示为一个值,但不应用于值参数,类型参数通过解决将表达式的类型 T 与预期类型 pt 关联的约束系统来推断。不失一般性,我们可以假设 T 是一个值类型;如果它是一种方法类型,我们应用eta-expansion将其转换为函数类型。求解意味着为类型参数 a i 定义类型 T i 的替换 em>




  • 没有推断的类型 T i 一个单例类型


  • 所有类型的参数边界都受到尊重,即σ L <:sigma;一个 σ 对于 i = 1,...,n

  • 的$ 表达式的类型符合预期的类型,即σ T<:σ如果没有这样的替换存在,那么这是一个编译时错误。 如果存在多个替换,则局部类型推断将为每个类型变量选择一个最小或最大类型的变量 T i 解决方案空间。如果类型参数 a i 在类型中矛盾地出现,则会选择最大类型 T i 表达式的T 。在所有其他情况下,即如果变量共变地,不变地或者根本不在类型 T 中选择最小类型 T i 。我们称这种替代为给定的约束系统的最佳解决方案。


总之:Scalac必须为您省略的泛型类型选择值,并在结果编译的约束条件下挑选最具体的选项。


Set is defined as Set[A]. It takes a in-variant parameter. Doing below works as expected as we are passing co-variant argument:

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

But the below works:

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

Above as I see it, the scala compiler converts Set("hi") to Set[Object] type and hence works.

What is the type-inference doing here? Can someone please link to specification explaining the behavior and when does it happen in general? Shouldn't it be throwing a compile time error for such cases? As 2 different output for the same operation type.

解决方案

Not sure, but I think what you're looking for is described in the language spec under "Local Type Inference" (at this time of writing, section 6.26.4 on page 100).

Local type inference infers type arguments to be passed to expressions of polymorphic type. Say e is of type [ a1 >: L1 <: U1, ..., an >: Ln <: Un ] T and no explicit type parameters are given.

Local type inference converts this expression to a type application e [ T1, ..., Tn ]. The choice of the type arguments T1, ..., Tn depends on the context in which the expression appears and on the expected type pt. There are three cases.

[ ... ]

If the expression e appears as a value without being applied to value arguments, the type arguments are inferred by solving a constraint system which relates the expression's type T with the expected type pt. Without loss of generality we can assume that T is a value type; if it is a method type we apply eta-expansion to convert it to a function type. Solving means finding a substitution σ of types Ti for the type parameters ai such that

  • None of inferred types Ti is a singleton type

  • All type parameter bounds are respected, i.e. σ Li <: σ ai and σ ai <: σ Ui for i = 1, ..., n.

  • The expression's type conforms to the expected type, i.e. σ T <: σ pt.

It is a compile time error if no such substitution exists. If several substitutions exist, local-type inference will choose for each type variable ai a minimal or maximal type Ti of the solution space. A maximal type Ti will be chosen if the type parameter ai appears contravariantly in the type T of the expression. A minimal type Ti will be chosen in all other situations, i.e. if the variable appears covariantly, nonvariantly or not at all in the type T. We call such a substitution an optimal solution of the given constraint system for the type T.

In short: Scalac has to choose values for the generic types that you omitted, and it picks the most specific choices possible, under the constraint that the result compiles.

这篇关于奇怪的行为&amp;函数在Set中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆