Почему шаблон OCaml "ноль -> ноль", кажется, соответствует всему? - PullRequest
5 голосов
/ 30 января 2012

Вот фрагмент кода из моей книги, и я не уверен в том, как работает сопоставление, очевидно, потому что кажется, что первый случай соответствует всему.Вот предупреждения, которые Окамл бросает в меня:

# let zero = 0;;
# let one = 1;;
# let rec fib i =
match i with
zero -> zero
| one -> one
| j -> fib (j - 2) + fib (j - 1);;
Characters 57-60:


Warning: this match case is unused.
Characters 74-75:
Warning: this match case is unused.
| one -> one
^^^
| j -> fib (j - 2) + fib (j - 1);; 
^
val fib : int -> int = <fun>
# fib 1;;
- : int = 1
# fib 2002;;
- : int = 2002

Ответы [ 2 ]

9 голосов
/ 30 января 2012

Это довольно распространенный источник путаницы.По сути, вы хотите думать о шаблонах как о созданных из констант (например, 0 и 1) и идентификаторов, которые связаны шаблоном.

Когда идентификатор отображается в шаблоне, он вообще совпадает с чем угодно и связывает сопоставленное значение с идентификатором.Идентификатор в шаблоне не относится к любому предыдущему значению, связанному с идентификатором.Таким образом, ваш шаблон всегда будет соответствовать первому случаю и связывать zero со значением i.

. Вы можете представить, что хотите иметь возможность давать имена постоянным значениям, а затемиспользуйте имена, а не константы в шаблоне.Однако OCaml (как и другие языки FP) не работает таким образом.Одним из преимуществ (мне кажется) является простота.

0 голосов
/ 31 января 2012

Я подумал, что добавлю, что если вы переписали код следующим образом, он будет работать нормально:

# let zero = 0;;
# let one = 1;;
# let rec fib i =
match i with
  0 -> zero
| 1 -> one
| j -> fib (j - 2) + fib (j - 1);;

Фундаментальная проблема (как довольно хорошо объяснено в другом ответе)что вы можете создавать новые локальные переменные с тем же именем, что и глобальные переменные, и что с помощью любого имени переменной в левой части совпадения просто создается новая локальная переменная с таким именем и заполняется ею при сопоставлении.Точно так же, как j - это новая локальная переменная, которая содержит все сопоставляемое, zero.А тот факт, что он был ранее объявлен в большем объеме, игнорируется Ocaml (вот почему вы можете с радостью писать такие вещи, как

let x = 1;;
let x = 2 in let x = 3 in x;;

, что дает результат 3.

...