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

Julian Fondren ayrnieu at gmail.com
Sun Feb 5 18:46:39 AEDT 2012


On Sat, Feb 4, 2012 at 11:51 PM, Jeff Thompson <jeff at thefirst.org> 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?
>
> :- module test.
> :- interface.
> :- import_module io.
> :- pred main(io__state::di, io__state::uo) is cc_multi.

io__state = io.state = io.io; and as you used 'import_module' rather
than 'use_module', io.io = io.  So,

  :- pred main(io::di, io::uo) is cc_multi.

> :- implementation.
> :- import_module int, list.
>
> main(!IO) :-
>  if test(list.member) then io.write_string("yes", !IO) else
> io.write_string("no", !IO).

> :- pred test(pred(int, list(int))).
> :- mode test(pred(in, in) is semidet) is semidet.

OK, given test(X), we know that X is a semidet predicate that accepts an
int and a list of ints.  But, er, what is the mode of X?  i.e., does
test produce X?  Is X bound to such a predicate by test(X)?  Or does it
accept an X, perhaps failing when you give it the wrong X?  Your :- mode
line should answer this basic question, but it doesn't.  (Or rather, it
answers it in a very odd way, which you can see in your error
message.)

>From section 8.3 of the Mercury Language Reference, Higher-order modes:

 If you want to define a predicate which returns a higher-order
 predicate term, you would use a mode such as `free >> pred(...) is
 ...', or `out(pred(...) is ... )'.  For example:

erm, I'll give my own example:

  :- pred foo(pred(int)).
  :- mode foo(free >> (pred(out) is multi)) is det.
  foo(numbers).

  :- pred numbers(int::out) is det.
  numbers(1).
  numbers(2).
  numbers(3).

That could be written:

  :- type producer(T) == pred(T).
  :- inst producer == (pred(out) is multi).

  :- pred foo(producer::out(producer)) is det.
  foo(numbers).

Cheers,
Julian
--------------------------------------------------------------------------
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