更好地检查Scala中的匹配

时间:2010-08-02 13:22:45

标签: compiler-construction scala pattern-matching typechecking

scala> class A
defined class A

scala> class B
defined class B

scala> val a: A = new A
a: A = A@551510e8

scala> a match {
     | case _: B => println("unlikely")
     | case _ => println("no match")
     | }
no match

在上面的例子中,编译器不应该告诉我其中一个案例永远不能匹配?一个稍微复杂的例子最近引起了我的注意,导致了一个应该被编译器捕获的不必要的bug。

修改

只是为了更清楚这个问题。由于某种原因,我无法看到Scala中这是不可能的吗? (我可以理解这些类型是否使用泛型和类型擦除导致问题,但这看起来非常直接。)如果这不是不可能的,是否有正当理由这不是Scala?如果不是什么时候加入? ;)

3 个答案:

答案 0 :(得分:22)

目前,详尽无遗和冗余检查仅针对案例类构造函数模式进行。原则上,编译器也可以为其他类型的模式执行此操作。但是必须在SLS中明确指出要进行的测试。考虑到不同模式类之间的相互作用,这看起来可行但非平凡。因此,总而言之,这是Scala中可以从进一步贡献中获益的领域之一。

答案 1 :(得分:4)

如果您使用案例类,编译器会发出警告(事实上编译失败):

scala> case class A()
defined class A

scala> case class B()
defined class B

scala> val a = A()
a: A = A()

scala> a match {
     | case A() => println("A")
     | case B() => println("B")
     | case _ => println("_")
     | }
<console>:13: error: constructor cannot be instantiated to expected type;
 found   : B
 required: A
       case B() => println("B")

答案 2 :(得分:1)

我检查了 Scala 2.13.3,我们收到了 fruitless type test 的警告:

scala> a match {
     | case _:B => println("B")
     | case _ => println("no match")
     | }
       case _:B => println("B")
              ^
On line 2: warning: fruitless type test: a value of type A cannot also be a B
no match