[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