[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


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 
      P = 0 
          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! 

Thanks in advance,

- An excited new user of Mercury.

mercury-users mailing list
Post messages to:       mercury-users at csse.unimelb.edu.au
Administrative Queries: owner-mercury-users at csse.unimelb.edu.au
Subscriptions:          mercury-users-request at csse.unimelb.edu.au

More information about the users mailing list