假设我有一个序言谓词,例如:
name(music,[jazz,blues,classical]).
我想要检查的是爵士乐的成员(member)资格,如果在音乐方面还可以归还我本人?
到目前为止,我做到了:
ismember(X,Y):-imember(X,name(Y,Z)),write(Z).
imember(X,[_|Tail]):-imember(X,Tail).
imember(X,[X|_]).
但这不起作用。
?- ismember(jazz,music).
false.
而且它不是在编写
write(Z)
部分。 最佳答案
在以下片段的可见部分中有一个错误。不仅程序会失败,而且以下一般化也会失败:
:-op(950,fy,*)。
*(_)。
ismember(X,Y):-
imember(_ / * X * /,name(_ / * Y * /,Z))。
imember(X,[_ | Tail]):-
* imember(X,Tail)。
imember(X,[_ / * X * / | _])。
?-ismember(X,Y)。
通过用_
替换一些变量,并通过用*
删除一个目标,可以实现这种概括。它尽可能地概括。也就是说,任何进一步的概括将使目标成功。在(纯净的,单调的)Prolog中有一个不错的属性:
如果泛化失败(针对特定查询),那么原始程序也会失败(针对同一查询)。
这是一个不错的属性,可以通过某种方式在广义片段和原始程序之间建立因果关系。如果要消除错误,则必须更改通用程序中的某些内容。或反之:如果您进行允许仍然进行概括的更改,则您尚未解决该错误。
考虑到这一点,当搜索这样的片段时,不需要“理解”实际程序。只要可能,就可以不加思索地猜测和概括。
现在,如果我们看一下概括,请注意ismember/2
的参数被完全忽略!