模式匹配和统一之间的区别?

发布于 2024-10-07 17:52:09 字数 101 浏览 6 评论 0原文

我以为我理解 Scala 和 Haskell 中的模式匹配与 Prolog 中的统一有何不同,但我对 Prolog 的误解很大。有哪些简单的问题,一个人可以解决,另一个人却无法解决? 谢谢

I thought I understand how pattern matching like found in Scala and Haskell is different from unification found in Prolog but my misunderstands of Prolog is great. What is some simple problems solvable by one that cannot be solved by the other?
Thank you

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

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

发布评论

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

评论(4

眼趣 2024-10-14 17:52:09

简单的说法:模式匹配是单向的,统一是双向的。也就是说,在 Prolog 中,右侧(正在匹配的一侧)可以包含未绑定的变量。例如,如果你有两个未绑定的变量 XY,这将工作得很好:

X = Y,
X = 5,
%% Y = 5 now as well

在 Erlang 中(使用与 Prolog 语法接近的模式匹配),行 X = Y 将产生错误:变量“Y”未绑定。请注意,X 未绑定是可以的:它应该是模式匹配的。

当您想要处理部分定义的值时,这可能很有用。一个很好的例子是差异列表

这也是允许在多种模式下使用 Prolog 谓词的原因。例如,在 Scala/Haskell/Erlang 中,如果您想要 1) 找到 A ++ B,2) 求解方程 A ++ X == B,或 3)对于给定的列表 AB,求解方程 X ++ A == B,您需要编写 3 个独立的函数;在 Prolog 中,所有这些工作(以及更多!)都是由一个谓词完成的。

Simple statement: pattern matching is one-way, unification is two-way. That is, in Prolog the right-hand side (the one being matched against) can include unbound variables. E.g., if you have two unbound variables X and Y, this will work fine:

X = Y,
X = 5,
%% Y = 5 now as well

In Erlang (which uses pattern-matching with syntax close to Prolog), the line X = Y will produce an error: variable 'Y' is unbound. Note that X being unbound is fine: it is supposed to be pattern-matched.

This can be useful when you want to deal with partially-defined values. A very good example is difference lists.

This is also what allows use of Prolog predicate in multiple modes. E.g. in Scala/Haskell/Erlang, if you want to 1) find A ++ B, 2) solve the equation A ++ X == B, or 3) solve the equation X ++ A == B for given lists A and B, you need to write 3 separate functions; in Prolog, all these jobs (and more!) are done by one predicate.

娇纵 2024-10-14 17:52:09

我认为将概念形式化是有用的,而不是研究特定的语言。匹配和统一是基本概念,比模式匹配和序言在更多上下文中使用。

  • 项 s 与 t 匹配,当且仅当存在替换 phi 使得 phi(s) = t
  • 项 s 与项 t 统一,当且仅当存在替换 phi 使 phi(s) = phi(t)

举个例子,我们检查术语 s = f(Y,a) 和 t = f(a,X),其中 X、Y 是变量,a 是常量。 s 与 t 不匹配,因为我们无法普遍量化常数 a。然而,s 和 t 有一个统一符: phi = {X\a, Y\a}

I think it is useful to formalize the concepts, instead of looking into a specific language. Matching and unification are fundamental concepts that are used in more contexts than pattern matching and prolog.

  • A term s matches t, iff there is a substitution phi such that phi(s) = t
  • A term s unifies with a term t, iff there is a substitution such that phi(s) = phi(t)

To give an example we inspect the terms s = f(Y,a) and t = f(a,X) where X,Y are variables and a is a constant. s does not match t, because we cannot universally quantify the constant a. However, there is a unifier for s and t: phi = {X\a, Y\a}

新人笑 2024-10-14 17:52:09

Scala 中的以下内容将无法编译,因为它的第一个 case 分支尝试声明变量 x 两次。

(1, 1) match{
   case (x, x) => println("equals")
   case _      => println("not equals")
}

如果 Scala 使用统一而不是模式匹配,则会成功并打印“等于”,同时

(1, 2) match{
   case (x, x) => println("equals")
   case _      => println("not equals")
}

会打印“不等于”。这是因为当尝试将变量 x 绑定到 12 时,统一会失败。

The following in Scala would fail to compile, as it's first case branch attempts to declare the variable x twice.

(1, 1) match{
   case (x, x) => println("equals")
   case _      => println("not equals")
}

If Scala used unification instead of pattern matching this would succeed and print "equals" while

(1, 2) match{
   case (x, x) => println("equals")
   case _      => println("not equals")
}

would print "not equals". This is because the unification would fail when attempting to bind the variable x to both 1 and 2.

南烟 2024-10-14 17:52:09

在 Prolog 中,您可以将 [3] 附加到 [1,2],如下所示:

?- append([1,2], [3], Z).
Z = [1, 2, 3].

统一的巧妙之处在于您可以使用相同的代码(“append”的内部定义),但是找到获取所需的第二个参数第一个参数的结果:

?- append([1,2], Y, [1,2,3]).
Y = [3].

在 Prolog 中,您可以通过说出您所知道的内容来进行编码,而不是通过编写“这样做,然后那样做”来进行编码。 Prolog 将您提供的事实视为方程。统一让它采用这些方程并求解您还不知道其值的任何变量,无论它们是在右侧还是左侧。

例如,您可以在 Prolog 中编写一个规划器,然后可以“向前”运行它,给它一个计划并让它预测其结果;或者您可以“向后”运行它,给它一组结果并让它构建一个计划。您甚至可以同时运行两种方式(如果您在编码时小心的话),指定计划的一组目标和一组约束,这样您就可以说“找到一个不涉及的开始工作计划”坐地铁。”

In Prolog, you can append [3] to [1,2] like this:

?- append([1,2], [3], Z).
Z = [1, 2, 3].

The neat thing about unification is that you can use the same code (the internal definition of 'append'), but instead find the second argument needed to get the result from the first argument:

?- append([1,2], Y, [1,2,3]).
Y = [3].

Rather than coding by writing "do this, then do that", you code in Prolog by saying what you know. Prolog treats the facts you give it as equations. Unification lets it take those equations and solve for whatever variables you don't yet know the values of, whether they're on the right or left side.

So, for instance, you can write a planner in Prolog, and you can run it "forward", giving it a plan and having it predict its results; or you can run it "backward", giving it a set of results and having it construct a plan. You could even run it both ways at once (if you were careful in your coding), specifying a set of goals and a set of constraints on the plan, so that you could say "Find a plan for getting to work that does not involve taking the subway."

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