简单的 Prolog 程序:"Arguments are not sufficiently instantiated" 错误
Simple Prolog program: "Arguments are not sufficiently instantiated" error
我正在编写一个 Prolog 谓词,它从编号列表中删除前三个元素并打印结果。编号列表的示例:
[e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)].
普通列表的原始谓词如下所示:
strim([H|T],R) :-
append(P,R,[H|T]),
length(P,3).
因此,由于长度谓词也适用于编号列表,我只需要编写将一个编号列表附加到另一个编号列表的谓词:
compose([],L,[L]).
compose([e(F,C)|T],e(A,_),[e(F,C)|L]) :-
N is C+1,
compose(T,e(A,N),L).
napp(X,[],X).
napp(L,[e(X,Y)|T],M):-
compose(L,e(X,Y),L1),
napp(L1,T,M).
我希望编号列表的谓词是普通列表谓词的略微修改版本,所以我这样写:
numstrim([e(X,Y)|T],R) :-
napp(P,R,[e(X,Y)|T]),
length(P,3).
但是,我收到了这个错误:
ERROR: compose/3: Arguments are not sufficiently instantiated
有人可以解释导致错误的原因以及如何避免错误吗?我是 Prolog 的新手。
实例化错误是使用 moded 谓词的 Prolog 程序中的常见现象:这些谓词只能在特殊的 情况下使用 ,例如要求某些参数完全 实例化 等
作为初学者,我认为您最好使用 更一般的谓词 来代替,这样您就可以自由交换目标的顺序,而不必采取程序考虑到限制,至少不会那么早,并且无法自由试验您的代码。
例如,在您的情况下,以下对 compose/3
的 微不足道的 更改为您提供了一个适用于所有方向的谓词:
compose([], L, [L]).
compose([e(F,C)|T], e(A,_), [e(F,C)|L]) :-
N #= C+1,
compose(T, e(A,N), L).
在这里,我只是简单地将 moded 谓词 (is)/2
替换为 CLP(FD) 约束 (#=)/2
,它完全包含整数上的更低级谓词。
经过这个小改动(根据您的 Prolog 系统,您可能需要导入库才能使用更通用的算术谓词),我们得到:
?- numstrim([e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)], Es).
nontermination
因此,我们发现实例化错误实际上掩盖了另一个只能从程序上理解的问题,现在已经暴露出来。
为了改进这一点,我现在将 numstrim/2
的两个目标转过来:
numstrim([e(X,Y)|T], R) :-
length(P, 3),
napp(P, R, [e(X,Y)|T]).
这是因为length(P, 3)
总是终止,放置一个总是终止的目标先最多可以改善,永不恶化,纯单调逻辑程序的终止特性。
所以现在我们得到:
?- numstrim([e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)], Es).
Es = [e(b, _1442), e(a, _2678), e(r, _4286)] .
也就是说,至少我们现在得到一个答案!
但是,谓词仍然不终止 普遍,因为我们得到:
?- numstrim([e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)], Es), false.
nontermination
我将修复此作为练习。
我正在编写一个 Prolog 谓词,它从编号列表中删除前三个元素并打印结果。编号列表的示例:
[e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)].
普通列表的原始谓词如下所示:
strim([H|T],R) :-
append(P,R,[H|T]),
length(P,3).
因此,由于长度谓词也适用于编号列表,我只需要编写将一个编号列表附加到另一个编号列表的谓词:
compose([],L,[L]).
compose([e(F,C)|T],e(A,_),[e(F,C)|L]) :-
N is C+1,
compose(T,e(A,N),L).
napp(X,[],X).
napp(L,[e(X,Y)|T],M):-
compose(L,e(X,Y),L1),
napp(L1,T,M).
我希望编号列表的谓词是普通列表谓词的略微修改版本,所以我这样写:
numstrim([e(X,Y)|T],R) :-
napp(P,R,[e(X,Y)|T]),
length(P,3).
但是,我收到了这个错误:
ERROR: compose/3: Arguments are not sufficiently instantiated
有人可以解释导致错误的原因以及如何避免错误吗?我是 Prolog 的新手。
实例化错误是使用 moded 谓词的 Prolog 程序中的常见现象:这些谓词只能在特殊的 情况下使用 ,例如要求某些参数完全 实例化 等
作为初学者,我认为您最好使用 更一般的谓词 来代替,这样您就可以自由交换目标的顺序,而不必采取程序考虑到限制,至少不会那么早,并且无法自由试验您的代码。
例如,在您的情况下,以下对 compose/3
的 微不足道的 更改为您提供了一个适用于所有方向的谓词:
compose([], L, [L]). compose([e(F,C)|T], e(A,_), [e(F,C)|L]) :- N #= C+1, compose(T, e(A,N), L).
在这里,我只是简单地将 moded 谓词 (is)/2
替换为 CLP(FD) 约束 (#=)/2
,它完全包含整数上的更低级谓词。
经过这个小改动(根据您的 Prolog 系统,您可能需要导入库才能使用更通用的算术谓词),我们得到:
?- numstrim([e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)], Es). nontermination
因此,我们发现实例化错误实际上掩盖了另一个只能从程序上理解的问题,现在已经暴露出来。
为了改进这一点,我现在将 numstrim/2
的两个目标转过来:
numstrim([e(X,Y)|T], R) :- length(P, 3), napp(P, R, [e(X,Y)|T]).
这是因为length(P, 3)
总是终止,放置一个总是终止的目标先最多可以改善,永不恶化,纯单调逻辑程序的终止特性。
所以现在我们得到:
?- numstrim([e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)], Es). Es = [e(b, _1442), e(a, _2678), e(r, _4286)] .
也就是说,至少我们现在得到一个答案!
但是,谓词仍然不终止 普遍,因为我们得到:
?- numstrim([e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)], Es), false. nontermination
我将修复此作为练习。