Search code examples
prologprolog-setof

existential qualifier in prolog, using setof / bagof


I had a quick question re. existential qualifier using setof in prolog (i.e. ^).

using SICStus it seems that (despite what a number of websites claim), S does indeed appear to be quantified in the code below (using the bog standard, mother of / child of facts, which i havent included here):

child(M,F,C) :- setof(X,(mother(S,X)),C).

i check the unification using:

child(M,F,C) :- setof(X-S,(mother(S,X)),C).

so the following code, with the existential operator seem to make no difference:

child(M,F,C) :- setof(X,S^(mother(S,X)),C).

Any ideas why this is? What would be a situation where you would need the unifier then?

thanks!


Solution

  • Ok, I'm not sure I can explain it perfectly, but let me try.

    It has to do with the fact that you are querying over a 2-ary relation, mother/2. In that case using X-S as the template has a similar effect on the result set C as using S^ in front of the goal. In X-S you are using both variables in the template, and therefore each possible binding of X and S is included in C. You get the same effect using S^ in front of the goal, as this is saying "ignore bindings of S when constructing the result".

    But the difference between the two becomes clearer when you query over a 3-ary relation. The SWI manual has this example:

    foo(a, b, c).
    foo(a, b, d).
    foo(b, c, e).
    foo(b, c, f).
    foo(c, c, g).
    

    Now do similar queries as in your example

    setof(X-Z, foo(X,Y,Z), C).
    

    and

    setof(Z, X^foo(X,Y,Z), C).
    

    and you get different results.

    It's not just checking unification, X-Z effectively changes your result set.

    Hope that helps.

    Edit: Maybe it clarifies things when I include the results of the two queries above. The first one goes like this:

    ?- setof(X-Z, foo(X,Y,Z), C).   
    Y = b
    C = [a-c, a-d] ;
    Y = c
    C = [b-e, b-f, c-g] ;
    No
    

    The second one yields:

    ?- setof(Z, X^foo(X,Y,Z), C).
    Y = b
    C = [c, d] ;
    Y = c
    C = [e, f, g] ;
    No