OCaml:作为模式匹配中的关键字时,行为异常 [英] OCaml : as keyword in pattern matching behaving strangely

查看:93
本文介绍了OCaml:作为模式匹配中的关键字时,行为异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说我写这段代码:

# 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>

完美,有效.

现在,假设我有这个很棒的功能:

Now, let's say I have this wonderful function :

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

所以,正如您所期望的,我想写以下内容

So, as you expect, I'd like to write the following

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

我想知道是因为_还是括号(我对此深信不疑,但我想穷举一下)?

I wondered, is it because of the _ or the parenthesis (I seriously had doubts about that but I wanted to be exhaustive) ?

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

不,不是...

哦,也许我必须告诉编译器我知道我有两个参数:

Oh, maybe I have to show the compiler I know I have two arguments :

# 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)我是在命名第一个参数,无论如何?很奇怪,不是吗?

It works. Then why, since the compiler knows that I'm expecting a couple and I'm even trying to give it to him it keeps failing ? Is it that by writing A (_ as c) I'm naming, no matter what, the first argument ? It's strange, isn't it ?

我的意思是,如果我写

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

对于这个列表是关联列表还是整数列表,编译器不会打扰我吗?那么,对我期望同样的行为感到奇怪吗?

The compiler won't bother me about this list being an association list or an integer list ? Then is it strange from me to expect the same behaviour from

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

?

推荐答案

OCaml的怪癖是,像您对A的定义那样的构造函数在语法上看起来像一对,但不是一对.

It's a quirk of OCaml that a constructor like your definition of A takes what syntactically looks like a pair, but is not a pair.

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

如果将构造函数定义为实际使用一对,则可以提供一对:

If you define the constructor as actually taking a pair, you can supply a pair:

# 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之类的构造函数提供专门带括号的参数.

This is somewhat confusing, but it's just the way OCaml works. You need to supply specifically parenthesized arguments to a constructor like A.

_匹配时不需要提供明确的括号也令人有些惊讶:

It's also a little surprising that you don't need to supply explicit parentheses when matching against _:

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

(当然,这仅在较大模式中有用.)

(This is only useful as part of a larger pattern, of course.)

这篇关于OCaml:作为模式匹配中的关键字时,行为异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆