[m-users.] [Beginner] How to make a function using list pattern matching deterministic

Volker Wysk post at volker-wysk.de
Fri Oct 14 22:31:37 AEDT 2022


Am Freitag, dem 14.10.2022 um 16:29 +0530 schrieb Razetime:
> Currently I have these two predicates in my program that I think I can
> make deterministic.
> 
> :- pred entry(list(string)::in, list(int)::out) is det.
> entry(Dirs, Out) :-
>   map((pred(X::in, [L,R]::out) is det :-
>          split(X, 1, L, R)),
>        Dirs, Spl),
>   foldl2((pred([T, B]::in, D::in, Ds::out, P::in, Ps::out) is det :-
>             rot(T, D, Ds),
>             BI = string.det_to_int(B),
>             map((pred(X::in, Y::out) is det :- Y = X*BI), Ds, Dso),
>             map_corresponding((pred(X::in, Y::in, Z::out) is det :- Z
> = X+Y), P, Dso, Ps)
>         ), Spl, [0, 1], _, [0, 0], Out).
> 
> :- pred rot(string::in, list(int)::in, list(int)::out) is det.
> rot("L", [X, Y], [A, B]) :-
>   A = -Y,
>   B =  X.
> rot("R", [X, Y], [A, B]) :-
>   A =  Y,
>   B = -X.

You're defining rot/3 to take two element lists, as the second argument,
only. It can't be deterministic, because of what should happen when no such
argument was specified, but, say an empty list. The first argument also
isn't exhaustive.

You could use unexpected/2 from the "require" library:


:- pred rot1(string::in, list(int)::in, list(int)::out) is semidet.

rot1("L", [X, Y], [A, B]) :-
  A = -Y,
  B =  X.
rot1("R", [X, Y], [A, B]) :-
  A =  Y,
  B = -X.


:- pred rot(string::in, list(int)::in, list(int)::out) is det.

rot(LR, Inlist, Outlist) :-
   ( if   rot1(LR, Inlist, Outlist0)
     then Outlist = Outlist0
     else unexpected($pred, "Unexpected arguments in call to rot/3")
   ).


It could be made to accept only two-element list and make it deterministic,
with the help of insts. But that's advanced stuff.


Bye,
Volker

> 
> I'm having trouble with both of these since they're giving me problems
> with determinism inference:
> 
> a01.m:017: In `entry'(in, out):
> a01.m:017:   Determinism error in lambda expression.
> a01.m:017:   Declared `det', inferred `semidet''.
> a01.m:017:   In argument 1 of clause head:
> a01.m:017:   in argument 2 of functor `[|]/2':
> a01.m:017:   in argument 2 of functor `[|]/2':
> a01.m:017:   unification with `list.[]' can fail.
> a01.m:017:   In argument 1 of clause head:
> a01.m:017:   in argument 2 of functor `[|]/2':
> a01.m:017:   unification with `list.[B | V_35]' can fail.
> a01.m:017:   In argument 1 of clause head:
> a01.m:017:   unification of `LambdaHeadVar__1' and `list.[T | V_34]' can fail.
> a01.m:024: In `rot'(in, in, out):
> a01.m:024:   error: determinism declaration not satisfied.
> a01.m:024:   Declared `det', inferred `semidet'.
> a01.m:024:   The reasons for the difference are the following.
> a01.m:025:   The switch on HeadVar__1 can fail.
> a01.m:025:   In argument 2 of clause head:
> a01.m:025:   in argument 2 of functor `[|]/2':
> a01.m:025:   in argument 2 of functor `[|]/2':
> a01.m:025:   unification with `list.[]' can fail.
> a01.m:025:   In argument 2 of clause head:
> a01.m:025:   in argument 2 of functor `[|]/2':
> a01.m:025:   unification with `list.[V_23 | V_22]' can fail.
> a01.m:025:   In argument 2 of clause head:
> a01.m:025:   unification of `HeadVar__2' and `list.[V_21 | V_20]' can fail.
> 
> how do i make sure that these functions that use a pattern match are
> det? Adding a branch with ; for the error cases makes it multi, but I
> want to know how i can make it return a single value for every set of
> arguments.
> _______________________________________________
> users mailing list
> users at lists.mercurylang.org
> https://lists.mercurylang.org/listinfo/users

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <http://lists.mercurylang.org/archives/users/attachments/20221014/a9990b9f/attachment.sig>


More information about the users mailing list