[m-users.] Factored out disjunction no longer compiles, generates determinism error.

Zoltan Somogyi zoltan.somogyi at runbox.com
Sun May 9 07:54:04 AEST 2021



On Sat, 8 May 2021 22:30:53 +0100, "Sean Charles (emacstheviking)" <objitsu at gmail.com> wrote:
> :- pred parse_cmd(command::out, list(char)::in, list(char)::out) is semidet.
> parse_cmd(Cmd)  —>
>     (
>         help_cmd(Cmd).   %<=== this is line 111
>         %['h','e','l','p'], skip_ws, eol, {Cmd=help}
>     ;
>         ['l','e','x'], skip_ws, eol, {Cmd=lex}
>     ;
>         ['a','s','t'], skip_ws, eol, {Cmd=ast}
>     ).
> 
> :- pred help_cmd(command::out, list(char)::in, list(char)::out) is semidet.
> 
> help_cmd(Cmd)  —>
>     ['h','e','l','p’],
>     skip_ws,
>     eol,
>     {Cmd=help}.
> 
> 
> >>> repl.m:111:   Disjunction has multiple clauses with solutions.
> 
> What does this means in English? I know what the disjunction is, it’s the call to help_cmd(),

No, that is not the disjunction. The disjunction is ( Disjunct1 ; Disjunct2 ; Disjunct3 ),
where Disjunct1 is the call to help_cmd().

> what I don’t get is why it has multiple solutions,

Because (a) the determinism of help_cmd() says it may generate a solution,
and (b) the compiler can see that either Disjunct2 and Disjunct3 may also
generate solutions. That means that the compiler cannot rule out the
possibility that the disjunction will generate *more than one* solution
for a given input.

Before you moved moved the code recognizing the help command
into a separate predicate, the compiler could see, when analyzing
parse_cmd, that each disjunct unified the first char in the second arg list
with a distinct value. That made the disjunction a switch on that char,
and this told the compiler that at runtime, at most one disjunct
can generate solutions. Moving the test for 'h' into a separate
predicate hid this info from the compiler, which why you now get
that error.

Mercury's rules for determinism are simple, because humans
find complex rules unpredictable. And even complex rules
wouldn't be guaranteed to read programmers minds, as you
seem to expect the compiler to do in this case, because
in the fully general case, a determinism analysis can be fully accurate
(meaning it computes the tightest possible determinism for every
possible piece of code) only if it can solve the halting problem,
which is provably impossible.

I think you need to read section 6.2 of the reference manual,
and judging by earlier emails, the Prolog to Mercury transition guide
as well.

Zoltan.






More information about the users mailing list