[m-users.] Using type constructors in predicate heads

Julien Fischer jfischer at opturion.com
Sun Nov 7 15:11:54 AEDT 2021


Hi Sean,

On Sat, 6 Nov 2021, Sean Charles (emacstheviking) wrote:

> Is it possible / allowed to write a predicate declaration to
> explicitly mention a single type from a set of types? I seem to have a
> pattern cropping up again and again lately, here is my current
> situation. I have a node type:
> 
> :- type snode
>     --->    sexp(location, list(snode))
>     ;       list(location, list(snode))
>     ;       map(location, list(snode))
>     ;       tk(location,string)
>     ;       kw(location, string)
>     ;       s1(location,string)
>     ;       s2(location,string)
>     .
> 
> In my code, I have performed some pre-checks on a term 
> 
>     ( if Term = sexp(_, [tk(_, F)|_]) then
> 
> such that when I call the predicate to handle it, I —know— that it can
> only be the one containing an s-expression, but it seems that I am
> forced to define the predicate I call as the containing `snode` type,
> I guess what I am saying is is it possible to change this:
> 
> :- pred do_gencall(int, renderer, snode, tcon, tcon).
> :- mode do_gencall(in, renderer, in, in, out) is det.
> do_gencall(L, R, Term, !T) :-
> 
> to this in some way?
> 
> :- pred do_gencall(int, renderer, snode:sexp, tcon, tcon).
> :- mode do_gencall(in, renderer, in, in, out) is det.
> do_gencall(L, R, Term, !T) :-

Yes, use inst subtyping.

     :- pred do_gencall(int, renderer, snode, tcon, tcon).
     :- mode do_gencall(in, renderer, in(sexp(ground, ground)), in, out) is det.

It's a little cleaner to do:

    :- inst sexp for snode/0
       --->  sexp(ground, ground).

    :- pred do_gencall(int, renderer, snode, tcon, tcon).
    :- mode do_gencall(in, renderer, in(sexp), in, out) is det.

If you're using a recent ROTD you could alternatively use subtypes
to achieve the same thing:
<http://mercurylang.org/information/doc-latest/mercury_ref/Subtypes.html#Subtypes>

Julien.


More information about the users mailing list