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

发布于 2024-11-06 03:31:19 字数 1010 浏览 1 评论 0原文

我需要检测我的函数之一中的交换模式。我认为编写以下内容可以完成工作:

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

这不起作用,Ocaml 抱怨 this sub-pattern isused 对标有 (***) 的行发出警告。

1)有人可以向我解释这个警告的意思以及为什么这不起作用吗?

2) 鉴于我现在想要哪个参数 is_valid,我如何才能在不使用 if then else 的情况下优雅地编写此代码?

2) 是仅使用模式匹配即可获得预期功能,并且无需重复 when is_valid b ->;进程 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 的答案),我如何才能使其工作。您能建议一种方法使其在我的情况下发挥作用吗?

I need to detect a commutative pattern in one of my functions. I thought that writing the following will do the work:

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

This doesn't work and Ocaml complains with this sub-pattern is unused
warning for the line marked with (***).

1) Can someone explain to me what this warning try to say and why this doesn't work?

2) How can I actually write this elegantly without using if then else given the fact that I want to now which argument is_valid?

2) Is it possible to get the intended functionality using only pattern matching and without repeating when is_valid b -> process b as it happens bellow?

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 
  (*...*)

Edit:

In my concrete example a and b are pairs. The function is a bit more complicated but the following will illustrate the case:

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

Calling f (1,1) (1,2) will yield pattern match failed. I know understand why (thanks to the answers bellow) and I understand how I can make it work if I have different constructors for each element (as in Ashish Agarwal's answer). Can you suggest a way to make it work in my case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嘿哥们儿 2024-11-13 03:31:19

匹配的工作原理是首先匹配模式,如果成功,则通过该模式匹配的附加环境评估条件。由于 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

您将在 模式 的定义中看到这一点。它实际上是一种模式,由多个模式组成,相互匹配。

The matching works by first matching the pattern, and if that succeedes, then by evaluating the condition with the attached environment from that pattern match. Since a,b will always bind, this is the only case used, and the compiler is correctly reporting that b,a is never used. You'll have to repeat that line,

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

Your method could work if you didn't perform the match with variables but to some variant, for example,

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

Edit: Think of the multiple patterns using one guard as a subexpression,

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

You'll see this exemplified in the definition for patterns. It's really one pattern, composed of patterns, being matched.

大姐,你呐 2024-11-13 03:31:19

对于你的第一个问题,要认识到你只有一个模式 ((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 类型正在与.

For your first question, the thing to realize is you only have one pattern ((a,b) | (b,a)), which happens to be an "or" pattern. Matching proceeds from left to right in an "or" pattern. Since (a,b) will match anything, the second part will never be used.

For your second question, I don't see the problem, but it depends on the types of a and b. Here's an example:

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

It would also work for simpler types:

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

If you still can't get this to work in your case, let us know the types of a and b you are working with.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文