[mercury-users] cc_multi question

Fergus Henderson fjh at cs.mu.OZ.AU
Sat Nov 30 12:23:33 AEDT 2002


On 29-Nov-2002, Peter Ross <peter.ross at miscrit.be> wrote:
> Below is some code abstracted from the RTTI stuff that I am doing.
> (q = deconstruct) and (p = limited_deconstruct).  It was originally coded
> all coded up in C, so no Mercury compiler to make happy.  However with the
> mercury implementation I get the following error.  Can anyone help me on
> what the correct solution is?
> 
> The only thing I can think of is to use promise_only_solution, but that just
> doesn't feel right to me.
> 
> 
> % main.m:018: Error: call to predicate `main:q/2' with determinism `cc_multi'
> % main.m:018:   occurs in a context which requires all solutions.
> % For more information, try recompiling with `-E'.
> :- module main.
> 
> :- interface.
> 
> :- type t
> 	--->	f(int)
> 	;	g(int).
> 
> :- pred p(int::in, int::out) is cc_nondet.
> 
> :- implementation.
> 
> :- import_module int.
> 
> p(A, B) :-
> 	q(f(A), B),
> 	B < 5.
> 
> :- pred q(t::in, int::out) is cc_multi.
> 
> q(f(A), A).
> q(f(A), A+1).
> q(g(B), B).

In this case, there is a simple solution: add another mode for q
which has determinism `multi' rather than `cc_multi':

	:- pred q(t, int).
	:- mode q(in, out) is cc_multi.
	:- mode q(in, out) is multi.

If you want the same semantics as the original code, that's basically
the only solution.

In cases where the procedure q/2 that you are calling cannot feasibly
be implemented in a way that returns all possible solutions
(as is the case e.g. for `deconstruct' in the standard library
when called for a type with user-defined equality),
then there is no way to implement the declarative semantics specified
by the clauses for p/2.  If what you want is something that is
equivalent to what p/2 would do operationally, then you need to
change the interface to p/2 to return a `maybe'.

For example:

	:- pred p(int::in, maybe(int)::out) is cc_multi.
	p(A, R) :-
		q(f(A), B),
		( B < 5 ->
			R = yes(B)
		;
			R = no
		).

The consequence of this with regard to your original problem
(deconstruct and limited_deconstruct) is that there is an
interface design error in the definition of limited_deconstruct
and a few other procedures defined with determinism cc_nondet
in the Mercury standard library.
We will need to change the interface of limited_deconstruct_cc
in std_util.m and drop the cc_nondet modes of limited_deconstruct,
arg, and det_arg in deconstruct.m.  The current implementation
of those procedures in C code does not satisfy referential
transparency -- they will produce different results even for
inputs that are equal (but that have different representations).

In general, code which uses committed choice nondeterminism will
normally need to use `cc_multi' rather than `cc_nondet'.
`cc_nondet' can only be used in cases where the code which might
fail gets called *before* any code which needs committed choice
nondeterminism.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list