我已经基于一个事实创建了一个简单的Prolog程序(使用GNU Prolog v1.4.4):
sunny.
当我运行以下查询时:
sunny.
我得到:
yes
如我所料。当我运行此查询时:
X.
我得到:
uncaught exception: error(instantiation_error,top_level/0)
我期望得到的时间:
X = sunny
有人知道为什么吗?
答案 0 :(得分:6)
序言基于一阶逻辑,但是X
是二阶逻辑查询(变量代表规则头/事实,而不仅是术语):您问“可以导出哪些谓词?”或换句话说“哪个公式是正确的?”。二阶逻辑是如此富有表现力,以至于我们失去了许多一阶逻辑(*)的优良特性。这就是为什么必须充分实例化二阶变量以知道在调用该规则时尝试哪个规则的原因(这就是错误消息的含义)。例如查询
?- X=member(A,[1,2,3]), X.
和
?- member(A,[1,2,3]).
仍然允许Prolog尝试member
谓词的定义(实际上,这两个定义是等效的),但是
?- X, X=member(A,[1,2,3]).
将引发异常,因为在应推导X
时,我们不知道它应该成为谓词member(A,[1,2,3])
。
不过,您的情况要简单得多:您可以将sunny
作为术语包装到谓词中,以便Prolog知道要尝试的规则。事实
weather(sunny).
weather(rainy).
定义谓词weather
,以便现在我们在查询中仅具有一阶变量作为参数:
?- weather(X).
X = sunny ;
X = rainy.
现在我们正在谈论术语级别,一切都按您的预期进行。
(*)尽管在两种情况下都无法确定公式是否有效,但是在一阶逻辑中至少可以最终得出所有正确的公式,但是如果公式为false,则搜索可能不会终止(即一阶逻辑是半确定的)。对于二阶逻辑,有一些公式不能证明不成立。更糟糕的是,我们甚至无法确定二阶公式是否属于该类别。