[mercury-users] Equivalent of Prolog setof with free variable

Jeff Thompson jeff at thefirst.org
Thu Jan 26 14:48:32 AEDT 2012


On 1/25/2012 7:53 AM, Julien Fischer wrote:
>
> Hi,
>
> On Tue, 24 Jan 2012, Jeff Thompson wrote:
>
>> Hello.  What is the preferred way in Mercury to implement the 
>> equivalent of setof with a free variable.  For example, Prolog:
>>
>> person(bob, accounting).
>> person(alice, accounting).
>> person(fred, sales).
>>
>> departmentMembers(Department, People) :-
>>  setof(Person, person(Person, Department), People).
>>
>> Calling departmentMembers returns multiple times with results for the 
>> free variable:
>> Department = accounting,
>> People = [alice, bob] ;
>>
>> Department = sales,
>> People = [fred].
>>
>> What is the preferred way to get this in Mercury?
>
> As Michael has mentioned, you will need to use the all-solutions
> predicates from the standard library's solutions module.
>
> A possible Mercury implementation of the above is:
>
>     :- module foo.
>     :- interface.
>     :- pred main(io::di, io::uo) is det.
>     :- implementation.
>
>     :- import_module list.
>     :- import_module set.
>     :- import_module solutions.
>     :- import_module string.
>
>     :- type person ---> alice ; bob ; fred.
>
>     :- type department ---> accounting ; sales.
>
>     :- pred departmentMembers({department, list(person)}::out) is multi.
>
>     departmentMembers({Department, People}) :-
>        person(_, Department),
>        solutions((pred(P::out) is multi :- person(P, Department)), 
> People).
>
>     :- pred person(person, department).
>     :- mode person(out, in) is multi.
>     :- mode person(out, out) is multi.
>
>     person(bob, accounting).
>     person(alice, accounting).
>     person(fred, sales).
>
> And since Mercury doesn't have an interactive top-level:
>
>     main(!IO) :-
>         solutions(departmentMembers, Solns),
>         io.write_list(Solns, "\n\n", output_soln, !IO),
>         io.nl(!IO).
>
>     :- pred output_soln({department, list(person)}::in, io::di, 
> io::uo) is det.
>
>     output_soln({Department, People}, !IO) :-
>         io.format("Department = %s,\nPeople = %s",
>         [s(string(Department)), s(string(People))], !IO).
>
> Julien.

Thanks for the detailed example.  Changing solutions in main to 
unsorted_solutions, here is the output:
Department = sales,
People = [fred]

Department = accounting,
People = [alice, bob]

Department = accounting,
People = [alice, bob]

This shows that departmentMembers computes person four times.  The first 
time to scan for three Department answers (accounting twice), and then 
three times for each Department answer.  An efficient Prolog solutions 
only computes the predicated once and accumulates results. I can guess 
at how to do this with accumulator predicates in solutions, but is there 
a typical or preferred way to do it?

Thanks for the help,
- Jeff




--------------------------------------------------------------------------
mercury-users mailing list
Post messages to:       mercury-users at csse.unimelb.edu.au
Administrative Queries: owner-mercury-users at csse.unimelb.edu.au
Subscriptions:          mercury-users-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the users mailing list