Scala模式匹配和类型推理



有人能解释一下为什么编译以下代码吗?

Option("foo") match {
  case x: List[String] => println("A")
  case _ => println("B")
}

这给了我一个关于类型擦除的(预期的)警告,但它仍然可以编译。我预计这会引发一个类型错误,就像我在"foo"而不是Option("foo")上匹配一样。

谢谢!

代码有注释,所以让我们花点时间来品味一下:

  /** If we can absolutely rule out a match we can fail early.
   *  This is the case if the scrutinee has no unresolved type arguments
   *  and is a "final type", meaning final + invariant in all type parameters.
   */

例如,请注意"无"不是最终结果。我知道,对吧?

如果您曾经尝试过scalac-Ypatmat调试,这里的注释可能会有所帮助:

https://github.com/scala/scala/pull/650

可达性几乎触手可及:

https://issues.scala-lang.org/browse/SI-6146

但我看不到任何关于有一天可能会引起战争的承诺。出于性能原因?人们也可以说,为什么它要警告[Foo[_]]的实例?

目前,规范第8.2-8.4节解释了为什么与Foo[a]匹配很有趣(因为a获得了边界)。我想我会再读一遍。喝了咖啡之后。

trait Foo[+A]
final class Fuzz[+A] extends Foo[A]
final object Fooz extends Foo[Nothing]
object Futz extends Foo[Nothing]
//error
Fooz match {
  case x: List[_] => println("A")
  case _ => println("B")
}
//no error
Futz match { ... }

我假设编译器将OptionList都视为Product,这就是它进行编译的原因。正如您所说,关于类型擦除的警告是意料之中的事。下面是一个使用另一种产品的例子:

scala> Option("foo") match {
 | case x: Tuple2[String,String] => println("TUPLE")
 | case x: List[String] => println("LIST")
 | case _ => println("OTHER")
 | }
<console>:9: warning: non variable type-argument String in type pattern (String, String)       is unchecked since it is eliminated by erasure
          case x: Tuple2[String,String] => println("TUPLE")
                  ^
<console>:10: warning: non variable type-argument String in type pattern List[String] is unchecked since it is eliminated by erasure
          case x: List[String] => println("LIST")
                  ^

更新w/r/t案例类(因为下面的注释):

scala> case class Foo(bar: Int)
defined class Foo
scala> val y: Product = Foo(123)
y: Product = Foo(123)

我注意到,当您匹配的值的类被声明为final时,会显示一个错误(我们知道String是final)。我仍然不知道为什么没有它就没有错误。

最新更新