Types 在OCaml中匹配总和类型时绑定名称

Types 在OCaml中匹配总和类型时绑定名称,types,ocaml,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))

在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\u pair
!相反,我希望能够写作

let f x = match x with
  | A (_ as pair) -> sum_pair pair
  | B (_, b) -> b
但这失败了,“错误:构造函数需要2个参数,但在这里应用于1个参数。”


也没有更好,因为这会将
绑定到整个值,而不是其中的对。(这也无法编译,正如您所期望的:“此表达式的类型为t,但表达式的类型应为int*int.”

如果您这样定义类型,则可以执行此操作:

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
#类型t=A of(int*int)| B of(int*int);;
类型t=A的(int*int)| B的(int*int)
#设和对(a,b)=a+b
设f x=将x与
|A p->和对p
|B(u,B)->B
;;
val和对:int*int->int=
val f:t->int=
#f(A(5,7));;
-:int=12

这是OCaml语法的一个棘手问题。下面是最近的另一个讨论:。

一般来说,我并不讨厌OCaml语法,但这很难看。OP的A构造函数与此答案中的语法完全相同,但它们有不同的类型。为什么我们不能为构造函数提供函数语法?这只是因为它们不能被咖喱化吗?我们可以使用函数语法,请参见
[@@deriving variants]
。BDFL是这么说的:另外,作为旁注,我想指出,该语言有一个很好的理由抵制您。它实际上是想告诉你,你做错了什么。没有理由创建一个curry函数,因为每次应用它时,都应该创建一对新函数。因此,您的
sum\u pair
开销很大。更好的版本应该是:
| A(x,y)->和对xy
# 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