[mercury-users] determinism suprises

Fergus Henderson fjh at cs.mu.OZ.AU
Sat Dec 9 20:20:36 AEDT 2000


On 07-Dec-2000, William Lee Irwin III <wli at holomorphy.com> wrote:

> Another "catch" I found was the following:
> 
> :- pred color(squareindex, color).
> :- mode color(in, out) is det.
> :- mode color(in, in) is semidet.
> :- mode color(out, in) is multi.
> color({File, Rank}, Color) :-
>    file_parity(File, FileParity),
>    rank_parity(Rank, RankParity),
>    add_parity(FileParity, RankParity, Residue),
>    parity_to_color(Residue, Color).
> 
> Now, file_parity, rank_parity, and parity_to_color have all the
> necessary modes and determinisms to allow all of color's modes and
> determinisms given the appropriate ordering of conjunctions, but I
> still found that the reordering was not done for each mode:
> 
> board.m:018: In `color(out, in)':
> board.m:018:   error: determinism declaration not satisfied.
> board.m:018:   Declared `multi', inferred `nondet'.
> board.m:167:   call to `parity_to_color(in, in)' can fail.
> 
> So I tried to reorder the conjunction as follows:
> 
> color({File, Rank}, Color) :-
>     parity_to_color(Residue, Color),
>     add_parity(FileParity, RankParity, Residue),
>     file_parity(File, FileParity),
>     rank_parity(Rank, RankParity).
> 
> but this runs into the following error:
> board.m:016: In `color(in, out)':
> board.m:016:   error: determinism declaration not satisfied.
> board.m:016:   Declared `det', inferred `nondet'.
> board.m:164:   call to `parity_to_color(out, out)' can succeed more than once.
> board.m:165:   call to `add_parity(out, out, in)' can succeed more than once.
> board.m:166:   call to `file_parity(in, in)' can fail.
> board.m:167:   call to `rank_parity(in, in)' can fail.

and then in a subsequence mail

> :- pred add_parity(parity, parity, parity).
> :- mode add_parity(in, in, out) is det.
> :- mode add_parity(in, out, in) is det.
> :- mode add_parity(out, in, in) is det.
> :- mode add_parity(in, in, in) is semidet.
> :- mode add_parity(out, out, in) is multi.
> :- mode add_parity(out, in, out) is multi.
> :- mode add_parity(in, out, out) is multi.
> :- mode add_parity(out, out, out) is multi.
> add_parity(even, even, even).
> add_parity(even, odd, odd).
> add_parity(odd, even, odd).
> add_parity(odd, odd, even).

The problem here is essentially that you have declared *too many* modes
for the called predicates `add_parity', `file_parity', and `rank_parity'.

In general, you should not declare modes for predicates in which they
produce values for output arguments that are unconstrained, as is the
case for all the modes of `add_parity' that have determinism `multi'.
Instead, you should use the "constrain and then generate" paradigm.
You should omit declarations for those modes, and instead use an
explicit generator predicate, e.g. `gen_parity', to generate
unconstrained values.

	:- pred gen_parity(parity).
	:- mode gen_parity(in) is det.
	:- mode gen_parity(out) is multi.
	gen_parity(even).
	gen_parity(odd).

Code which needs to generate values should first call all the
predicates which impose constraints, and then finally call a generator
to generate values for values which remain unconstrained:

	color({File, Rank}, Color) :-
		% first apply the constraints
		file_parity(File, FilePar),
		rank_parity(Rank, RankPar),
		add_parity(FilePar, RankPar, Res),
		parity_to_color(Res, Color),

		% then generate any values which haven't
		% been determined by the constraints
		gen_parity(FilePar).

I enclose below a patch to your example code which uses this idiom and
which the Mercury compiler will happily accept.

--- old/pathology.m	Sat Dec  9 19:56:40 2000
+++ ./pathology.m	Sat Dec  9 20:12:01 2000
@@ -18,7 +18,6 @@
 :- mode rank_parity(in, in) is semidet.
 :- mode rank_parity(in, out) is det.
 :- mode rank_parity(out, in) is multi.
-:- mode rank_parity(out, out) is multi.
 rank_parity(first, odd). rank_parity(second, even). rank_parity(third, odd).
 rank_parity(fourth, even). rank_parity(fifth, odd). rank_parity(sixth, even).
 rank_parity(seventh, odd). rank_parity(eighth, even).
@@ -27,7 +26,6 @@
 :- mode file_parity(in, in) is semidet.
 :- mode file_parity(in, out) is det.
 :- mode file_parity(out, in) is multi.
-:- mode file_parity(out, out) is multi.
 file_parity(a,odd). file_parity(b,even). file_parity(c,odd).
 file_parity(d,even). file_parity(e,odd).
 file_parity(f,even). file_parity(g,odd). file_parity(h,even).
@@ -36,7 +34,6 @@
 :- mode parity_to_color(in, in) is semidet.
 :- mode parity_to_color(in, out) is det.
 :- mode parity_to_color(out, in) is det.
-:- mode parity_to_color(out, out) is multi.
 parity_to_color(even, black).
 parity_to_color(odd, white).
 
@@ -45,26 +42,25 @@
 :- mode add_parity(in, out, in) is det.
 :- mode add_parity(out, in, in) is det.
 :- mode add_parity(in, in, in) is semidet.
-:- mode add_parity(out, out, in) is multi.
-:- mode add_parity(out, in, out) is multi.
-:- mode add_parity(in, out, out) is multi.
-:- mode add_parity(out, out, out) is multi.
 add_parity(even, even, even).
 add_parity(even, odd, odd).
 add_parity(odd, even, odd).
 add_parity(odd, odd, even).
 
-% What this really should have been was:
-% color({File, Rank}, Color) :-
-%	parity_to_color(Res, Color),
-%	add_parity(FilePar, RankPar, Res),
-%	file_parity(File, FilePar),
-%	rank_parity(Rank, RankPar).
-% but its determinism could not be correctly inferred by the compiler.
 color({File, Rank}, Color) :-
+	% first apply the constraints
 	file_parity(File, FilePar),
 	rank_parity(Rank, RankPar),
 	add_parity(FilePar, RankPar, Res),
-	parity_to_color(Res, Color).
+	parity_to_color(Res, Color),
+	% then generate any values which haven't
+	% been determined by the constraints
+	gen_parity(FilePar).
+
+:- pred gen_parity(parity).
+:- mode gen_parity(in) is det.
+:- mode gen_parity(out) is multi.
+gen_parity(even).
+gen_parity(odd).
 
 :- end_module pathology.
-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  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