<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Julien,<div class="">Thanks for that. I knew in the back of my mind I had read something about using inst. I thrashed around for about an hour and in the end I just declared a new type! This answer though I will read until I get it and then apply it to my code.</div><div class=""><br class=""></div><div class="">I am using:</div><div class=""><span style="font-size: 14px; font-family: MonoidNerdFontComplete-Regular;" class="">{7:40}~/Documents/code/mercury/f2:ast-start ✗ ➭ mmc -v</span></div><div class=""><font face="MonoidNerdFontComplete-Regular" style="font-size: 14px;" class="">Mercury Compiler, version 20.06.1, on x86_64-apple-darwin19.6.0<br class="">Copyright (C) 1993-2012 The University of Melbourne<br class="">Copyright (C) 2013-2020 The Mercury team<br class="">Usage: mmc [<options>] <arguments><br class="">Use `mmc --help' for more information.</font></div><div class=""><br class=""></div><div class="">In section 3.2.4 the words “experimental” and “subject to change” were enough for me , </div><div class=""><br class=""></div><div class="">I made your suggested change, it works fine but… can I push it a little further? I went back to the Mercury crash course page as it mentioned non_empty_list, I found no references in the reference guide or the library but plenty in the source code for my ROTD version… but I am unsure of the syntax, if possible, of stating that the the list of terms to the sexp() functor is guaranteed to be non empty because:</div><div class=""><br class=""></div><div class=""><span style="font-size: 14px;" class=""><font face="MonoidNerdFontComplete-Regular" class=""> ( if Term = sexp(_, <b class="">[ tk(_,F) | _ ]</b>) then</font></span><br class=""></div><div class=""><br class=""></div><div class="">already established that fact prior to the call…but this leads me to my final question: —should— I be doing this? I ask because</div><div class=""><br class=""></div><div class=""><span style="font-size: 14px;" class=""><font face="MonoidNerdFontComplete-Regular" class="">:- mode do_gencall(in, renderer, in(sexp), in, out) is det.<br class="">do_gencall(_L, R, sexp(_, [Functor|Args]), !T) :-<br class=""></font></span></div><div class=""><br class=""></div><div class="">This obv. fails because the unification into head and tail could fail, but if I declare it as semidet then obv. I have to check the call further up the code, again I totally understand why but my question then is, should I do this at all ? I have not used Haskell in a while now, plumping for Mercury, but I was getting reasonably proficient at the concept of `programming with types` and this feels similar. If I instructed the compiler that the mode was something like</div><div class=""><br class=""></div><div class=""><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">:- mode</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class=""> do_gencall</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">(</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">in</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">,</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class=""> renderer</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">,</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class=""> in</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">(</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">sexp-with-non-empty-args</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">),</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class=""> in</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">,</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class=""> out</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">)</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class=""> </span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">is</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class=""> </span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">det</span><span style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class="">.</span><br style="font-family: MonoidNerdFontComplete-Regular; font-size: 14px;" class=""></div><div class=""><br class=""></div><div class="">then presumably the predicate could remain as `det`, everybody is happy and my code feels more rigorous for it. I refer to the sample of code in the file ‘./mercury-srcdist-20.06.1/browser/parse.m’ , lines 305 to 307:</div><div class=""><br class=""></div><div class=""><font face="MonoidNerdFontComplete-Regular" style="font-size: 14px;" class="">:- pred lexer_arg(list(char)::in(non_empty_list), list(token)::out) is det.<br class=""><br class="">lexer_arg([Head | Tail], Toks) :-</font></div><div class=""><br class=""></div><div class="">This clearly shows to me that by using non_empty_list the compiler is happy to let me deconstruct the list in the clause head with no problems. I am not sure how to combine the mode you showed me with the addition of the non empty constraint as well that’s all!</div><div class=""><br class=""></div><div class="">This is currently at the edges of both my knowledge and comfort with Mercury , I am hoping to learn some more from you guys.</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Sean.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Thanks again,</div><div class="">Sean</div><div class=""><br class=""></div><div class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On 7 Nov 2021, at 04:11, Julien Fischer <<a href="mailto:jfischer@opturion.com" class="">jfischer@opturion.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><br class="">Hi Sean,<br class=""><br class="">On Sat, 6 Nov 2021, Sean Charles (emacstheviking) wrote:<br class=""><br class=""><blockquote type="cite" class="">Is it possible / allowed to write a predicate declaration to<br class="">explicitly mention a single type from a set of types? I seem to have a<br class="">pattern cropping up again and again lately, here is my current<br class="">situation. I have a node type:<br class="">:- type snode<br class=""> ---> sexp(location, list(snode))<br class=""> ; list(location, list(snode))<br class=""> ; map(location, list(snode))<br class=""> ; tk(location,string)<br class=""> ; kw(location, string)<br class=""> ; s1(location,string)<br class=""> ; s2(location,string)<br class=""> .<br class="">In my code, I have performed some pre-checks on a term <br class=""> ( if Term = sexp(_, [tk(_, F)|_]) then<br class="">such that when I call the predicate to handle it, I —know— that it can<br class="">only be the one containing an s-expression, but it seems that I am<br class="">forced to define the predicate I call as the containing `snode` type,<br class="">I guess what I am saying is is it possible to change this:<br class="">:- pred do_gencall(int, renderer, snode, tcon, tcon).<br class="">:- mode do_gencall(in, renderer, in, in, out) is det.<br class="">do_gencall(L, R, Term, !T) :-<br class="">to this in some way?<br class="">:- pred do_gencall(int, renderer, snode:sexp, tcon, tcon).<br class="">:- mode do_gencall(in, renderer, in, in, out) is det.<br class="">do_gencall(L, R, Term, !T) :-<br class=""></blockquote><br class="">Yes, use inst subtyping.<br class=""><br class=""> :- pred do_gencall(int, renderer, snode, tcon, tcon).<br class=""> :- mode do_gencall(in, renderer, in(sexp(ground, ground)), in, out) is det.<br class=""><br class="">It's a little cleaner to do:<br class=""><br class=""> :- inst sexp for snode/0<br class=""> ---> sexp(ground, ground).<br class=""><br class=""> :- pred do_gencall(int, renderer, snode, tcon, tcon).<br class=""> :- mode do_gencall(in, renderer, in(sexp), in, out) is det.<br class=""><br class="">If you're using a recent ROTD you could alternatively use subtypes<br class="">to achieve the same thing:<br class=""><<a href="http://mercurylang.org/information/doc-latest/mercury_ref/Subtypes.html#Subtypes" class="">http://mercurylang.org/information/doc-latest/mercury_ref/Subtypes.html#Subtypes</a>><br class=""><br class="">Julien.</div></div></blockquote></div><br class=""></div></body></html>