Reputation: 13
Lets say I'm looking for someones friends.
friend(mary, peter).
friend(mary, paul).
friend(mary, john).
friend(mary, justin).
friend(chris, peter).
friend(chris, paul).
friend(chris, conner).
friend(chris, louis).
friend(tyler, justin).
friend(tyler, lindsey).
friend(tyler, frank).
friend(tyler, paul).
friend(dan, justin).
friend(dan, conner).
friend(dan, frank).
friend(dan, peter).
In the above example I know that I can do something like
friend(X, paul).
which will tell me everyone paul is friends with
or also
findall(X, friend(X, paul), L).
which will return a list of everyone paul is friends with.
Let's say that I want to go a little bit deeper in my search and refine it. So let's say that I was to do
findall(X, friend(X, paul), A).
To get A to be a list of [mary, chris, tyler]. But then I wanted to further refine that search. I want to be able to put the list into the function (I know this isnt valid but this is my thought pattern for what I want to do) for something like
findall(A, friend(A, peter), B).
To get back just [mary, chris] this time. And then even FURTHER refine it to say
findall(B, friend(B, conner), C).
To finally conclude my search to find [chris]
Is this possible? Is there a better or even possible way to do this?
Upvotes: 1
Views: 69
Reputation: 476503
Given I understood it correctly, you want to generate a list of people that are friends with paul
, peter
and connor
. We can do that by "constructing" a goal that aims to satisfy the three conditions:
findall(F, (friend(F, paul), friend(F, peter), friend(F, conner)), L).
or another conjunction of conditions. These then give:
?- findall(F, (friend(F, paul)), L).
L = [mary, chris, tyler].
?- findall(F, (friend(F, paul), friend(F, peter)), L).
L = [mary, chris].
?- findall(F, (friend(F, paul), friend(F, peter), friend(F, conner)), L).
L = [chris].
member/2
in the goalOr we can also use two calls, and use member/2
to "emulate" an intersection like:
findall(F, friend(F, paul), L1),
findall(F, (member(F, L1), friend(F, peter)), L2).
here we thus use member/2
such that F2
only takes values from L1
(the result of the initial findall/3
), but I think the first way is cleaner and more self explaining: we want after all a list of F
s that are friends with paul
, and peter
, and conner
.
maplist/2
to obtain people that are friends with everybody in a listWe can also find the people that are friends with a list of people by using maplist/2
here:
findall(F, maplist(friend(F), [paul, peter, conner]), L).
We can also make two separate findall/3
calls, and then calculate the intersection:
findall(F, friend(F, paul), L1),
findall(F, friend(F, paul), L2),
intersection(L1, L2, M).
Here M
will thus contain the elements that are both in L1
and L2
. But a potential problem here is that the second predicate can generate a lot of results that were not possible with given we filtered with the values of the first predicate.
Upvotes: 1