Понимание соответствия шаблонов с операторами cons

В "Программирование F #" я столкнулся с подобранным шаблоном (я немного упростил):

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

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

Ответ 1

В дополнение к ответу Брайана, есть несколько моментов, которые стоит отметить. Синтаксис 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).

Ответ 2

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

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

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

(Возможно, также смотрите эту запись в блоге.)

Ответ 3

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

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

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

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

Вы можете просмотреть сопоставление шаблонов F # в качестве мощной структуры if if else.