[mercury-users] Mode checking if-then-else vs less readable switch
Andrew Ross
andrew at bubblehelicopter.com
Thu Aug 25 11:45:03 AEST 2011
Hi all, I'm wondering if I've hit a limitation in the mode checker of
the Mercury compiler, or if I just need more experienced Mercury users
to point me in the right direction :-)
A simplified example:
:- import_module int.
:- import_module string.
:- type const_or_var
---> const(int)
; var(string).
:- inst var
---> var(ground).
:- inst const
---> const(ground).
:- func plus(const_or_var, const_or_var) = const_or_var.
:- mode plus(in(const), in(const)) = out(const) is det.
:- mode plus(in(var), in) = out(var) is det.
:- mode plus(in, in(var)) = out(var) is det.
My intention with these modes is to allow mmc to infer that callers are
det when they do things like:
var(NewVarName) = plus(var("V"), const(0))
With the mode "plus(in, in) = out is det" mmc thinks the unification can
fail. If we want the caller to be det we need to use the above-mentioned
modes or make the calling code be:
NewVar = plus(var("V"), const(0)),
(
NewVar = var(NewVarName)
;
NewVar = const(_),
unexpected($module, $pred, "var + const should equal var")
)
This extra code can be optimized away, but it still annoys me that
anyone reading it is given the false impression that a run-time error
could occur here. Perhaps I'm overreacting, but I'm happier with the
one-line version of the calling code and the extra modes for plus.
Now, a concise implementation of plus is:
plus(A, B) = Z :-
( if
A = const(IntA),
B = const(IntB)
then
Z = const(IntA + IntB)
else
Z = var("A + B")
).
but this fails mode checking:
In clause for `plus(in((itest.const)), in((itest.const))) =
out((itest.const))':
mode error: argument 3 had the wrong instantiatedness.
Final instantiatedness of `Z' was `unique(itest.const(unique) ;
itest.var(unique("A + B")))',
expected final instantiatedness was
`bound(itest.const(ground))'.
The following implementation passes mode checking, but (in my opinion)
it's less readable than the previous version. It's certainly more
error-prone, since it has duplicated code.
plus(A, B) = Z :-
(
A = const(IntA),
(
B = const(IntB),
Z = const(IntA + IntB)
;
B = var(_),
Z = var("A + B")
)
;
A = var(_),
Z = var("A + B")
).
Should the mode checker be able to infer that the if-then-else version
of plus satisfies the declared modes?
Cheers
Andrew
--------------------------------------------------------------------------
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