【问题标题】:Prolog: arguments not sufficiently instantiated (sum of list 1+2+...+n)Prolog:参数没有充分实例化(列表 1+2+...+n 的总和)
【发布时间】:2017-03-28 18:14:17
【问题描述】:

我需要写一个谓词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),将不胜感激!

提前致谢。

【问题讨论】:

    标签: list prolog sum instantiation-error


    【解决方案1】:

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

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

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

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

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

    因此,我们得到:

    列表和(L,S):-列表和(L,S,1)。 列表和(L,0,A):- N #= A-1, N #> 1, 从到(1,N,L)。 列表和(L,S,A):- S #> 0, SA #= S-A, A1 #= A+1, 列表和(L,SA,A1)。

    另外,如果你的Prolog系统提供numlist/3,我建议fromTo/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 系统要求您导入库以使用声明性整数运算。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-26
      相关资源
      最近更新 更多