我曾经以为我理解了类似于Scala和Haskell中的模式匹配与在Prolog中发现的协同一致的区别,但是我对Prolog的误解很大。有哪些简单的问题可以通过其中一个解决而无法通过另一个解决?
我曾经以为我理解了类似于Scala和Haskell中的模式匹配与在Prolog中发现的协同一致的区别,但是我对Prolog的误解很大。有哪些简单的问题可以通过其中一个解决而无法通过另一个解决?
简单来说,模式匹配是单向的,而统一是双向的。也就是说,在Prolog中,右侧(被匹配的一侧)可以包含未绑定的变量。例如,如果你有两个未绑定的变量X
和Y
,这将可以很好地工作:
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)解决方程X ++ A == B
,给定列表A
和B
,则需要编写3个单独的函数;在Prolog中,所有这些任务(及更多!)都由一个谓词完成。
我认为将概念形式化,而不是仅限于某个具体语言,是很有用的。匹配和统一是基本概念,不仅在模式匹配和Prolog中使用,在更多场景中也会用到。
举个例子,我们检查术语s = f(Y,a)和t = f(a,X),其中X、Y是变量,a是常量。s与t不匹配,因为我们无法对常量a进行普遍量化。然而,s和t存在一个统一:phi = {X\a, Y\a}
(1, 1) match{
case (x, x) => println("equals")
case _ => println("not equals")
}
(1, 2) match{
case (x, x) => println("equals")
case _ => println("not equals")
}
x
绑定到1
和2
时,统一将失败。?- append([1,2], [3], Z).
Z = [1, 2, 3].
?- append([1,2], Y, [1,2,3]).
Y = [3].
?- B = X + A, B 是 3,A 是 2。
- Feofilakt?- 8 #= X + 3.
=>X = 5.
。详细了解请参阅:https://www.metalevel.at/prolog/clpfd - Felixyz