【发布时间】:2013-06-19 09:58:10
【问题描述】:
在 Prolog 中,我经常通过提供模板(包含变量的结构)然后满足一组约束来解决问题。一个简单的例子可能是:
go(T) :-
T = [_, _, _],
member(cat, T),
member(dog, T),
member(mouse, T).
实际上,约束集是通过其他方式生成的,而不是固定的,我必须编写一个递归谓词来依次满足每个约束:
go(T) :-
T = [_, _, _],
findall(A, animal(A), As),
% satisy member(A, T) for each A in As
fill_in_animals(T, As)
fill_in_animals(T, []).
fill_in_animals(T, [A|Rest]) :-
member(A, T),
fill_in_animals(T, Rest).
请注意,我的问题与列表相关的约束无关,甚至约束的参数也不能总是很容易地生成为要传递给上面使用的相对简单的辅助谓词的列表。在实践中,我发现 helper 是一个我每次都写的相当笨拙的谓词,它:
- 接受一个模板、几个用于约束的参数(因此用于将模板的变量绑定到有用的值),以及一个用于指示它受哪个约束的变量。
- 生成要在此迭代中满足的约束,并将其应用于模板。
- 递归调用自身,以便满足剩余的约束。
我正在寻找的是一个类似于findall 等的谓词,它将一个接一个地满足一组目标。比如:
% satisfyall(:Goal)
% backtracks on Goal but keeps all bindings from each fully satisfied goal.
satisfyall((animal(A), member(A, T)))
我正在寻找的答案不一定是这种形式。事实上,在回溯一个目标和维护由此产生的每组绑定之间可能存在矛盾。
我希望我已经解释了我的问题,以便清楚地知道什么会有所帮助。 (如果不让我知道。)提前为这个冗长的问题道歉!
更新(2 年后)
我将在今天晚些时候尝试并更新我的问题!
请注意,我从未说过我会在尝试的同一天更新问题。 ;-)
@CapelliC 将我引向了正确的方向,我发现了一种似乎运作良好的模式:
?- Gs = [member(red),member(blue)], T = [_,_], foreach(member(G, Gs), call(G, T)).
T = [red, blue] ;
T = [blue, red] ;
【问题讨论】:
-
lambda.pl 可能会有所帮助,但我认为您应该选择 findall/3
-
lambda 没有随 SWI 分发有什么特别的原因吗?我很想能够
use_module(library(lambda))! -
@DanielLyons:当我试图回答同样的问题时,我得到了一些反对意见 :)
-
我可能对这个问题读得太多了,但它似乎涉及两个有趣的想法。一种是使用部分绑定的结构(您的模板)来表达单个约束的结果。另一个是包装器,它对参数化的约束序列执行for all量化,以串行方式应用于部分绑定的结构。
-
apply(G,[T])完全过时了!请改用call(G,T)。
标签: prolog