我用一个事实创建了一个简单的Prolog程序(使用GNU Prolog v1.4.4):
sunny.
Run Code Online (Sandbox Code Playgroud)
当我运行以下查询时:
sunny.
Run Code Online (Sandbox Code Playgroud)
我明白了:
yes
Run Code Online (Sandbox Code Playgroud)
正如我所料.当我运行此查询时:
X.
Run Code Online (Sandbox Code Playgroud)
我明白了:
uncaught exception: error(instantiation_error,top_level/0)
Run Code Online (Sandbox Code Playgroud)
当我期望得到:
X = sunny
Run Code Online (Sandbox Code Playgroud)
谁知道为什么?
Prolog基于一阶逻辑,但是X
是二阶逻辑查询(变量代表规则头/事实,而不仅仅是一个术语):你问"可以推导出哪些谓词?" 或换句话说"哪些公式是真的?".二阶逻辑是如此富有表现力,以至于我们失去了一阶逻辑(*)的许多优良特性.这就是为什么必须充分实例化二阶变量以了解在调用它时要尝试的规则(这就是错误消息的含义).例如查询
?- X=member(A,[1,2,3]), X.
Run Code Online (Sandbox Code Playgroud)
和
?- member(A,[1,2,3]).
Run Code Online (Sandbox Code Playgroud)
仍允许Prolog尝试member
谓词的定义(实际上这两个定义是等价的)但是
?- X, X=member(A,[1,2,3]).
Run Code Online (Sandbox Code Playgroud)
会抛出异常因为当时X
应该派生出来,我们不知道它应该成为谓词member(A,[1,2,3])
.
你的情况要简单得多:你可以将sunny
一个术语包装成一个谓词,以便Prolog知道要尝试哪些规则.事实
weather(sunny).
weather(rainy).
Run Code Online (Sandbox Code Playgroud)
定义谓词weather
,以便现在我们在查询中只有一个变量作为参数:
?- weather(X).
X = sunny ;
X = rainy.
Run Code Online (Sandbox Code Playgroud)
现在我们正在讨论术语级别,一切都按预期工作.
(*)虽然在两种情况下找出公式是否有效的问题是不可判定的,但在一阶逻辑中,至少所有真公式都可以最终导出,但如果公式为假,则搜索可能不会终止(即一阶逻辑是半可判定的).对于二阶逻辑,有些公式既不能被证明也不能被证明.更糟糕的是,我们甚至无法判断二阶公式是否属于这一类.