Prolog:参数未充分实例化(列表 1+2+ 的总和.+n)



>我需要写一个谓词listsum(L, S)这是真的,因为L是从1增加到某个n的自然数列表(即[1,2,..,n])。现在我让它适用于listsum(L, <any number larger than 0>)类型的查询,但是当我尝试查询例如listsum([1,2,3], S)时,它说参数没有充分实例化。这是我的代码:

listsum(L,S) :- listsum(L,S,1).
listsum(L, 0, A) :- 
N is A-1,
N > 1,
fromTo(1, N, L). ; true iff L is the list [1,2,...,N]
listsum(L, S, A) :-
S > 0,
SA is S-A,
A1 is A+1,
listsum(L, SA, A1).

如果有人能帮助我如何以两种方式完成这项工作(因此也使用 L 的给定值,查询 S),将不胜感激!

提前谢谢。

当初学者第一次遇到老式的Prolog 代码时,此错误是一个常见问题。原因是像(is)/2(>)/2这样的谓词不是真正的关系。相反,它们只有在它们的参数被充分实例化时才有效。

这引起了很多混乱,尤其是在初学者中,从实际的角度来看 ,显然也是非常不幸的。在Prolog中 编程时,我们希望从关系的普遍性中受益,而不是从一开始就陷入这种低级问题 。

此类问题的声明性解决方案是约束。各种Prolog 系统对它们的支持有所不同。然而,目前,使用最 广泛的Prolog系统都至少带有整数约束。

例如,要在 GNU Prolog 中使用它们,只需对您的代码进行以下直接的更改:

  • (is)/2替换为(#=)/2
  • (>)/2替换为(#>)/2

因此,我们获得:

listsum(L,S) :- listsum(L,S,1). listsum(L, 0, A) :-N #= A-1, N #> 1, fromTo(1, N, L). listsum(L, S, A) :-S #> 0, SA #= S-A, A1 #= A+1, listsum(L, SA, A1).

此外,我建议以下fromTo/3定义,如果你的Prolog系统提供了numlist/3

fromTo(1, N, Ls
) :- numlist(1, N, Ls).

我把实施numlist/3自己留作一个简单的练习。

通过这些更改,我们得到:

?- listsum([1,2,3], S).S = 6 。

因此,至少我们得到了正确的解决方案,现在可以专注于剩余的问题。

例如,查询不会普遍终止,我们可以看到:

?- listsum([1,2,3], S),false.不可终止

我把纠正这个问题作为一种练习。

请注意,某些Prolog系统要求您导入库以使用声明性整数算术。

最新更新