[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?
Thanks,
- 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