[mercury-users] Getting 'any' insts to ground

Fergus Henderson fjh at cs.mu.oz.au
Sat Nov 15 01:57:37 AEDT 1997

Bas de Bakker wrote:
> The solution seems to be to have a get_val/2 predicate with a mode
> that is actually declared as multi (but still operationally aborts
> when called with a non-ground argument), but I don't know how to
> implement this as it seems to require creating a 'multi' procedure in
> C.
> % cheated_is_ground is only used as a helper in get_value/2 below.
> % It is cheated, because I've declared it as multi, while it isn't.

Yes, this is cheating.  If you declare it multi, then on backtracking
is should return the other solution, but your implementation doesn't.

(This contrasts with get_val/2, which is fine, even though it is
declared as multi and only returns one solution.  Declaratively
get_val/2 it is multi.  Operationally it happens to return only one
solution, and aborts in cases where multiple solutions would be
required.  That is OK: aborting is not cheating, it is just giving up.)

Using the C interface to implement a `multi' procedure is also cheating.
The Mercury language reference manual specifically rules it out:

    | If there is a `pragma c_code' declaration for a mode of a predicate
    | or function, then that mode of the predicate may not have determinism
    | `multi' or `nondet' [...]

It is as you say just luck (indeed, arguably a bug) that the existing
implementation does not enforce that rule in this case.

The current implementation happens to treat `pragma c_code' declarations
in a similar manner to clauses; you can have multiple c_code pragmas 
for each procedure, and the result will be equivalent to a disjunction
of the different c_code pragmas.  This doesn't really help you in
general, which is why the documentation disallows this case.

We have done a preliminary design for extending the language to support
a more useful way of defining `nondet' or `multi' predicates in C, but
this has not been high on our list of priorities.  One reason that it
hasn't been a high priority is that it is possible to achieve the same
effect using existing language features -- for example, you can define
a det predicate or function in C that returns a lazy list of solutions,
and then you can call a nondet lazy_list_member/2 predicate to
nondeterministically select a solution.  (Lazy lists can be defined
using Mercury's higher-order features.)

You could I guess avoid cheating by implementing get_value/2 directly
in C.  Maybe that would still be "cheating" in a sense, but you
would not be lying to the compiler.

I think it is fair to say that `any' insts are still a fairly
experimental feature of Mercury -- there are still a few things
we need to iron out.

Fergus Henderson <fjh at cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh at         |     -- the last words of T. S. Garp.

More information about the users mailing list