如何在OCaml中使用:: when模式匹配时

tim*_*ngy 1 ocaml functional-programming list pattern-matching

let rec (l:int list) f int list =
  match l with
  | [] -> []
  | hd::tl -> 2+tl
Run Code Online (Sandbox Code Playgroud)

我想知道的是hd第一个元素,然后tl是第二个元素因为当我这样做时我不断得到一个错误,如果tl不是第二个元素我将如何访问第二个元素深入解释hd::tl将非常感谢谢谢

ivg*_*ivg 6

tl不是第二个元素,它是列表的其余部分,它的类型为'a list.这里hdtl是你选择绑定到列表的第一个元素只是变量名,并以列表的其余部分(即,包含除第一个所有元素的列表).您可以选择其他名称,例如fst::rest.在这种情况下获得第二个元素就像fst::snd::rest(或者x::y::rest- 名称无关紧要)一样简单.

您尝试使用的是模式匹配.它是某些语言的一个特性,它提供了一种轻松解构复合数据结构的机制.我们的想法是,如果您以与构建数据结构相同的方式解构数据结构,例如,

let xs = [1;2;3;4]
Run Code Online (Sandbox Code Playgroud)

这是解构

let [x1;x2;x3;x4] = xs
Run Code Online (Sandbox Code Playgroud)

实际上,[x;y;...;z]对于更基本的语法来说,它是一种语法糖x :: y:: ... :: z :: [],因此构造[1;2;3;4]列表的另一种方法是使用以下构造:1::2::3::4::[].同样的方向相反,例如,

 let x1::x2::x3::x4::[] = xs
Run Code Online (Sandbox Code Playgroud)

现在我们准备下一步,如果右边的结构与左边的结构不匹配,例如,

 let [x;y;z] = [1;2]
Run Code Online (Sandbox Code Playgroud)

要么

 let x::y::z::[] = 1::2::[]
Run Code Online (Sandbox Code Playgroud)

在这种情况下,匹配将失败.在我们的运行时案例中.为了防止这种情况,并允许程序员处理其数据结构的所有可能配置,OCaml提供了一个match构造,您可以在其中指定值结构的多个变体,并选择匹配的第一个,例如,

let orcish_length xs = match xs with
  | [] -> 0
  | x :: [] -> 1
  | x :: y :: [] -> 2
  | x :: y :: z :: [] -> 3
Run Code Online (Sandbox Code Playgroud)

上面的函数仅预测具有最多三个元素的列表(因为Orcs不能超过三个).但我们可以.为此,我们将使用以下功能 - 如果列表模式的最后一个元素不是[](仅匹配且仅与空列表匹配,并指定列表末尾),但其他任何内容(即变量) ),然后这个变量将绑定到所有元素,例如,

let rec elvish_length xs = match xs with
  | [] -> 0
  | x :: [] -> 1
  | x :: y :: [] -> 2
  | x :: y :: z :: [] -> 3
  | x :: y :: z :: leftovers -> 3 + elvish_length leftovers
Run Code Online (Sandbox Code Playgroud)

所以现在,我们预计所有可能的列表模式.但是,该功能现在过于复杂(因为精灵很复杂).现在,让我们最终得出一个普通的,人类可读的长度函数,

  let rec length xs = match xs with
    | [] -> 0
    | x :: xs -> 1 + length xs
Run Code Online (Sandbox Code Playgroud)

作为练习,尝试向自己证明此功能可以预测所有可能的列表.