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

时间:2016-11-18 03:45:30

标签: types ocaml

在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)))

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

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

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

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

并不是更好,因为这会将pair绑定到整个值,而不是内部对。 (这也无法编译,正如您所期望的那样:"此表达式的类型为t,但表达式的类型为int * int。")

1 个答案:

答案 0 :(得分:5)

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

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

这意味着构造函数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

这是OCaml语法的棘手问题。以下是另一个最近的讨论:'as' Keyword in Pattern Matching Behaving Strangely