在OCaml中匹配sum类型时绑定名称

ben*_*sch 2 ocaml types

在OCaml中,是否可以在模式匹配时将名称绑定到数据构造函数的内容?作为一个说明性示例,假设我有以下OCaml程序:

type t = A of int * int | B of int * int

let sum_pair (a, b) = a + b

let f x = match x with
  | A (a1, a2) -> sum_pair (a1, a2)
  | B (_, b) -> b

let _ = Printf.printf "%d\n" (f (A (1, 2)))
Run Code Online (Sandbox Code Playgroud)

这会编译,但是我需要(a1, a2)在匹配后重新构建元组以将其传递给相当烦人sum_pair!相反,我希望能够写作

let f x = match x with
  | A (_ as pair) -> sum_pair pair
  | B (_, b) -> b
Run Code Online (Sandbox Code Playgroud)

但这失败了"错误:构造函数A需要2个参数,但这里应用于1个参数." 写作

let f x = match x with
  | A _ as pair -> sum_pair pair
  | B (_, b) -> b
Run Code Online (Sandbox Code Playgroud)

并不是更好,因为这与pair整个价值有关,而不是对内.(这也无法编译,正如您所期望的那样:"此表达式的类型为t,但表达式的类型为int*int.")

Jef*_*eld 5

如果您以这种方式定义类型,则可以使其工作:

type t = A of (int * int) | B of (int * int)
Run Code Online (Sandbox Code Playgroud)

这意味着构造函数A实际上接受一个参数是一对.在你的原始定义中,它需要两个不是一对的int参数,并且没有办法解决这个问题.

# type t = A of (int * int) | B of (int * int);;
type t = A of (int * int) | B of (int * int)

# let sum_pair (a, b) = a + b 

  let f x = match x with
  | A p -> sum_pair p
  | B (_, b) -> b
  ;;
val sum_pair : int * int -> int = <fun>
val f : t -> int = <fun>

# f (A (5, 7));;
- : int = 12
Run Code Online (Sandbox Code Playgroud)

这是OCaml语法的棘手问题.这是最近的另一个讨论:'作为'模式匹配关键词表现奇怪.