正确使用findall / 3,尤其是最后的结果参数

时间:2014-06-18 15:17:45

标签: variables prolog singleton prolog-setof prolog-findall

我是Prolog的初学者,我正在处理一个看起来很愚蠢的问题,但我真的无法理解我做错了什么!好的,我有这个文件fruits.pl,里面有我这样的东西:

fruit(apple,small,sweet).
fruit(lemon,small,nosweet).
fruit(melon,big,sweet).

我已经(在该文件中创建了一个共存(X,Y)原子,检查两个水果是否可以放在盘子里。它工作正常!但现在我无法创建一个建议(X)将水果作为参数并返回可以放在同一个盘子中的水果列表。 问题是我试图做出类似的东西

suggest(X) :- findall(Y,fruit(Y,_,_), List), coexist(X,Y).
你怎么看?每当我尝试在swi prolog中运行它时,都会出现一个警告单例变量'当我按下

suggest(apple).

然后说错误.. 对不起我的英文:/

2 个答案:

答案 0 :(得分:3)

Prolog中的谓词不会返回任何内容。您的目标是否满意,您可以将其解释为返回truefalse

您的谓词suggest(X)应该包含另一个参数,该参数将绑定到与X一起的水果列表。选项可以是:suggest(X, List),它描述了以下关系:List表示与X一起出现的所有成果。然后,你可以问:

?- suggest(apple, List).
List = [pear, cherry].

目标findall(Y, ... , ...)在内部使用Y变量,Y在目标满足后仍未绑定。因此,您应该将coexist(X,Y)移到findall/3的第二个参数内,这是以所有可能的方式满足的目标。以下规则仅在X实例化时才有效(<{1}})。

suggest(+X, -List)

您可以按照以下方式阅读:“suggest(X, List) :- findall(Y, (fruit(Y,_,_), coexist(X, Y)), List). 代表与List共存的所有水果Y。”

答案 1 :(得分:2)

当您尝试在Prolog中定义谓词时,首先假装您已经编写了该谓词,并从想象如何使用它开始。也就是说,您想要提出什么样的问题。

对我来说,好像coexist/2已经描述了你想要的东西。顺便说一下,may_coexist/2可能是一个更具描述性的名称。你为什么要把它放在一个单独的列表中?为什么要使用fruit/3呢?但是为了这个问题,让我们假设这是有道理的。所以基本上你现在有一个关系fruit_compatible/2

fruit_compatible(F, G) :-
   fruit(F, _, _),
   may_coexist(F, G),
   fruit(G, _, _).  % maybe you want to add this?

现在,让我们假设您也想要这个列表。所以你会有一个关系fruit_suggestions/2。怎么用?

?- fruit_suggestions(apple, L).
L = [cherry, pear].

或......应该是L = [pear, cherry]吗?或两者兼而有之?

?- fruit_suggestions(lemon, L).
L = [orange].

所以每当我想要一个建议时,我都要想到一个水果。一直在想:应该是什么水果?幸运的是,在Prolog中有一种要求不高的方式:只需使用变量而不是水果!现在我们应该立刻得到所有建议!

?- fruit_suggestions(F, L).
F = apple, L = [cherry, pear] ;
F = lemon, L = [orange] ;
F = cromulon, L = [embiggy, mushfruit].

所以我们需要实现它,以便它会以这种方式运行。仅findall/3并不能解决这个问题。手动实现它远非微不足道。但是setof/3以完全相同的方式处理变量。许多微小的细节设计决策已经完成,就像列表将按升序排序一样。

fruit_suggestions(F, L) :-
   setof(G, fruit_compatible(F, G), L).

编辑:由于下面的讨论,这里将是一个允许空列表的解决方案。请注意,这听起来微不足道,但事实并非如此。要查看此内容,请考虑以下问题:

?- fruit_suggestions(F, []).

这是什么意思? F应该是什么?还有什么东西都没结果?在这种情况下,我们必须为所有生成解决方案。像F = badger ; F = 42 ; ...一样。最有可能这没有多大意义。可能意图是那些与一切都不相容的水果。为此,我们需要添加一条新规则:

fruit_suggestions(F, []) :-
   setof(t,X^Y^fruit(F,X,Y),_),
   \+ fruit_compatible(F, _).
fruit_suggestions(F, L) :-
   setof(G, fruit_compatible(F, G), L).