简体   繁体   中英

Checking a relation of a prolog list element

Lets say I have a relations

Happy(james)
Happy(harry)
unhappy(Tom)
unhappy(Ben)
unhappy(Dick)

And then a list of people

[Ben, James, Harry, Tom, Dick]

How can I iterate the list and check the boolean of each list element as to whether they are happy or not?

Well, first of all, in Prolog, if a word starts with a capital letter, it means that it is a variable. So you should be careful with that.

This is my database after the correction:

happy(james).
happy(harry).
unhappy(tom).
unhappy(ben).
unhappy(dick).

and I added a recursive rule that helps me see who is happy and who is not from a given list:

emotion([]).
emotion([H|T]):- happy(H),emotion(T),
                 write(H),write(' is happy.'),
                 nl;
                 unhappy(H),emotion(T),
                 write(H),write(' is unhappy.'),
                 nl.

Here is the result:

4 ?- emotion([ben, james, harry, tom, dick]).
dick is unhappy.
tom is unhappy.
harry is happy.
james is happy.
ben is unhappy.
true.

Here is another approach to dealing with this task. This answer doesn't fuss with with IO, which is unnecessary here, and it goes into some detail about the strategy employed:

I'm working with the following facts:

happy(james).
happy(harry).
unhappy(tom).
unhappy(ben).
unhappy(dick).

people([ben, james, harry, tom, dick]).

Your desired end can be achieved with a simple predicate establishing a relationship between a name and the happy/1 and unhappy/1 predicates:

person_happiness(Person, happy(Person))   :- happy(Person).
person_happiness(Person, unhappy(Person)) :- unhappy(Person).

This person_happiness/2 exploits the homoiconic nature of Prolog. The instance of happy/1 appearing in the rule's body is a call to the predicate, and it is true just in case Person can be unified in a call to the fact happy/1 . The instance of happy/1 occurring in the second argument of person_happiness/2 functions as a data structure, and essentially works to label Person as happy. This second argument could be replaced with happy-Person , happy/Person , happy=Person , emotion(Person, happy) , and many other things besides.

With this predicate alone, we can generate a report of all the happy and unhappy people by backtracking over free variables:

?- person_happiness(Person, Happiness).
Person = james,
Happiness = happy(james) ;
Person = harry,
Happiness = happy(harry) ;
Person = tom,
Happiness = unhappy(tom) ;
Person = ben,
Happiness = unhappy(ben) ;
Person = dick,
Happiness = unhappy(dick).

We can also find the Happiness for a particular person:

?- person_happiness(dick, Happiness).
Happiness = unhappy(dick).

And we can find all the people who share a common quality:

?- person_happiness(Person, happy(Person)).
Person = james ;
Person = harry.

The queries above work just by consulting the facts happy/1 and unhappy/2 , but you want to check these facts against the names in your list. We can use member/2 in conjunction with person_happiness/2 to achieve everything you want with backtracking:

?- people(Ps), member(P, Ps), person_happiness(P, PH).
Ps = [ben, james, harry, tom, dick],
P = ben,
PH = unhappy(ben) ;
Ps = [ben, james, harry, tom, dick],
P = james,
PH = happy(james) ;
Ps = [ben, james, harry, tom, dick],
P = harry,
PH = happy(harry) ;
Ps = [ben, james, harry, tom, dick],
P = tom,
PH = unhappy(tom) ;
Ps = [ben, james, harry, tom, dick],
P = dick,
PH = unhappy(dick).

To get all of these results in one go, we can use maplist/3 to apply person_happiness/2 to each member of the People in people(People) :

?- people(People), maplist(person_happiness, People, PeopleHappiness).
People = [ben, james, harry, tom, dick],
PeopleHappiness = [unhappy(ben), happy(james), happy(harry), unhappy(tom), unhappy(dick)] 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM