[m-users.] switch confusion with cc_multi

Julian Fondren jfondren at minimaltype.com
Wed Aug 21 02:44:33 AEST 2019


On 2019-08-20 11:06, Mark Brown wrote:
> On Tue, Aug 20, 2019 at 3:20 AM Zoltan Somogyi
> <zoltan.somogyi at runbox.com> wrote:
>> 
>> On Mon, 19 Aug 2019 14:17:31 +0100, emacstheviking <objitsu at gmail.com> 
>> wrote:
>> > Every time I use multiple predicates with (_,..) as the event
>> 
>> What does this mean? If you don't show us the actual code, we cannot 
>> tell you
>> what is wrong with it. We can only guess, as the previous two replies 
>> have done,
>> which may only confuse you further.
> 
> Code was posted, and the relevant predicate was referred to by name.
> The code compiles fine with a reasonable type declaration so long as
> it doesn't have user defined equality or comparison, but if it does
> the compiler reports that a unification has multiple solutions. That
> is why I asked about that feature.

The code that was posted isn't the code that he had a problem with
though.  "Every time I use multiple predicates with (_,..)" <- so when,
*instead* of the posted code, he tries writing multiple clauses where
one of the clauses uses a _ catch-all, he gets this problem: that the _
means the predicate isn't deterministic anymore, because every event he
wants to handle, he's also handling with the catch-all.

I think this is pretty clearly what the question is about, but without
code it's arguable that I'm guessing. And, I didn't understand your
reply at all, so clearly there are other potential interpretations of
the question :)

Mercury FAQ for people from FP langs with pattern-matching (SML, OCaml,
Erlang, Haskell, even Rust):

Q. Why isn't this deterministic?

   :- func handle(bool) = string.
   handle(yes) = "the bool was 'yes'".
   handle(_) = "the bool was something else".

A. Unlike in FP langs with pattern-matching, these clauses aren't
ordered and the _ isn't a "catch-all" that in this code will only ever
match 'no' after the 'no' fails to match against the first clause. This
is a disjunction and only one clause must be true; because _ also
matches yes, both clauses define solutions for handle(yes), so this must
be (at least) a 'multi' rule.

As a rule, you can

1. exhaustively match all the cases to achieve a deterministic
disjunction.

   handle(yes) = "...".
   handle(no) = "...".

or

   :- type other_thing ---> yes ; no ; maybe.

   :- func handle(other_thing) = string.
   handle(yes) = "the other thing was 'yes'".
   handle(X) = _ :-
       ( X = no ; X = maybe ),
       throw(not_implemented).

2. wrap an incomplete disjunction in a conditional, with the 'else' part
of the conditional as your catch-all.

   handle(B) = R :-
       ( if X = yes, R0 = "ok" ; X = no, R0 = "denied" then
           R = R0
       else
           throw(not_implemented)
       ).

3. drop down to semidet determinism, allowing for failure and no 'else'
case.

     :- func handle(bool::in) = (string::out) is semidet.
     handle(yes) = "the bool was 'yes'".
     % nothing else.

As a rule, you SHOULD NOT EVER

1. replace 'det' with 'cc_multi'. It will only accidentally seem to do
what you want.

>> only det code may do I/O.
> 
> cc_multi code may do I/O.
> 
> Mark
> _______________________________________________
> users mailing list
> users at lists.mercurylang.org
> https://lists.mercurylang.org/listinfo/users


More information about the users mailing list