【问题标题】:Prolog: Head of a variable list is not instantatedProlog:变量列表的头部未实例化
【发布时间】:2017-06-28 15:57:39
【问题描述】:

我正在编写一个简单的代码,生成一个包含 5 个数字的简单列表,其第一个变量应该是正数,我试图理解为什么这段代码会失败

test([H|T]) :- H > 0, length(T,4).

当我打电话时

 length(X,5), test(X).

它显示以下错误:

错误:参数没有充分实例化

当我调试代码时,test 中的 H 变量没有被实例化。

有人知道为什么吗?

【问题讨论】:

  • 它怎么知道它应该是一个数字?
  • 尝试查询length(X, 5).
  • length(X, 5) 给你一个......嗯......长度为 5 的列表,但其元素尚不清楚。所以它们是可变的。 length/2 不会生成实际的元素。
  • 您收到实例化错误的原因与H > 0 给您的原因相同。
  • 换句话说,在 Prolog 提示符下尝试查询 H > 0.H 没有被实例化,因为 you 还没有将它实例化为任何东西。但是,如果你这样做,例如H = 3, H > 0.,或H is 1 + 2, H > 0.然后它工作。另见stackoverflow.com/tags/instantiation-error/info

标签: list prolog instantiation-error


【解决方案1】:

这里的问题是您的test([H|T]) 规则在Prolog 中没有描述H 是一个正整数。它只测试H > 0 是否失败,因为H 没有实例化。仅仅试图将一个未实例化的变量与一个数字(在这种情况下为 H > 0)进行比较不会导致 Prolog 假定您打算将 H 视为一个数字,并且不会实例化 H

此外,您的 test/1 规则没有描述列表的其余部分 (T),只是强制它的长度为 4。由于您的查询建立了原始列表长度的规则是5,这个规定是多余的。

您似乎想要定义test(L),这意味着L 是一个任意正整数列表。这通常使用 CLP(FD) 完成:

:- use_module(library(clpfd)).

test(X) :- X ins 1..10000.

这条规则表明X 是一个列表,其值在 1 到 10000 的范围内。生成长度为 5 的列表的适当查询是:

?- length(X, 5), test(X), label(X).
X = [1, 1, 1, 1, 1] ;
X = [1, 1, 1, 1, 2] ;
X = [1, 1, 1, 1, 3] ;
X = [1, 1, 1, 1, 4] ;
X = [1, 1, 1, 1, 5] ;
...

如果你想进一步限制它并说元素需要是唯一的,你可以使用all_different/1

test(X) :- X ins 1..10000, all_different(X).

?- length(X, 5), test(X), label(X).
X = [1, 2, 3, 4, 5] ;
X = [1, 2, 3, 4, 6] ;
X = [1, 2, 3, 4, 7] ;
X = [1, 2, 3, 4, 8] ;
X = [1, 2, 3, 4, 9] ;
X = [1, 2, 3, 4, 10] ;
...

【讨论】:

  • all_distinct/1 具有更强的传播能力,通常应该使用而不是 all_different/1,尽管我怀疑这在这种特殊情况下会有什么不同。
  • @Fatalize 谢谢你,好建议。我同意,在这个问题/答案场景中可能会让人毛骨悚然。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多