[m-users.] Issue with assoc_list and other container types

Volker Wysk post at volker-wysk.de
Sat Jan 22 06:17:36 AEDT 2022


Am Donnerstag, dem 20.01.2022 um 10:56 +1100 schrieb Peter Wang:
> On Wed, 19 Jan 2022 21:01:16 +0100 Volker Wysk <post at volker-wysk.de> wrote:
> > Hi!!
> > 
> > The search predicate in the assoc_list module is like this:
> > 
> > :- pred search(assoc_list(K, V)::in, K::in, V::out) is semidet.
> > 
> > This leads to a problem. The mode of the output variable is "out", this
> > means that its instantiation state is "ground", after the predicate has been
> > called. I have a "call_action" predicate like this:
> > 
> > :- inst assoc_list(K, V) == list(pair(K, V)).
> > 
> > :- func actions =
> >     ( assoc_list(string, pred(string, string))
> >       :: out(assoc_list(ground, pred(in, out) is det))
> >     ).
> > 
> > :- pred call_action(string::in, string::in, string::out) is det.
> >     
> > call_action(Action, Str, Str1) :-
> >     (
> >         if   assoc_list.search(actions, Action, Pred)
> >         then Pred(Str, Str1)
> >         else throw("Bug: unknown action " ++ Action)
> >     ).
> > 
> > The variable "Pred" gets the instantiatedness "ground". This means that
> > "Pred(Str, Str1)" leads to a compile time error, because the
> > instantiatedness of Pred needs to be "pred(in, out) is det" for the call.
> > And such a higher-order inst is not ground.
> > 
> > This means that functions/predicates can't be usefully stored in association
> > lists, because you can't call them (what else would you want to do with
> > them?).
> 
> The workaround (or preferred pattern, if you like) is to define a type
> to carry the higher-order inst around:
> 
>     :- type action_pred
>         --->    action_pred(
>                     pred(string::in, string::out) is det
>                 ).
> 
> Then store values of that type in your container instead of the
> higher-order terms directly.

Okay, thanks. I'm doing it this way now. 

> > :- pred assoc_list_search(
> >     assoc_list(string, pred(string, string)),
> >     string,
> >     pred(string, string)).
> > 
> > :- mode assoc_list_search(
> >     in(assoc_list(Key, Val)),
> >     in,
> >     out(Val))
> > is semidet.
> > 
> > assoc_list_search(L, K, V) :-
> >     ( L = [K - V]
> >     ; L = [_, K1 - V1 | Rest],
> >       assoc_list_search([K1 - V1 | Rest], K, V)
> >     ).
> > 
> > This predicate works for call_action/3. You get the higher-order-inst of the
> > predicate, which has been found, in the search result. 
> > 
> > I guess, the assoc_list.search/3 and other predicates/functions should be
> > modified, and it be done this way.
> > 
> > It should be the same problem with other container types (I haven't
> > checked).
> 
> This works for assoc_list because the type definition is exported from
> the module. It won't work for types like types like map where the type
> is deliberately kept private.

I see. But it would work for assoc_list. Perhaps change the modes of the
predicates and functions in question?

Cheers,
Volker
-------------- 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/20220121/3d64270e/attachment.sig>


More information about the users mailing list