假设我有一个序言谓词,例如:

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的参数被完全忽略!

10-06 10:47