问题描述
Peano 算术中的这个小于谓词
less(0,s(_)).
less(s(X),s(Y)) :- less(X,Y).
何时循环
?- less(X,Y),X=s(0),Y=0.
有没有更好的写法less/2
(仅使用 Horn 子句)?
解决方法
您可以使用 when/2
。使它不再是一个无限枚举的谓词,并且仍然保持 100% 纯净。 when/2
修改了 SLD-Resolution 中的 S(选择规则),这一想法可以追溯到 Alain Colmerauer。
less(X,Y) :- when((nonvar(X),nonvar(Y)),less2(X,Y)).
less2(0,s(_)).
less2(s(X),s(Y)) :- less(X,Y).
将 less/2
改写为 less/2
和 less2/2
类似于表格改写。您插入一个存根并重命名子句标题。但是主体中的递归调用并没有被重写,而是再次调用存根。
你现在变得坚定了:
?- less(s(s(0)),s(s(s(0)))).
true.
?- less(X,Y),X = s(s(0)),Y = s(s(s(0))).
X = s(s(0)),Y = s(s(s(0))).
甚至有时会出现不稳定性和真实性:
?- less(s(s(_)),s(0)).
false.
?- less(s(0),s(s(_))).
true.
一些Prolog系统甚至提供了一个类似table/1的指令,这样你就不需要重写,只需要进行声明。一种这样的系统是 SICStus Prolog。在 SICStus Prolog 中,感谢 block/1 directive,
你只会写:
:- block less(-,?),less(?,-).
less(0,s(_)).
less(s(X),Y).
对于 1980 年代的论文,请参见示例:
WAM 中 diff 和 freeze 的实现
Mats Carlsson - 1986 年 12 月 18 日
http://www.softwarepreservation.com/projects/prolog/sics/doc/Carlsson-SICS-TR-86-12.pdf/view