1

This is a somewhat silly example but I'm trying to keep the concept pretty basic for better understanding. Say I have the following unary relations:

person(steve). 
person(joe). 

fruit(apples).
fruit(pears).
fruit(mangos).

And the following binary relations:

eats(steve, apples).
eats(steve, pears).
eats(joe, mangos).

I know that querying eats(steve, F). will return all the fruit that steve eats (apples and pears). My problem is that I want to get all of the fruits that Steve doesn't eat. I know that this: \+eats(steve,F) will just return "no" because F can't be bound to an infinite number of possibilities, however I would like it to return mangos, as that's the only existing fruit possibility that steve doesn't eat. Is there a way to write this that would produce the desired result?

I tried this but no luck here either: \+eats(steve,F), fruit(F).

If a better title is appropriate for this question I would appreciate any input.

fia928
  • 143
  • 3
  • 10

1 Answers1

2

Prolog provides only a very crude form of negation, in fact, (\+)/1 means simply "not provable at this point in time of the execution". So you have to take into account the exact moment when (\+)/1 is executed. In your particular case, there is an easy way out:

fruit(F), \+eats(steve,F).

In the general case, however, this is far from being fixed easily. Think of \+ X = Y, see this answer.

Another issue is that negation, even if used properly, will introduce non-monotonic properties into your program: By adding further facts for eats/2 less might be deduced. So unless you really want this (as in this example where it does make sense), avoid the construct.

Community
  • 1
  • 1
false
  • 10,264
  • 13
  • 101
  • 209
  • Thank you for your response. In a basic example like this, would it be possible to store this logic in a rule and then call that rule? For instance, "doesnt_eat(P) :- fruit(F), \+eats(P,F)." Then if I call it with "doesn't_eat(steve).", it just returns true rather than the desired "mangos." – fia928 Mar 12 '15 at 21:56
  • 1
    You would need `doesnt_eat(P,F) :- ...`. If you have a one-argument relation as you suggest, the name `person_that_does_not_eat_some_fruit/1` would be more appropriate. – false Mar 12 '15 at 22:02
  • 1
    And: ideally, your definition would be `doesnt_eat(P, F) :- person(P), fruit(F), \+eats(P,F).` so you can ask "Who does not eat mango?": `doesnt_eat(P,mango)` – false Mar 12 '15 at 22:03