[mercury-users] Switches and "subswitches"
Ondrej Bojar
oboj7042 at ss1000.ms.mff.cuni.cz
Sun Sep 30 21:26:47 AEST 2001
Hello.
I quite often face a problem with switches and "subswitches". (I hope
you'll find switches and subswitches in the following code, I'm really
unable to describe the notion in English.)
I want to write code like this: (line numbers supplied)
15 :- type type_a ---> a_a; a_b; a_c.
16 :- type type_b ---> b_a; b_b.
17
18 :- type type_c ---> c_a_a; c_anything_b; c_b_a; c_c_anything.
19
20 % the two_to_and_from_one is to convert information supplied
21 % in headvar 1 and headvar2 to headvar3 and back again.
22 :- pred two_to_and_from_one(type_a, type_b, type_c).
23 :- mode two_to_and_from_one(in, in, out) is det.
24 :- mode two_to_and_from_one(out, out, in) is multi.
25
26 % of course the real conversion is a bit more complicated
27 % usually I do some calls *after* the unifications
28 two_to_and_from_one(a_a, b_a, c_a_a).
29 two_to_and_from_one(a_b, b_a, c_b_a).
30 two_to_and_from_one(a_c, B, c_c_anything) :-
31 B = b_a; B = b_b.
32 two_to_and_from_one(A, b_b, c_anything_b) :-
33 A = a_a ; A = a_b.
...And now the error message
testswitches.m:023: In `two_to_and_from_one(in, in, out)':
testswitches.m:023: error: determinism declaration not satisfied.
testswitches.m:023: Declared `det', inferred `nondet'.
testswitches.m:028: In argument 2 of clause head:
testswitches.m:028: unification of `HeadVar__2' and `testswitches:b_a'
can fail.
testswitches.m:029: In argument 2 of clause head:
testswitches.m:029: unification of `HeadVar__2' and `testswitches:b_a'
can fail.
testswitches.m:032: In argument 2 of clause head:
testswitches.m:032: unification of `HeadVar__2' and `testswitches:b_b'
can fail.
testswitches.m:033: The switch on A does not cover testswitches:a_c/0.
testswitches.m:028: Disjunction has multiple clauses with solutions.
I suppose, Mercury is not able to find out that for example the case of
input variables a_a, b_b is covered with the last clause. And Mercury
tries to get the answer in the first clause already. A solution would be
to parse the input variables in exact order, as a decision tree: (the
switches and subswitches notion)
if A = a_a
then
if B = b_b
then C = c_anything_b
else C = c_a_a
else
...
But this solution will lead to I-dont-know-what code when the other mode
of the predicate is to be build.
Another solution would be to list all possible cases one by one:
two_to_and_from_one(a_a, b_a, c_a_a).
two_to_and_from_one(a_a, b_b, c_anything_b).
But this solution is not too "typing-efficient" and is absolutely useless
when string or int comes as the input variable type... (Which is my case.)
Is there a better way of writing such code?
(In the example above, the c_anything_b and c_c_anything combination is
deliberate. Sometimes, only the first input is important, sometimes only
the other is.)
What also fails is using negation:
two_to_and_from_one(A, b_b, c_anything_b) :-
A \= a_c.
This leads to a mixed-mode error, as Mercury is (naturally) not able to
find all possilbe values for A different from a_c when building mode (out,
out, in).
It might happen, that I even forget some cases when writing the code... I
love Mercury for showing me mistakes like that, but here the situation is
a bit too complicated, so Mercury can't explain what did I wrong...
Thanks for any tips on rewriting the code.
Andrew.
--------------------------------------------------------------------------
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