子类型导致编译器中的Any:Bug或我的代码出现问题



让我直接谈谈我在处理类型边界时遇到的问题
让我们考虑以下内容。。。我创建了一个类似的函数"foo">

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

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

foo("Mars",2400)

我得到了类似的结果

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

注意火星和2400的推断类型
现在,我想强制函数"foo"接受Integers、float或Doubles(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库2.11.8
感谢

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

在上面的例子中,您将类型参数A声明为类型参数B的子类型。当您将A传递为String,将B传递为Int时,编译器会向上遍历类层次结构,为B找到合适的类型,这样Int是BString也是B

您可以考虑使用具有推断类型的原始声明,如"查找AB,使x具有类型Ay具有类型B,并且AB的子类型"。由于Any0和B = Any满足这些条件,编译器正确地推断出它们(也有其他解决方案,例如A = B = Any,但这一个是最具体的(。

但是,您可以更改声明,告诉编译器"找到AB,使x具有类型Ay具有类型B,然后检查AB的子类型"。具体操作如下:

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

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

最新更新