[mercury-users] Passing a multi-mode higher order predicate

Jeff Thompson jeff at thefirst.org
Tue Feb 7 02:36:50 AEDT 2012

On 2/6/2012 12:03 AM, Julien Fischer wrote:
> On Sun, 5 Feb 2012, Jeff Thompson wrote:
>> On 2/5/2012 7:52 AM, Julien Fischer wrote:
>>> Hi,
>>> On Sat, 4 Feb 2012, Jeff Thompson wrote:
>>>> Hello again.  In the program below, the compiler gives the 
>>>> following error due to "test(list.member)".
>>>> test.m:010: In clause for `main(di, uo)':
>>>> test.m:010:   in argument 1 of call to predicate `test.test'/1:
>>>> test.m:010:   mode error: variable `V_6' has instantiatedness `free',
>>>> test.m:010:   expected instantiatedness was `(pred((ground >> 
>>>> ground), (ground
>>>> test.m:010: >> ground)) is semidet)'.
>>>> The predicate list.member exists with the correct mode, so why does 
>>>> the compiler say the argument is free?
>>> In general, the current Mercury implementation. does *not* support
>>> creating higher-order terms from multi-moded predicates.   See the
>>> ``Creating higher-order terms'' of the reference manual (section 8.1).
>>> (There is an exception to this in the case where the are some curried
>>> higher-order arguments, but that does not apply here.)   The compiler
>>> usually generates a more useful error message for this; I'm not sure
>>> why it doesn't in this case.
>> Thanks for the clarification.  I see that in the language reference 
>> manual now. I came across this because I am trying to convert a code 
>> base of Prolog to Mercury which deeply uses bagof in multiple modes. 
>> My example comes from the following use case where Prolog can easily 
>> handle the following code whether X is var or nonvar:
>> test(X, Bag) :- bagof(X, member(X, [1, 2]), Bag).
>> If X is ground, then it uses list.member(int::in, list(int)::in).  
>> But if it is nonvar, then it uses list.member(int::out, 
>> list(int)::in).   I cannot figure out an efficient way to duplicate 
>> bagof,
> What do you mean by duplicate bagof?  Do you mean implement it in
> Mecury?  What was wrong with the implementation you had that used
> unsorted_aggregate?

Yes, to implement in Mercury.  My implementation of bagof uses map where 
each call to map.set copies the whole map.  I looked but I can't find a 
version of map.set which is:
:- pred map.set(K::in, V::in, map(K, V)::di, map(K, V)::uo) is det.
where the map is destructively (and more efficiently) updated.  This 
would have to be supported internally by the compiler.  Does the library 
have something like this, or should I use the foreign language interface 
and implement it myself?

>> much less the case where there are multiple modes. I know Mercury
>> disputes the soundness of the semantics of bagof, but is there a paper
>> which describes how to achieve the same multi-mode behavior?
> Can't you just use mode-specific clauses?
> ... with bagof/3 itself, for example
>    bagof(X::in, Pred::in(pred(in, in) is semidet), Bag::out) :- ...
>    bagof(X::out, Pred::in(pred(out, in) is nondet), Bag::in) :- ...

This is precisely how I came across my recent question.  Suppose I want 
to call bagof inside the following predicate:
:- pred myTest(int, list(int)).
:- mode myTest(in, out) is semidet.
:- mode myTest(out, out) is nondet.
myTest(X, Xs) :- bagof(X, list.member, Xs).

As you point out, I can't just pass a multi-mode predicate of 
list.member like this.  Do I have to implement myTest for each mode just 
to pass the right mode of list.member?

- 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