[m-users.] Determinism woes...

Richard O'Keefe raoknz at gmail.com
Fri Jul 5 21:43:28 AEST 2019


Some Prolog systems offer a so-called "soft cut".
For example, in SWI Prolog, GNU Prolog, Jekejeke Prolog, and I think Yap:

%%         A                    B
?- ((X = 1 ; X = 2) *-> Y = yes ; Y = no).
X = 1,
Y = yes ;
X = 2,
Y = yes.

The soft cut removed the choice point at B but not the choice point at A.
Colour me stupid, but I've never quite figured out what this *means*.
I always felt that you should think of (A -> B ; C) as a more efficient
(A , B ; \+(A), C) so that if \+(A) was semantically dodgy, you should
not do that, but should restructure your Prolog code in some way.
But that, of course, is Prolog.

What the manual is saying here is that
(A -> B ; C) in Mercury is like (A -> B ; C) in Prolog
and
(if A then B else C) in Mercury is like (A *-> B ; C) in many Prologs.
C will be executed only if A has no solutions, otherwise it acts like
(A, B).

In your particular example, where Char is ground, Char = '(' has at most
one solution, and the same for Char = ')', so there shouldn't be any
difference between the -> ; version and the if then else version.



On Fri, 5 Jul 2019 at 22:29, emacstheviking <objitsu at gmail.com> wrote:

> OK, I read everybodies comments, read all the suggested links and I
> amended my code to be like so:
>
> :- pred char_type(char::in, chartype::out) is det.
>
> char_type(Char, Type) :-
>     (   if      Char = '(' then Type = p_open
>         else if Char = ')' then Type = p_close
>         else    Type = c_general
>     ).
>
> This works as desired and as expected which is great, but....understanding
> why! I can see that by using the if-then-else that the final else clause
> has no mention of Char, whereas before I had "Char = _"...    meaning that
> multiple solutions where available. In the polog-mercury transition docs,
> section 6 cuts and indexing it says:
>
> Mercury allows if-then-elses to be written not just as ‘C -> T ; E’, but
>> also as ‘if C then T else E’. In Mercury, an if-then-else prunes away
>> either the ‘else’ goal (if the condition succeeded) or the ‘then’ goal (if
>> the condition failed), but if there are multiple solutions to the
>> condition, they will all be found on backtracking, and the ‘then’ goal will
>> be executed for each of those solutions. By contrast, an if-then-else in
>> Prolog prunes away all solutions of the condition except the first.
>
>
> But I find this hard to decipher. I can see the equivalence between the
> two expression forms, that's the easier part, but I am confused where it
> says "but if there are multiple..." because if the if-the-else is syntactic
> sugar...? But it says something about pruning away the else goal or the
> then goal(s) etc. I think I nearly have it but I find my brain feeling like
> trying to climba greasy pole at time and I really really want to understand
> this.
>
> All I seek is some clarification over why the if-then-else works as I
> expected it too and I can assimilate that and move on!
>
> Thanks again,
> Sean.
>
>
>
>
> On Fri, 5 Jul 2019 at 05:17, Julian Fondren <jfondren at minimaltype.com>
> wrote:
>
>> On 2019-07-04 17:46, emacstheviking wrote:
>> > Thanks Richard!
>> >
>> > That is so obvious when you see it. I am thinking like a Haskell
>> > hacker this evening for sure.
>> > I changed it to "cc_multi" and it compiled ANd did what I expected /
>> > wanted.
>>
>> It may do you what you want, but this is by accident. It is legal for
>> the cc_multi version of your code to report that '(' is a c_general
>> rather than a p_open.
>>
>> Consider:
>>
>> https://mercurylang.org/information/doc-latest/mercury_ref/Semantics.html
>>
>> Or this chapter of the Prolog to Mercury guide:
>>
>>
>> https://mercurylang.org/information/doc-latest/mercury_trans_guide/Commits.html
>>
>> I don't know Prolog well at all, and wouldn't've benefited from that
>> chapter since I'm not familiar with that pattern of cuts and a
>> catch-all, but I've run into your exact problem of wanting to say
>>
>>    char_type(')', p_open).
>>    char_type('(', p_close).
>>    char_type(_, c_general).
>>
>> because functional languages with pattern-matching all do it in an
>> ordered way that permits very similar constructs. This is probably
>> what you meant by "thinking like a Haskell hacker" but even C's
>> switch() statement permits this sort of thing. For Mercury you can try
>> viewing your code through the lens of the strict commutative
>> semantics.
>>
>> So when looking at that code, imagine
>>
>>    char_type(_, c_general).
>>    char_type(')', p_open).
>>    char_type('(', p_close).
>>
>> or
>>
>>    char_type(')', p_open).
>>    char_type(_, c_general).
>>    char_type('(', p_close).
>>
>> or
>>
>>    char_type('(', p_close).
>>    char_type(_, c_general).
>>    char_type(')', p_open).
>>
>> ...
>>
>> If any variation doesn't look like something you'd want, your original
>> code isn't what you want either.
>> _______________________________________________
>> users mailing list
>> users at lists.mercurylang.org
>> https://lists.mercurylang.org/listinfo/users
>>
> _______________________________________________
> users mailing list
> users at lists.mercurylang.org
> https://lists.mercurylang.org/listinfo/users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20190705/e2f0e9a1/attachment-0001.html>


More information about the users mailing list