Понимание сопоставления с образцом с помощью оператора cons

В «Программировании F #» я наткнулся на сопоставление с образцом вроде этого (я немного упростил):

let rec len list = 
  match list with
  | [] -> 0
  | [_] -> 1
  | head :: tail -> 1 + len tail;;

Практически я понимаю, что последнее совпадение распознает начало и конец списка. Концептуально я не понимаю, почему это работает. Насколько я понимаю, :: - это оператор cons, который добавляет значение в начало списка, но мне не кажется, что он используется здесь как оператор. Следует ли мне понимать это как «специальный синтаксис» для списков, где :: интерпретируется как оператор или «шаблон соответствия» в зависимости от контекста? Или можно распространить ту же идею на типы, отличные от списков, с другими операторами?


person Mathias    schedule 17.05.2010    source источник


Ответы (3)


Помимо ответа Брайана, стоит отметить еще несколько моментов. Синтаксис h::t может использоваться как оператор и как шаблон:

let l = 1::2::[]                    // As an operator
match l with x::xs -> 1 | [] -> 0   // As a pattern

Это означает, что это немного особенная конструкция, потому что другие операторы (например, +) не могут использоваться в качестве шаблонов (для разложения результата обратно на аргументы оператора) - очевидно, для + это было бы неоднозначно.

Также паттерн [_] интересен тем, что является примером вложенного паттерна. В его состав входят:

  • _ - Шаблон подчеркивания, который соответствует любому значению и не связывает какие-либо символы
  • [ <pattern> ] - Шаблон одноэлементного списка, который сопоставляет списки с отдельными элементами и сопоставляет элемент списка с вложенным <pattern>.

Вы также можете написать match 1::[] with | [x] -> x, который вернет значение одного элемента (в данном случае 1).

person Tomas Petricek    schedule 17.05.2010
comment
Спасибо, ваше мнение о том, что :: является особой конструкцией, - это именно то, о чем я не понял. Я экспериментировал, пытаясь использовать другие операторы для сопоставления с образцом таким же образом, но это не имело особого смысла, и я ничего не добился, что и заставило меня задуматься о минусах. - person Mathias; 17.05.2010
comment
Обратите внимание, что то же самое верно и для кортежей - вы можете использовать шаблон (,) для построения и сопоставления / распаковки кортежей, а также для других типов (Some () / None) и т. Д. - person Benjol; 18.05.2010
comment
Вот список всех поддерживаемых типов шаблонов с примерами. - person JanDotNet; 12.02.2017

Это специальный синтаксис для списков. Вы можете думать о типе list как о размеченном объединении следующим образом:

type list<'T> =         // '
    | Nil
    | Cons of 'T * list<'T>

за исключением того, что есть специальный синтаксис, который делает Nil равным [], а Cons(h,t) h::t. Тогда это просто нормальное сопоставление с образцом в размеченном объединении. Это поможет?

(См. Также эту запись в блоге.)

person Brian    schedule 17.05.2010

Он используется как средство форматирования или формально pattern, `list 'сопоставляется с тремя шаблонами:

[] означает, что список пуст

[_] означает, что в списке один элемент, так как вам все равно, что это за элемент, поэтому просто поместите туда _, вы также можете использовать [a].

head :: tail означает, что список действительно состоит из двух частей: головы и хвоста.

Вы можете рассматривать сопоставление с образцом F # как мощную структуру if then else.

person Yin Zhu    schedule 17.05.2010