[mercury-users] sqrt.m:005: error: determinism declaration not satisfied.
Terrence Brannon
princepawn at earthlink.net
Fri Apr 27 18:59:51 AEST 2001
[localhost:~/src/mercury/sqrt] metaperl% mmc -E --infer-all sqrt.m
sqrt.m:005: In `main(di, uo)':
sqrt.m:005: error: determinism declaration not satisfied.
sqrt.m:005: Declared `det', inferred `semidet'.
sqrt.m:080: call to `to_float(in, out)' can fail.
... so when I got this error, I changed main/2 to semi det. Then I was
told:
[localhost:~/src/mercury/sqrt] metaperl% mmc -E --infer-all sqrt.m
sqrt.m:005: Error: main/2 must be `det' or `cc_multi'.
... what can I do? everything works when I hardcode the number to find
the square root of, but I am trying to get it from the command
line.. Entire program included for reference.
:- module sqrt.
:- interface.
:- import_module io.
:- pred main(io__state::di, io__state::uo) is semidet.
:- implementation.
:- import_module std_util, float, io, string, list.
% Section 1.1.7 of Abelson and Sussman
% "Structure and Interpretation of Computeer Programs"
% How does one compute square roots? The most common way is to use
% Newton's method of successive approximations, which says that whenever
% we have a guess y for the value of the square root of a number x, we
% can perform a simple manipulation to get a better guess (one closer to
% the actual square root) by averaging y with x/y. For example, we can
% compute the square root of 2 as follows. Suppose our initial guess
% is 1:
%
% Guess Quotient Average
% 1 (2/1) = 2 ((2 + 1)/2) = 1.5
% 1.5 (2/1.5) = 1.3333 ((1.3333 + 1.5)/2) = 1.4167
% 1.4167 (2/1.4167) = 1.4118 ((1.4167 + 1.4118)/2) = 1.4142
% 1.4142 ... ...
% Mercurally speaking, this is:
:- func improve_guess(float, float) = float.
improve_guess(Guess, X) = (Guess + (X / Guess)) / 2.0.
% Continuing this process, we obtain better and better approximations to
% the square root.
%
% Now let's formalize the process in terms of procedures. We start with
% a value for the radicand (the number whose square root we are trying
% to compute) and a value for the guess. If the guess is good enough for
% our purposes, we are done; if not, we must repeat the process with an
% improved guess. We write this basic strategy as a procedure:
% (define (sqrt-iter guess x)
% (if (good-enough? guess x)
% guess
% (sqrt-iter (improve guess x)
% x)))
:- func sqrt_iter(float, float) = float.
sqrt_iter(Guess, X) =
( if good_enough(Guess, X)
then Guess
else sqrt_iter(improve_guess(Guess, X), X)
)
.
% We also have to say what we mean by ``good enough.'' The following
% will do for illustration, but it is not really a very good test. (See
% exercise 1.7.) The idea is to improve the answer until it is close
% enough so that its square differs from the radicand by less than a
% predetermined tolerance (here 0.001):
% (define (good-enough? guess x)
% (< (abs (- (square guess) x)) 0.001))
:- pred good_enough(float, float).
:- mode good_enough(in, in) is semidet.
good_enough(Guess,X) :- abs(Guess * Guess - X) < 0.001.
% Finally, we need a way to get started. For instance, we can always
% guess that the square root of any number is 1
% (define (sqrt x)
% (sqrt-iter 1.0 x))
% main --> { X = sqrt(22.4) }, io__print(X), io__nl.
main -->
io__command_line_arguments(ArgV),
{ if ArgV = [Arg1 | _] then string__to_float(Arg1,X) else (X = 12.0) },
{ Answer = sqrt(X) },
io__print(Answer).
:- func sqrt(float) = float.
sqrt(Num) =
% ( if Num < 0
% then io_write_string("no solution"), fail.
sqrt_iter(1.0, Num).
--------------------------------------------------------------------------
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