Улучшенная проверка типов при совпадении в Scala

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

Разве в приведенном выше примере компилятор не должен сказать мне, что один из случаев никогда не может совпадать? Недавно меня привлек немного более сложный пример, который привел к ненужной ошибке, которую должен был обнаружить компилятор.

Изменить:

Просто чтобы было понятнее вопрос. Это невозможно в Scala по какой-то причине, которую я не вижу? (Я могу понять, если типы использовали дженерики, а стирание типов вызывало проблемы, но это выглядит довольно прямолинейно.) И если это не невозможно, есть ли законные причины, по которым этого нет в Scala? Если нет, то когда он будет добавлен? ;)


person David    schedule 02.08.2010    source источник


Ответы (3)


В настоящее время проверка полноты и избыточности выполняется только для шаблонов конструктора case-класса. В принципе, компилятор может сделать это и для некоторых других типов шаблонов. Но в SLS должно быть указано, какие именно тесты проводятся. Это выглядит выполнимым, но нетривиальным, учитывая взаимодействие между различными классами шаблонов. Таким образом, это одна из областей Scala, которая выиграет от дальнейших разработок.

person Martin Odersky    schedule 02.08.2010
comment
Удивительно ! Иду свой ответ от того, кто научил меня скале и тоже ее изобрел! Спасибо, переполнение стека! - person Kami; 04.08.2010

Компилятор предупреждает вас (на самом деле компиляция завершается ошибкой), если вы используете case-классы:

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")
person michid    schedule 02.08.2010
comment
К сожалению, кейс-классы имеют некоторые ограничения и не всегда подходят. Я не понимаю, почему компилятор не может понять это и для обычных классов. - person David; 02.08.2010

Проверил в 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
person Saurav Sahu    schedule 13.02.2021