Этот шаблон кажется исчерпывающим, но я все еще получаю предупреждения - PullRequest
6 голосов
/ 31 января 2012

Я изучаю sml, и написал следующую простую функцию:

(* Return a list with every other element of the input list *)
fun everyOther [] = []
  | everyOther [x] = [x]
  | everyOther x = let
        val head::head2::tail = x
    in
        head::everyOther(tail)
    end;

Который выдает следующее предупреждение:

! Toplevel input:
!   val head::head2::tail = x
!       ^^^^^^^^^^^^^^^^^
! Warning: pattern matching is not exhaustive

Я полагаю, что функция никогда не может завершиться ошибкой, поскольку val head::head2::tail всегда будет работать для списков с двумя или более элементами, а случай с одним элементом и нулевыми элементами рассматривается. Насколько я могу судить, эта функция работает как положено. Я думаю, что проблема может быть связана с использованием [], но я действительно не знаю.

Мой вопрос на самом деле трехкратный:

  1. Почему sml считает, что это не является исчерпывающим (как я это неправильно понимаю)?
  2. Есть ли случаи, когда эта функция не будет работать?
  3. Я делаю что-то тупое, написав функцию таким образом?

1 Ответ

5 голосов
/ 31 января 2012
  1. SML предупреждает вас об этом, потому что не знает, что x имеет как минимум два элемента. Все, что он знает, это то, что x является списком, он не помнит тот факт, что x должен был не соответствовать первым двум шаблонам, чтобы перейти к третьему случаю.

  2. Нет, код не может завершиться ошибкой.

  3. Нет причин выполнять сопоставление с образцом в операторе let. Вы можете просто поместить шаблон в оператор fun, что приведет к уменьшению кода и удалению предупреждения:

    fun everyOther [] = []
      | everyOther [x] = [x]
      | everyOther (head::head2::tail) = head :: everyOther tail;
    
...