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

Julien Fischer juliensf at csse.unimelb.edu.au
Wed Feb 8 15:04:56 AEDT 2012


On Mon, 6 Feb 2012, Jeff Thompson wrote:

> 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.

Each call to map.set will *not* copy the whole map.  Umodified portions
of the underlying 234-tree will be shared between the old and new
versions of the 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.

The procedures in the map module (and many others) do not have unique
modes because limitations in the current mode checker mean that they
would be more trouble than they are worth.

> 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?

Unless, there is actually a demonstrable performance problem with maps
then I wouldn't worry about it.  If there is, you could try using the
stdlib's hash_table type (which is destructively updated).

>>> 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?

Yes.

Julien.
--------------------------------------------------------------------------
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