Посмотрите на этот код F # / OCaml:
type AllPossible =
| A of int
| B of int*int
| ...
| Z of ...
let foo x =
....
match x with
| A(value) | B(value,_) -> (* LINE 1 *)
(* do something with the first (or only, in the case of A) value *)
...
(* now do something that is different in the case of B *)
let possibleData =
match x with
| A(a) -> bar1(a)
| B(a,b) -> bar2(a+b)
| _ -> raise Exception (* the problem - read below *)
(* work with possibleData *)
...
| Z -> ...
Так в чем же проблема?В функции foo мы сопоставляем шаблон с большим списком типов.Некоторые из типов имеют общую функциональность - например, они выполняют общую работу, поэтому мы используем «| A | B ->» в строке 1 выше.Мы читаем единственное целое число (в случае A) или первое целое число (в случае B) и делаем что-то с ним.
Далее мы хотим сделать что-то совершенно другое, в зависимости отработаем ли мы на A или B (т.е. звоним bar1 или bar2).Теперь нам нужно снова сопоставить с образцом, и вот проблема: в этом вложенном сопоставлении с образцом, если мы не добавим правило 'catchAll' (то есть '_'), компилятор жалуется, что мы пропускаем случаи - т.е.учтите, что здесь могут произойти только A и B.
Но если мы добавим правило catchAll, то у нас будет гораздо более серьезная проблема: если в какой-то момент мы добавим больше типов в список LINE1 (т.е. в строку'| A | B ->' ... тогда компилятор НЕ поможет нам во вложенном сопоставлении - '_' поймает их, и в RUNTIME будет обнаружена ошибка. Одна из самых важных возможностей сопоставления с образцом -то есть обнаружение таких ошибок во время компиляции - потеряно.
Есть ли лучший способ написания такого рода кода, без необходимости повторять какую-либо работу, разделяемую между A и B, в двух отдельных правилах для A и B? (или помещая общую работу A-and-B в функцию, созданную исключительно для «локального совместного использования кода» между A и B?)
EDIT : обратите внимание, что можноутверждают, что F # coВ этом случае поведение mpiler является ошибочным - он должен быть в состоянии обнаружить, что нет необходимости в сопоставлении за пределами A и B во вложенном сопоставлении.