模式匹配与最终类绑定的类型参数

时间:2017-09-23 14:03:32

标签: scala type-erasure

这是一个例子

def maybeeq[A <: String](x: A):A = x match {
  case z:A => x
}

在编译期间产生了以下错误消息

  

错误:(27,12)scrutinee与模式类型不兼容;   找一个    必需:字符串       case z:A =&gt; X

我可以将任何最终类放入A的绑定中以重现错误。

为什么这会为非最终类编译但在最终版本中失败?为什么键入擦除不只是用String替换A?

编辑:

注意:这样的绑定允许我将String类型的值传递给'x'参数。所以'x'可以只是一个字符串而不必是字符串的子类型,所以我不是要求编译器使用不正确的签名编译方法。在现实世界的代码中,我只是将String放在A参数上,但从实验的角度来看,我很感兴趣为什么需要在现有限制(基于最终类性质)的基础上进行这样的额外限制。

2 个答案:

答案 0 :(得分:4)

TBH这是一个关于编译器设计的问题,只能由实施此类检查的人员来回答

编译器测试套件中有a test requires such error to be shown。它与被丢弃的类型信息有关,其中具体类型无法分配给变量,但是从该测试的git blame无法理解其原因。

但是,我会指出,仍然有很多方法可以满足A <: String,而A在编译时不知道StringNull。例如,Nothingval UhOh: { type T <: String } = new { type T = String } implicitly[UhOh.T <:< String] // satisfies type bound implicitly[UhOh.T =:= String] // won't compile - compiler cannot prove the type equality 满足它,位于Scala类型层次结构的底部。在类型匹配时明确禁止这两个。另一个例子涉及更多:

shapeless.tag

这类似于一些新型模式,例如: A =:= String

在所有这些可能性中,只有一个可以做任何合理的事情是String,因为ClassTag是唯一可以在运行时实际检查的类型。哦,除非你在匹配中使用泛型类型 - 它根本不起作用(至少在范围内没有<?php header('Response.ContentType = "application/vnd.ms-excel"'); header('Content-Disposition: attachement; filename="xlxml.xml"'); echo '<root><name>sample_name</name></root>'; exit(); ?> ),因为这些类型通过擦除来消除。

答案 1 :(得分:1)

最终课程无法扩展。因为def maybeeq[A <: String](x: A)语法不正确,因为Stringfinal,不应该有任何子类型String延伸。编译器巧妙地指出了这个问题。