如何使用模式匹配检测Ocaml中的交换模式?

时间:2011-05-09 15:07:09

标签: warnings pattern-matching ocaml

我需要在我的一个函数中检测到一个可交换模式。我认为写下面的内容可以完成这项工作:

let my_fun a b = match a,b with
  (*...*)
  | a,b
  | b,a when is_valid b -> process b  (***)
  (*...*)

这不起作用,Ocaml抱怨此子模式未使用 标有(***)的行的警告。

1)有人可以向我解释这个警告试图说什么以及为什么这不起作用?

2)考虑到我现在想要哪个参数if then else

,我怎么能在不使用is_valid的情况下优雅地写出这个呢?

2)是否可以仅使用模式匹配来获得预期的功能而不重复when is_valid b -> process b,如下所示?

let my_fun a b = match a,b with
  (*...*)
  | a,b when is_valid b -> process b
  | b,a when is_valid b -> process b 
  (*...*)

编辑:

在我的具体示例中,ab是成对的。这个函数有点复杂,但下面将说明这个案例:

let f a b = match a,b with
  | (a1,a2),(b1,b2)
  | (b1,b2),(a1,a2) when b1 = b2 -> a1 + a2

调用f (1,1) (1,2)会导致模式匹配失败。我知道理解为什么(感谢下面的答案),如果我对每个元素都有不同的构造函数,我理解如何使它工作(如在Ashish Agarwal的答案中)。你能建议一种方法让它适用于我的情况吗?

2 个答案:

答案 0 :(得分:7)

匹配首先匹配模式,如果成功,则通过从该模式匹配的附加环境评估条件。由于a,b将始终绑定,因此这是唯一使用的情况,并且编译器正确报告从未使用b,a。你必须重复这一行,

let my_fun a b = match a,b with
  | a,b when is_valid b -> process b
  | b,a when is_valid b -> process b

如果您没有对变量执行匹配,但是对某些变体执行匹配,则可以使用您的方法,例如,

let my_fun a b = match a,b with
  | a, `Int b
  | `Int b, a when is_valid b -> process b

编辑:使用一个后卫作为子表达式来考虑多个模式,

let my_fun a b = match a,b with
  | ((a,b) | (b,a)) when is_valid b -> process b

您会在patterns的定义中看到这一点。它实际上是一种模式,由模式组成,匹配。

答案 1 :(得分:4)

对于你的第一个问题,要意识到的是你只有一个模式((a,b) | (b,a)),恰好是一个“或”模式。匹配从“左”到“右”以“或”模式进行。由于(a,b)将匹配任何内容,因此第二部分将永远不会被使用。

对于您的第二个问题,我没有看到问题,但这取决于ab的类型。这是一个例子:

type t = A of int | B of float

let my_fun a b = match a,b with
  | A a, B b
  | B b, A a when b > 0. ->  (float_of_int a) +. b
  | … -> (* other cases *)

它也适用于更简单的类型:

let my_fun a b = match a,b with
  | 1,b
  | b,1 when b > 0 -> b + 1
  | … -> (* other cases *)

如果您仍然无法使用此功能,请告诉我们您正在使用的ab的类型。