OCaml的:如在模式匹配的关键字出现异常行为(OCaml : as keyword in patt

2019-09-28 12:36发布

比方说,我写这篇文章的代码:

# type t = A of int * int
  let f = function A (i1, i2) -> print_int i1;;
type t = A of int * int
val f : t -> unit = <fun>

完美的,它的工作原理。

现在,让我们说我有这样的功能:

# let print_couple (i1, i2) = print_int i1; print_int i2;;
val print_couple : int * int -> unit = <fun>

因此,当你想到,我想写以下

# let f = function A (_ as c) -> print_couple c;;

好吧,我不能

Error: The constructor A expects 2 argument(s),
       but is applied here to 1 argument(s)

我不知道,是不是因为的_或括号(我认真了有关质疑,但我想是详尽的)?

# let f = function A _ -> failwith "Fight me"
  let g = function A (_) -> failwith "1o1";;
val f : t -> 'a = <fun>
val g : t -> 'a = <fun>

不,这是不是...

哦,也许我必须表明我知道我有两个参数的编译:

# let f = function A ((_, _) as c) -> print_couple c;;
Error: The constructor A expects 2 argument(s), 
       but is applied here to 1 argument(s)

但是...如果我写

# let f = function A (_, _) -> failwith "Puppey style";;

有用。 那么,为什么,因为编译器知道我在等一对夫妇,我甚至试图把它给他它不断失败? 难道写A (_ as c)我命名,无论什么时候,第一个参数? 很奇怪,不是吗?

我的意思是,如果我写的

# let rec f = function
    | [] -> ()
    | hd :: tl -> print_couple hd; f tl;;
val f : (int * int) list -> unit = <fun>

编译器不会打扰我,这个名单是一个关联列表或一个整数列表? 然后就是很奇怪,从我期望从相同的行为

 # match a with
    | A c | A (_ as c) | A ((_, _) as c) -> ()

Answer 1:

这是OCaml中的怪癖,喜欢你的定义构造A需要什么语法看起来就像是一对,但不是对。

# type t = A of int * int;;
type t = A of int * int
# A (3, 4);;
- : t = A (3, 4)
# let z = (3, 4) in A z;;
Error: The constructor A expects 2 argument(s),
       but is applied here to 1 argument(s)

如果定义构造函数实际上正在一对,你可以提供一对:

# type u = B of (int * int);;
type u = B of (int * int)
# B (3, 4);;
- : u = B (3, 4)
# let z = (3, 4) in B z;;
- : u = B (3, 4)

这有点混乱,但它只是OCaml的工作方式。 您需要提供专门带括号的参数像一个构造A

这也是一个令人感到有点惊讶,你不需要对匹配时提供明确的括号_

# let A _ = A (4, 5);;
# 

(这仅是作为一个更大的图案,当然,部分是有用的。)



Answer 2:

严格地说,当你声明A of int * intA需要两个int参数,而不是由一对的一个参数int_是只有一个参数的占位符,因此,该错误消息时看到写A (_ as c)A _ )。 有没有办法(短期使用黑魔法我不会在这里描述的),以两个参数在某种程度上隐含改造A成一对:你不得不求助于match x with A (x,y) -> x,y

另一种方法是,这样只有一对,就像下面的代码来声明你的构造。 要知道,这是低效率的,但(你需要两种间接访问的参数A ,一个检索夫妇,和一个检索其组件):

type t = A of (int * int)
let print_couple (i1, i2) = print_int i1; print_int i2
let f = function A c -> print_couple c


文章来源: OCaml : as keyword in pattern matching behaving strangely