在 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
, etc 的谓词,它将一个接一个地满足一组目标。就像是:
% 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] ;