Prolog成员名单

时间:2014-05-05 13:01:32

标签: prolog

Prolog新手在这里谁想知道为什么这些规则不能自立,如果我想知道某些东西是否是列表的成员。

member(X, [X|_]).

member(X, [_|Y]) :- member(X,Y).

如果我要求以下规则:

member(will, [anna, eddie, pat, will, marjorie, donna]).

我知道,但如果我删除:

member(X, [X|_]).

刚离开第二条规则,我就是假的。如果第二条规则规定“如果X是列表尾部的成员,则X是列表的成员”,为什么会这样呢?

“will”是此列表尾部的成员。

而且,为什么可以

member(X, [X|_]).
单独告诉我什么时候X是列表的头部(第二个规则不能)?

谢谢。

3 个答案:

答案 0 :(得分:5)

如果您只有member(X, [X|_]).并执行此查询:member(will, [will,anna]).

您将获得true.,因为根据您的规则,X将是列表的头部。

但是如果你只有那条规则并执行member(anna, [will,anna]).,那么你就会得到错误,因为安娜不是你名单的负责人。

让我们看看你的第二条规则。

您将程序创建为member(X, [_|Y]) :- member(X,Y).

您执行查询member(will, [anna, eddie, pat, will, marjorie, donna]).

这就是Prolog看到的:

获取列表并移除头部。对列表的其余部分执行相同操作,直到尾部为空。

您获得false.,因为列表中没有任何元素。

您的问题是您不会检查X是否是您列表的成员。您也可以将该规则重命名为removehead(X,[_|Y]):-removehead(X,Y).

答案 1 :(得分:4)

  

刚离开第二条规则,我就错了。

没有基本情况的规则失败的原因是,当列表归结为单个项目时,当列表变空时,没有规则与其右侧统一。

您可以使用较短的列表在一张纸上播放:

  • member(will, [anna, will])开始。
  • 这与规则统一,将anna统一到_,并将[will]保持在Y
  • 这会再次与规则统一,将will统一到_并将[]保持在Y
  • 现在,Prolog尝试member(will, [])规则不再与其统一,因为member(X, [_|Y])要求第二个参数是至少包含一个项目的列表。
  • 一旦最后一次统一失败,失败就会向上传播,导致false返回顶层调用者。
  

而且,为什么member(X, [X|_]).可以独立并告诉我什么时候X是列表的头部

这是因为规则立即成功,而不必与右边的任何其他规则统一。

通常,当您处理数据结构的递归处理时,您需要寻找两件事:

  • 基本情况,它告诉我们在最简单的情况下做什么,或者当递归数据结构简化为退化情况时(例如空列表,单节点“叶子”)树,等等。)
  • 还原步骤,它说明如何使问题更接近基本案例。

单独处理基础案例有时会给你带来结果;单独处理还原步骤永远不会给你正确的结果,因为它可以做所有的还原工作。

答案 2 :(得分:2)

member(X, [_|Y])(1)仅匹配[_|Y]形式的列表,(2)从不查看实际元素。尝试跟踪执行:

?- trace.
true.

[trace]  ?- member(foo, [foo, bar]).
   Call: (6) member(foo, [foo, bar]) ? creep
   Call: (7) member(foo, [bar]) ? creep
   Call: (8) member(foo, []) ? creep
   Fail: (8) member(foo, []) ? creep
   Fail: (7) member(foo, [bar]) ? creep
   Fail: (6) member(foo, [foo, bar]) ? creep
false.

正如预期的那样,你的member版本只是跳过元素,因为它只想看尾部,直到它碰到[],与头部的模式不匹配。

另一个版本member(X, [X|_])可以匹配每个定义的头。它会查看头部并将其与您正在寻找的项目统一起来。