当泛型类型与无界通配符一起使用时,不考虑类型参数绑定

时间:2019-02-27 17:36:59

标签: scala generics existential-type bounded-wildcard

在我的项目中,我有一个像这样的星座:

trait F

trait X[A <: F]

def test(x: X[_]): X[_ <: F] = x

特质X具有类型参数,其上限为F。据我了解,类型X[_]X[_ <: F]应该等效。但是scalac 2.12.5抱怨一个不能分配给另一个。

$ scalac -Xscript test test.scala 
test.scala:5: error: type mismatch;
 found   : this.X[_$1] where type _$1
 required: this.X[_ <: this.F]
def test(x: X[_]): X[_ <: F] = x
                               ^

我无法想到这种分配会使声音程序不健全的情况。拒绝此分配的原因是什么?有没有办法允许这样的分配(也许在一个更复杂的示例中)有问题?

2 个答案:

答案 0 :(得分:1)

这种分配并不是真正的问题,编译器甚至都知道这一点,因为以下实现可以毫无问题地进行编译:

trait F
trait X[A <: F]
def test(x: X[_]): X[_ <: F] = x match { case q: X[t] => q }

如果通过允许类型检查器推断类型变量t的更精确界限来给类型检查器一些懈怠,它最终会发现t必须是F的子类型,然后允许您返回值q(与x相同)而不会抱怨。默认情况下,for some counter-intuitive reasons不会probably have something to do with Java-wildcard interoperability执行此操作。

(再次删除;我的最初猜测似乎相差不大,并且考虑到Dmytro Mitin的link,相比较而言,它似乎还没有那么模糊。)

答案 1 :(得分:0)

我可能是错的,但是查看函数本身的定义就足够了:

def test(x: X[_]): X[_ <: F] = x

存在类型唯一提供的信息是存在某物。并使用此签名尝试“缩小”功能结果

通过一个实例以实际的方式介绍它。假设您有这样的东西:

def test(x: Option[_]): Option[_ <: String]

,然后将其称为Option[Int]内部传递。您希望这项分配正确吗?

val result: Option[_ <: String] = test(Some(1): Option[_])