我以为我理解Scala和Haskell中的模式匹配与Prolog中的统一不同,但我对Prolog的误解很大。一个无法通过另一个解决的简单问题是什么? 谢谢
答案 0 :(得分:28)
简单陈述:模式匹配是单向的,统一是双向的。也就是说,在Prolog中,右侧(与之匹配的那个)可以包括未绑定的变量。例如,如果您有两个未绑定的变量X
和Y
,这将正常工作:
X = Y,
X = 5,
%% Y = 5 now as well
在Erlang中(使用接近Prolog的语法进行模式匹配),行X = Y
将产生错误:variable 'Y' is unbound
。请注意,X
未绑定是正常的:它应该是模式匹配的。
当您想要处理部分定义的值时,这非常有用。一个很好的例子是difference lists。
这也是允许在多种模式下使用Prolog谓词的原因。例如。在Scala / Haskell / Erlang中,如果你想1)找到A ++ B
,2)求解方程A ++ X == B
,或3)求解给定列表X ++ A == B
的等式A
和B
,你需要编写3个独立的函数;在Prolog中,所有这些工作(以及更多!)都由一个谓词完成。
答案 1 :(得分:5)
我认为将这些概念形式化是有用的,而不是寻找特定的语言。匹配和统一是在模式匹配和序言中使用的基本概念。
举一个例子,我们检查条件s = f(Y,a)和t = f(a,X)其中X,Y是变量,a是常数。 s与t不匹配,因为我们不能普遍量化常数a。但是,s和t有一个统一符:phi = {X \ a,Y \ a}
答案 2 :(得分:1)
Scala中的以下内容将无法编译,因为它的第一个案例分支尝试两次声明变量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
绑定到1
和2
时,统一会失败。
答案 3 :(得分:0)
在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中编写一个计划程序,然后你可以运行它"转发",给它一个计划并让它预测结果;或者你可以运行它"向后",给它一组结果并让它构建一个计划。您甚至可以同时以两种方式运行它(如果您在编码时小心),指定一组目标和一组计划约束,以便您可以说"找到一个开始工作的计划不涉及乘坐地铁。"