答案 0 :(得分:3)
让我们首先单独考虑该条款的单一目标:
?- append([H|T], _, L).
这是什么意思?使用纯Prolog代码,有一种方便的方式可以更多地了解关系:只需在查询上发布查询,看看解决方案是什么样的。
试一试!例如:
?- append([H|T], _, L). L = [H|_1282], T = [] ; L = [H, _1078|_1096], T = [_1078] ; L = [H, _1078, _1084|_1108], T = [_1078, _1084] ; L = [H, _1078, _1084, _1090|_1120], T = [_1078, _1084, _1090] ; etc.
由此我们看到append/3
的这个调用定义了它的参数之间的关系,我们看到了以下模式:
L
总是包含:
H
作为第一个元素T
这并不令人惊讶,因为这正是append([H|Ts], _, Ls)
的含义:[H|Ts]
后跟任何列表构成列表Ls
。
在您的具体用例中,L
显然是实例化,因此后缀不能任意长。
例如:
?- append([H|T], _, [a,b,c]). H = a, T = [] ; H = a, T = [b] ; H = a, T = [b, c] ; false.
所以我们看到了整个子句的含义(我已经重命名了变量,以便列表在变量名中用后缀 s 表示):
powerset(Ls, [H|Ts]):- append([H|Ts], _, Ls).
如果 Ls
是一个列表,其中包含第一个元素H
,后跟元素Ts
,后跟任何内容,然后列表[H|Ts]
是L
的powerset的成员。
非正式:
列表中的每个非空前缀都是powerset的成员。
从这一点我们也看到了powerset/2
的明显遗漏,因为它出现在这个帖子中:没有一个条款产生空集作为powerset的成员,甚至更多令人不安的是,他们都没有接受空集作为有效集,因此以下错误失败:
?- powerset([], _). false. % empty set is not a set?
练习:纠正powerset/2
,以便它实际上对于powerset的所有元素都成功。