0

让我直接讨论我在使用类型边界时遇到的问题。
让我们考虑以下内容......我创建了一个这样的函数'foo'

def foo[A,B](x:A,y:B):(A,B)=(x,y)

我在 scala 工作表中调用了 foo ,比如

foo("Mars",2400)

我得到了类似的结果

res0: (String, Int) = (Mars,2400)

注意 Mars 和 2400 的推断类型
现在我想强制函数 'foo' 接受整数或浮点数或双精度数(任何类型是 AnyVal 的子类型)。

为了强制执行,我编写了类似的代码

def fooNew[A<:B,B](x:A,y:B):(A,B)=(x,y)

从前面的代码中推断出的类型是 (String,Int) 并且当我调用 fooNew 时

fooNew("Saturn",2400)

我很惊讶地看到编译器确实让我的代码通过并且没有引发错误,而是给出了类似的输出

res0: (String, Any) = (Saturn,2400)

现在,所需的执行方式在这里不起作用。如果我做了这样的事情

def fooNew[A<:B,B<:AnyVal](x:A,y:B):(A,B)=(x,y)

编译器肯定会为我引发错误,而且确实如此!

Error:(2, 2) inferred type arguments [String,Any] do not conform to method fooNew's type parameter bounds [A <: B,B <: AnyVal]
fooNew("Saturn",2400);}

我想问,为什么编译器没有将类型设为 Int 而是推断出类型 Any 并让我的代码通过类型检查?
我是否总是需要将第二种类型强制为AnyVal的子类型,而不是让编译器为我推断它?或者它是编译器中的错误。
如果您发现我的问题具有误导性或不符合您的期望,请寻求原谅。
目前我正在使用 scala-library 2.11.8
谢谢

4

2 回答 2

3
def fooNew[A<:B,B](x:A,y:B):(A,B)=(x,y)

在上面,您将类型参数 A 声明为类型参数 B 的子类型。当您将 A 作为 String 传递并将 B 作为 Int 传递时,编译器会向上类层次结构查找适合 B 的类型,使得Int 是 B并且String 也是 B 的子类型。满足这两个条件的层次结构中唯一的类型是Any类型。因此,String 是 Any 的子类型,而 Int 是 Any 类型

于 2016-08-31T07:59:04.663 回答
2

您可以考虑将原始声明与推断类型一起使用为“find Aand Bsuch that xhas type A, yhas type B, and Ais a subtype of B”。由于A = StringB = Any满足这些条件,编译器会正确推断它们(还有其他解决方案,例如A = B = Any,但这个是最具体的)。

但是您可以更改声明以告诉编译器“找到具有类型AB具有类型的和,然后检查它是”的子类型。这是按如下方式完成的:xAyBAB

def fooNew[A,B](x:A,y:B)(implicit evidence: A <:< B): (A,B)=(x,y)

这是有效的,因为编译器将只使用第一个参数列表来推断AB。搜索“广义类型约束”以查找有关<:<和的更多信息=:=

于 2016-08-31T08:24:56.530 回答