OCaml Pattern Matching and Type synonyms

229 阅读2分钟

这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

我们通常会用到如下几个模式匹配:

  • p1 | ... | pn : 选择模式(or),从左到右,如果其中pi匹配成功就返回正确。所有的模式必须绑定同样的变量
  • (p : t):显式匹配类型
  • c: 这里c为常量,可以是整数、布尔类型的
  • 'ch1'..'ch2'ch说明这是一个字符。例如'A'..'Z'匹配所有的大些字母
  • p when e:当etrue是匹配p

more pattern forms : link

Let进行模式匹配

syntax

let表达式的用法实际上是一个特殊的语法结构

let p = e1 in e2

左边实际上一个模式,不仅仅是变量名。当然,变量的标识符也是我们合法模式的一个匹配。之前,一个let的定义被认为let表达式的body是没有给出的。所以,可以推出

let p = e

用函数进行模式匹配

let f p1 ... pn = e1 in e2   (* function as part of let expression *)
let f p1 ... pn = e          (* function definition at toplevel *)
fun p1 ... pn -> e           (* anonymous function *)

Examples

utop # (* Pokmon types *)
type ptype = TNormal | TFire | TWater;;
type ptype = TNormal | TFire | TWater


utop # (* A record to represent Pokmon *)
type mon = { name : string; hp : int; ptype: ptype };;
type mon = { name : string; hp : int; ptype : ptype; }

utop # (* OK *)
let get_hp m = match m with { name =n; hp = h; ptype = t } -> h;;
val get_hp : mon -> int = <fun>

utop # (* better *)
let get_hp m = match m with { name = _; hp = h; ptype = _ } -> h;;
val get_hp : mon -> int = <fun>

utop # (* better *)
let get_hp m = match m with {name; hp; ptype } -> hp;;
val get_hp : mon -> int = <fun>

utop # (* best *)
let get_hp m = m.hp;;
val get_hp : mon -> int = <fun>

这里我们可以通过如下的方式获得一个pair的第一个和第二个元素

utop # let fst (x, _) = x;;
val fst : 'a * 'b -> 'a = <fun>

utop # let snd (_, y) = y;;
val snd : 'a * 'b -> 'b = <fun>

这里的fstsnd已经存在标准库中。同理可以扩展到三元组上面。

Type Synonyms

类型的同名对已经存在的类型的新的名字。比如:

utop # type point = float * float;;
type point = float * float

utop # type vector = float list;;
type vector = float list

utop # type matrix = float list list;;
type matrix = float list list

在其他地方,你可以用point来代替float * float

utop # let get_x = fun (x, _) -> x;;
val get_x : 'a * 'b -> 'a = <fun>

utop # let p1 :point = (1., 2.);;
val p1 : point = (1., 2.)

utop # let p2 : float * float = (1., 3.);;
val p2 : float * float = (1., 3.)

utop # let a = get_x p1;;
val a : float = 1.

utop # let b = get_x p2;;
val b : float = 1.