[mercury-users] Understanding why a predicate using try/2 is multi (instead of cc_multi)
Ian MacLarty
maclarty at csse.unimelb.edu.au
Thu Oct 20 09:40:22 AEDT 2011
Hi Andrew,
On Wed, Oct 19, 2011 at 5:35 PM, Andrew Ross
<andrew at bubblehelicopter.com> wrote:
> 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.
In your example above, you've declared main as det. You can declare
it as cc_multi if you want to avoid the promise_equivalent_solutions
in run_test.
The reason try is cc_multi is because it could return either a result
or an exception, but (declaratively) you don't know which. If you
ignore try's result, then the result of run_test is unaffected by what
value try returns, so it's inferred to be det. However if you do
something with try's result that affects the output of run_test (for
example using to modify the io state by passing it to io.write), then
run_test's output depends on try's output and so it too must be
cc_multi.
I'm not sure exactly why the system infers run_test to be multi
instead of cc_multi if you omit the mode declarations. I'd guess it's
probably just a weakness in the mode inference. Usually you're better
off adding explicit mode and type declarations to all your predicates.
Ian.
--------------------------------------------------------------------------
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