Prolog单变量查询返回一个错误。为什么?

Prolog单变量查询返回一个错误。为什么?,prolog,Prolog,我创建了一个简单的Prolog程序(使用GNU Prolog v1.4.4),其中有一个事实: sunny. 当我运行以下查询时: sunny. 我得到: yes uncaught exception: error(instantiation_error,top_level/0) 如我所料。运行此查询时: X. 我得到: yes uncaught exception: error(instantiation_error,top_level/0) 当我期望得到: X = sunny

我创建了一个简单的Prolog程序(使用GNU Prolog v1.4.4),其中有一个事实:

sunny.
当我运行以下查询时:

sunny.
我得到:

yes
uncaught exception: error(instantiation_error,top_level/0)
如我所料。运行此查询时:

X.
我得到:

yes
uncaught exception: error(instantiation_error,top_level/0)
当我期望得到:

X = sunny

有人知道为什么吗?

Prolog基于一阶逻辑,但
X
是二阶逻辑查询(变量代表规则头/事实,而不仅仅是一个术语):您可以询问“哪些谓词可以派生?”或者换句话说“哪些公式是真的?”。二阶逻辑的表现力如此之强,以至于我们失去了一阶逻辑(*)的许多优良特性。这就是为什么必须充分实例化二阶变量,以便在调用它时知道要尝试哪个规则(这就是错误消息的含义)。例如查询

?- X=member(A,[1,2,3]), X.

仍然允许Prolog尝试定义
成员
谓词(实际上这两个定义是等效的),但是

将引发异常,因为在应该派生
X
时,我们不知道它应该成为谓词
成员(A[1,2,3])

不过,您的情况要简单得多:您可以将
sunny
作为一个术语包装到谓词中,这样Prolog就知道应该尝试哪些规则。事实

weather(sunny).
weather(rainy).
定义谓词
weather
,这样现在我们的查询中只有一个一阶变量作为参数:

?- weather(X).
X = sunny ;
X = rainy.
现在我们讨论的是术语级别,一切都按照您的预期进行


(*)尽管在这两种情况下,确定公式是否有效的问题都是不可判定的,但在一阶逻辑中,至少可以最终导出所有真公式,但如果公式为假,搜索可能不会终止(即一阶逻辑是半可判定的)。对于二阶逻辑,有些公式既不能证明也不能反驳。更糟糕的是,我们甚至无法判断二阶公式是否属于这一类

明白了。我读过的所有解析算法描述都简单地说(基本上)“浏览目标列表,以递归方式将其与程序中每个规则的头部统一起来。然后组成MGU”。“目标”被定义为一个术语,由于术语被定义为“一个原子、变量或复合术语(函子)”…你们可以看到我是如何得到这里的。X将与sunny统一,因此我假设答案是X=sunny。所以,我想他们应该说“解决问题的目标必须是一个不可变的术语”?或者在定义中还有其他一些微妙之处暗示了这一点?Prolog模糊了术语和公式层之间的界限,特别是当涉及到元逻辑谓词(当然不是初学者的材料:)时。在一阶逻辑中,语言不允许使用
X
X(1,2,3)
形式的子句,尤其是初学者文本,假装
X
根本不是合法的序言查询。然后,目标与规则头的统一总是以
goal(Something)
head(SomethingElse)
的形式出现,并且统一总是导致术语的替代。如果您允许更高阶的统一,那么仅仅决定哪些规则可能被应用只是半决定性的。像
X(f(a))=f(X(a))
这样的统一问题有无限多个最通用的统一因子(一阶逻辑的另一个很好的特性,在对公式/函数进行量化时丢失)。通常,所有可能派生的树都是有限分支的,但可能有无限深的路径。使用高阶统一子时,搜索树也突然(可能)无限分支。