类型参数限制为 final class 的模式匹配
Pattern matching with type parameter bounded to final class
这是一个例子
def maybeeq[A <: String](x: A):A = x match {
case z:A => x
}
编译时出现如下错误信息
Error:(27, 12) scrutinee is incompatible with pattern type;
found : A
required: String
case z:A => x
我可以将任何最终 class 放入 A 的绑定中以重现错误。
为什么这对非最终 classes 编译但对最终失败?为什么类型擦除不只是将 A 替换为 String?
已编辑:
注意:这样的绑定允许我将字符串类型的值传递给 'x' 参数。所以 'x' 可以只是一个字符串,不必是字符串的子类型,所以我不要求编译器编译带有不正确签名的方法。在现实世界的代码中,我只是将 String 放在 A 参数上,但从实验的角度来看,我很感兴趣为什么需要在现有限制之上进行这种额外限制(基于最终 class 性质)。
Final class 不能是 extended.so 因为 def maybeeq[A <: String](x: A)
不是正确的语法,因为 String
是 final
,不应有任何 子类型 从 String
扩展。编译器巧妙地指出了这个问题。
TBH 这是一个关于编译器设计的问题,只能由实施此类检查的人回答
有a test in compiler test suite that requires such error to be shown。它与类型信息被丢弃到无法将具体类型分配给变量的程度有关,但从该测试的 git blame
无法理解其原因。
不过,我要指出的是,仍然有许多方法可以满足 A <: String
而不会在编译时将 A
已知为 String
。一方面,Null
和 Nothing
满足这一点,处于 Scala 类型层次结构的底部。这两个在类型匹配时被明确禁止。另一个例子有点复杂:
val 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
这类似于一些新的打字模式,例如shapeless.tag
在所有这些可能性中,只有当 A =:= String
时可以做任何合理的事情,因为 String
是唯一可以在运行时实际检查的类型。哦,除非你在匹配中使用泛型类型——那根本不起作用(至少在范围内没有 ClassTag
),因为这些类型被擦除消除了。
这是一个例子
def maybeeq[A <: String](x: A):A = x match {
case z:A => x
}
编译时出现如下错误信息
Error:(27, 12) scrutinee is incompatible with pattern type; found : A required: String case z:A => x
我可以将任何最终 class 放入 A 的绑定中以重现错误。
为什么这对非最终 classes 编译但对最终失败?为什么类型擦除不只是将 A 替换为 String?
已编辑:
注意:这样的绑定允许我将字符串类型的值传递给 'x' 参数。所以 'x' 可以只是一个字符串,不必是字符串的子类型,所以我不要求编译器编译带有不正确签名的方法。在现实世界的代码中,我只是将 String 放在 A 参数上,但从实验的角度来看,我很感兴趣为什么需要在现有限制之上进行这种额外限制(基于最终 class 性质)。
Final class 不能是 extended.so 因为 def maybeeq[A <: String](x: A)
不是正确的语法,因为 String
是 final
,不应有任何 子类型 从 String
扩展。编译器巧妙地指出了这个问题。
TBH 这是一个关于编译器设计的问题,只能由实施此类检查的人回答
有a test in compiler test suite that requires such error to be shown。它与类型信息被丢弃到无法将具体类型分配给变量的程度有关,但从该测试的 git blame
无法理解其原因。
不过,我要指出的是,仍然有许多方法可以满足 A <: String
而不会在编译时将 A
已知为 String
。一方面,Null
和 Nothing
满足这一点,处于 Scala 类型层次结构的底部。这两个在类型匹配时被明确禁止。另一个例子有点复杂:
val 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
这类似于一些新的打字模式,例如shapeless.tag
在所有这些可能性中,只有当 A =:= String
时可以做任何合理的事情,因为 String
是唯一可以在运行时实际检查的类型。哦,除非你在匹配中使用泛型类型——那根本不起作用(至少在范围内没有 ClassTag
),因为这些类型被擦除消除了。