[mercury-users] Rewriting if-then-else as (CondGoal, ThenGoal; not(CondGoal), ElseGoal)

Daniel Patterson lists.mercury at dbp.mm.st
Mon Sep 5 11:45:48 AEST 2011

```Hi,

sorry if this is a really beginner question, but I have an example program (that solves the first of the project euler problems):

:- pred euler1(int::in,int::out) is det.

euler1(N,P) :-
Np = N mod 3, Nq = N mod 5,
( if
N =< 0
then
P = 0
else
(
if (Np = 0; Nq = 0)
then euler1(N-1,Ps), P = N + Ps
else euler1(N-1,P)
)
).

And I was trying to rewrite it without all the if-then-elses. My first attempt (just to get rid of the outermost one), said that it was inferred as nondet, not det. Code is:

:- pred euler1alt(int::in,int::out) is det.

euler1alt(N,P) :-
(
N =< 0, P = 0
;
not (N =< 0),
Np = N mod 3, Nq = N mod 5,
(if (Np = 0; Nq = 0)
then euler1alt(N-1,Ps), P = N + Ps
else euler1alt(N-1,P)
)
).

The error was:
one.m:025:   Declared `det', inferred `nondet'.
one.m:029:   Disjunction has multiple clauses with solutions.
one.m:029:   call to `int.=<'(in, in) can fail.
one.m:031:   Negated goal can succeed.

I'm not sure why this change meant that there were now many or no solutions, as it seemed analogous to the if-then-else used above. The error specifies that =< can fail, but I would have thought that was covered by the not (N =< 0) case in the switch.

What am I not understanding? I read the section on determinism and on goals (that talks about if-then-else having different semantics) in the reference manual, but I'm having a hard time figuring out how it is applying here, and how to fix the code!

- An excited new user of Mercury.

--------------------------------------------------------------------------
mercury-users mailing list
Post messages to:       mercury-users at csse.unimelb.edu.au