[mercury-users] Understanding why a predicate using try/2 is multi (instead of cc_multi)
Andrew Ross
andrew at bubblehelicopter.com
Wed Oct 19 17:35:08 AEDT 2011
Hi all, I'm hoping someone here and can help me understand why my mmc infers
that my predicate is multi instead of cc_multi. I've tried compiling with
--debug-det but the only extra output I got was comments of the form:
Inferred new detism det for predicate`test_do_overflow_safe.run_test'/3 mode 0
Inference pass complete
Inferred old detism det for predicate`test_do_overflow_safe.run_test'/3 mode 0
Inference pass complete
Inferred new detism det for predicate`test_do_overflow_safe.main'/2 mode 0
I'm writing unit tests and want to catch exceptions so I can run multiple
(related) tests sequentially within a single executable. Test case predicates
are passed to a wrapper predicate that is responsible for calling them and
catching exceptions.
Here is a dummy test function and an implementation of run_test that silently
swallows the exception:
:- pred main(io::di, io::uo) is det.
main(!IO) :-
Test1 = ((pred(N::out) is det) :- N = 0),
run_test(Test1, !IO).
:- pred run_test(pred(T), io, io) is det.
:- mode run_test(in(pred(out) is det), di, uo).
run_test(TestPred, !IO) :-
try(TestPred, _Result).
This compiles and runs correctly. By adding a trace goal to Test1 you can see
that it is being executed.
As soon as I try to do something with the result of try/2 (such as printing it
with io.write), mmc infers that run_test is multi:
In `main'(di, uo):
error: determinism declaration not satisfied.
Declared `det', inferred `multi'.
call to `test_do_overflow_safe.run_test'(di(/*
unique */(pred((free >> ground)) is det)), di,
uo) can succeed more than once.
In clause for `main(di, uo)':
mode error: argument 2 did not get sufficiently
instantiated.
Final instantiatedness of `STATE_VARIABLE_IO'
was `mostly_unique',
expected final instantiatedness was `unique'.
In `run_test'(di(/* unique */(pred((free >>
ground)) is det)), di, uo):
error: invalid determinism for a predicate with
I/O state arguments.
Valid determinisms are det, cc_multi and
erroneous.
Inferred :- pred run_test((pred T), io.state,
io.state).
Inferred :- mode run_test(di(/* unique
*/(pred((free >> ground)) is det)), di, uo) is
multi.
Error: call to predicate `exception.try'/2 with
determinism `cc_multi' occurs in a context which
requires all solutions.
Wrapping try/2 in promise_equivalent_solutions allows the compilation to
succeed, but I'm wary of using that without fully understanding why run_test is
being treated as multi.
I read the thread at
http://www.mercury.csse.unimelb.edu.au/mailing-lists/mercury-users/mercury-users.201005/0011.html
but that deals with why you need to explicitly convert cc_multi to det with
promise_equivalent_solutions, where as I would be happy for cc_multi to bubble
up to main.
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