5

这是第一个观察结果:

?- is_list([]), is_list([_,_,_]).
true.

这是另一个观察结果:

?- [] = _, [_,_,_] = _.
true.

因此,为什么会is_list/1这样实施

?- is_list(_).
false.

或者

?- is_list([_|_]).
false.

什么时候_可以明确统一一个list?这在逻辑上不是更合理true吗?

SWI-Prolog 的文档中is_list/1,有一条注释说: 

在 5.0.1 之前的版本中,is_list/1只需检查[]or[_|_]proper_list/1具有当前is_list/1. 目前的定义符合事实上的标准。

为什么这是事实上的标准?

4

1 回答 1

6

正如您正确观察到的那样,is_list/1它是不健全的,或者说是不完整的,因为它错误地表示在提出最一般的查询时没有任何解决方案。

?- is_list(Ls)。
错误的。

不存在列表?来吧!

这种不幸的特征是所有遗传类型检查谓词(如 等)所共有的atom/1integer/1 当这些谓词被构想时,其不正确性已经很明显,但在将那些正确反对其建议语义的人标记为“纯粹主义者”(当时缺乏这个词已经获得的互补字符)。

像这样的案例:

?- is_list(Ls), Ls = []。
错误的。

?- Ls = [], is_list(Ls)。
LS = []。

清楚地表明,从逻辑的角度来看,这种非单调测试从根本上破坏了某些东西。“Prolog(,)/2不是逻辑连接”,是的,如果您首先在代码中使用不合逻辑的谓词。否则,(,)/2总是目标的逻辑结合。

一个干净且逻辑正确的出路是在无法确定的情况下抛出实例化错误。

library(error)尤其是must_be/2在继承的不合逻辑谓词的不正确性变得难以忍受之后,即使对于 Prolog 的普通用户来说,也要朝着正确的方向前进:

?- must_be(列表,X)。
参数没有充分实例化

?- must_be(列表,[_|_])。
参数没有充分实例化

?- must_be(list, [a,b,c])。
真的。

must_be/2易于使用,是迈向更正确逻辑程序的良好第一步。其他构造也出现在地平线上,我希望其他人评论当前状态。

现在来看实际的措辞:撇开上面概述的基本问题不谈,SWI 文档中提到的争论是检查最外层函子是否足以将术语视为列表,或者列表是否实际上必须符合归纳定义一个列表,即:

  • 原子[]是一个列表。
  • 如果Ls是一个列表,那么'.'(_, Ls)就是一个列表。

请注意,在最近的 SWI 版本中,[]它甚至不是一个原子,所以它再次打破了这个概念。

于 2016-07-01T14:31:16.247 回答