我有一套事实:
likes(john,mary).
likes(mary,robert).
likes(robert,kate).
likes(alan,george).
likes(alan,mary).
likes(george,mary).
likes(harry,mary).
likes(john,alan).
现在我想写一个关系,如果likes(X,A)
为真,它将检查输入列表的所有元素X.如果likes(X,A)
对于列表L中的所有元素X都为真,则我的关系应返回true。
如果我试试这个:
relat(X) :- member(A,[john,alan,george,harry]), likes(A,X).
但输出是
?- relat(mary).
true ;
true ;
true ;
true.
我想写它,一旦发现likes(john,mary),likes(alan,mary),likes(george,mary),likes(harry,mary)
都是真的,它就会返回一个真值。
如何解决这个问题?
答案 0 :(得分:5)
在SWI-Prolog中,您可以使用forall/2
:
?- forall(member(A, [john, alan, george, harry]), likes(A, mary)).
true.
?- forall(member(A, [john,alan,george,harry,marys_ex]), likes(A, mary)).
false.
答案 1 :(得分:2)
使用library(lambda)
:
liked_byall(X, Ps) :-
maplist(X+\P^likes(P,X), Ps).
同样没有lambdas:
liked_byall(X, Ps) :-
maplist(liked(X), Ps).
liked(X, P) :-
likes(P, X).
同样:
liked_byall(_X, []).
liked_byall(X, [P|Ps]) :-
likes(P, X),
liked_byall(X, Ps).
根据上述定义,您可以提出更为一般性的问题,例如"某些人喜欢谁?"
?- liked_byall(N,[john, alan, george, harry]).
N = mary ;
false.
通过以下定义,这些一般性问题不再可能。
liked_byall(X, Ps) :-
\+ ( member(P, Ps), \+ likes(P, X) ).
如果X
是基础且Ps
是地面列表,则第二个定义才有意义。我们可以按如下方式确保:
liked_byall(X, Ps) :-
( ground(X+Ps) -> true ; throw(error(instantiation_error,_)) ),
length(Ps,_),
\+ ( member(P, Ps), \+ likes(P, X) ).
这些额外的检查确保了以下荒谬案例不成功:
?- liked_byall(mary, nonlist).
其他合法案件不会产生错误答案:
?- liked_byall(N,[john, alan, george, harry]), N = the_grinch.
N = the_grinch.
答案 2 :(得分:2)
使用标准列表处理,您可以执行以下操作:
helper(X, []). % No one left to check
helper(X, [H|L]) :- likes(H, X), helper(X, L). % Check head, then rest
relat(X) :- helper(X, [john,alan,george,harry]).
演示:
| ?- relat(harry).
no
| ?- relat(mary).
true ? ;
no
| ?-