Как систематически избегать небезопасного соответствия шаблонов в Scala?

Рассмотрим следующую ломаную функцию:

def sum (list : Seq[Int]) : Int = list match {
  case Nil => 0
  case head :: tail => head + sum(tail)
}

Здесь функция должна была работать с List[Int], но была реорганизована для принятия Seq[Int] вместо этого, таким образом, она была нарушена без уведомления компилятора.

Это зазорное отверстие в обнаружении совпадения неполного шаблона Scala делает его рядом с бесполезным.

Я хочу иметь способ систематического обнаружения таких проблем. В частности, я хотел бы, чтобы компилятор выдавал ошибку/предупреждение для каждого сопоставленного шаблона instanceof, т.е. Я хотел только разрешить совпадения шаблонов в запечатанных иерархиях и на пользовательских сопоставлениях.

Существуют ли существующие параметры/плагины компилятора для выполнения консервативных (в отличие от произвольных) проверок безопасности соответствия шаблонов?

Ответ 1

Посмотрите этот ответ М. Одерского.

Резюме

Проверки совпадений непечатанных иерархий выполняются, но не тривиальны и не реализованы (пока).

Ответ 2

Nil и :: - это четкие способы построения List, но не все Seq uences бывают Lists, поэтому можно было бы ожидать, что тег Scala отклонит эту программу как больную -typed. Правильно?

Неправильно. Попробуйте это, и вы увидите, что я имею в виду:

def sum (list : Seq[Int]) : Int = list match {
  case Nil => 0
  case head :: tail => head + sum(tail)
  case _ => -1
}

> sum(Array(1,2,3).toSeq)
res1: Int = -1
> sum(List(1,2,3))
res2: Int = 6

Итак, вы видите, что некоторые Seq могут быть деконструированы с помощью Nil и ::, поэтому те, которые могут, будут. Те, которые не могут, не смогут совместить шаблон и двигаться дальше, пробовав следующий матч. Nil и :: достаточно, чтобы охватить все возможности для List, но не для Seq. Здесь существует компромисс между подтипированием, удобством и безопасностью типа. Решение на данный момент: будьте осторожны при рефакторе.