<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="">Julien, <div class=""><br class=""></div><div class="">An additional change I had to make, seeking explanation! I think I know why but just would like to fully understand… here is the predicate that is calling the do_gencall predicate, note that the type of Term is an snode...<div class=""><br class=""></div><font face="MonoidNerdFontComplete-Regular" size="2" class="">:- pred translate_all_terms(renderer, lsnode, tcon, tcon).<br class="">:- mode translate_all_terms(renderer, in, in, out) is det.<br class=""><br class="">translate_all_terms(_, [], !_T).<br class=""><br class=""></font><div class=""><font face="MonoidNerdFontComplete-Regular" size="2" class="">translate_all_terms(R, [ Term | Terms ], !T) :-<br class=""></font><div class=""><font face="MonoidNerdFontComplete-Regular" size="2" class=""> TPos = snpos(Term),<br class=""> ( if Term = sexp(Spos, [ tk(Tpos,F) | Args ]) then<br class=""> (<br class=""> is_illegal_inst(F)<br class=""> -><br class=""> syntax.error(TPos, top_level_form_required, !T)<br class=""> ;<br class=""> (<br class=""> bifmap(F, _Inst)<br class=""> -><br class=""> % FELT function call<br class=""> syntax.error(TPos, msg("this is a felt call"), !T)<br class=""> ;<br class=""> do_gencall(0, R,<br class=""> <b class="">sexp(Spos, [tk(Tpos,F) | Args ]), % <— the change!</b><br class=""> !T)</font></div><div class=""><font face="MonoidNerdFontComplete-Regular" class=""><font size="2" class=""><span class="Apple-tab-span" style="white-space: pre;"> </span>% it was: do_gencall(0, R, Term, !T),<br class=""> )<br class=""> )</font></font></div><div class=""><font face="MonoidNerdFontComplete-Regular" class=""><font size="2" class=""> else<br class=""> syntax.error(TPos, expected_s_expression, !T)<br class=""> ),<br class=""> translate_all_terms(R, Terms, !T).<br class=""><br class=""></font></font><div>and for completeness:</div><div><br class=""></div><div><font face="MonoidNerdFontComplete-Regular" size="2" class="">:- pred do_gencall(int, renderer, snode, tcon, tcon).<br class="">:- mode do_gencall(in, renderer, in(sexp_ne), in, out) is det.<br class="">:- inst sexp_ne for snode/0 ---> sexp(ground, non_empty_list).<br class=""><br class="">do_gencall(_L, R, sexp(_, [Functor|Args]), !T) :-<br class=""></font></div><div><font face="MonoidNerdFontComplete-Regular" size="2" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>:</font></div><div><br class=""></div><div>I got a huge great compiler message compiler message which was, I think, trying to tell me that the type of Term was sexp(ground, ground), which thanks to your previous response I now fully understood! In order to remove the error message I had to work out that, in order to fully satisfy the constraint of an expected non empty list, that I had to explicitly construct the term again, in situ at the call site so that it was plan to the compiler that lo! here is a non empty list in the expected position…it compiled and the code runs again once more.</div><div><br class=""></div><div>The error message was this:</div><div><br class=""></div><div><font face="MonoidNerdFontComplete-Regular" size="2" class="">translate.m:216: In clause for `translate_all_terms((translate.renderer), in,<br class="">translate.m:216: in, out)':<br class="">translate.m:216: mode error in conjunction. The next 3 error messages<br class="">translate.m:216: indicate possible causes of this error.<br class="">translate.m:216: <br class="">translate.m:205: In clause for `translate_all_terms((translate.renderer), in,<br class="">translate.m:205: in, out)':<br class="">translate.m:205: in argument 3 of call to predicate `translate.do_gencall'/5:<br class="">translate.m:205: mode error: variable `Term' has instantiatedness<br class="">translate.m:205: `bound(sexp(ground, ground))',<br class="">translate.m:205: expected instantiatedness was<br class="">translate.m:205: named inst sexp_ne,<br class="">translate.m:205: which expands to<br class="">translate.m:205: bound(<br class="">translate.m:205: sexp(<br class="">translate.m:205: ground,<br class="">translate.m:205: named inst list.non_empty_list,<br class="">translate.m:205: which expands to<br class="">translate.m:205: bound(<br class="">translate.m:205: '[|]'(ground, ground)<br class="">translate.m:205: )<br class="">translate.m:205: )<br class="">translate.m:205: ).</font></div><div><br class=""></div><div>I think I understood it enough to figure out the solution, so thanks again for the enlightening responses.</div><div>I think this is one of the nicest language lists I’ve had the pleasure to be a member of!</div><div><br class=""></div><div>Thanks,</div><div>Sean.</div><div><br class=""></div><div><br class=""></div><div><br class=""><blockquote type="cite" class=""><div class="">On 7 Nov 2021, at 09:24, 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 Sun, 7 Nov 2021, Sean Charles (emacstheviking) wrote:<br class=""><br class=""><blockquote type="cite" class="">I made your suggested change, it works fine but… can I push it a<br class="">little further? I went back to the Mercury crash course page as it<br class="">mentioned non_empty_list, I found no references in the reference guide<br class="">or the library but plenty in the source code for my ROTD version… but<br class="">I am unsure of the syntax, if possible, of stating that the the list<br class="">of terms to the sexp() functor is guaranteed to be non empty because:<br class=""> ( if Term = sexp(_, [ tk(_,F) | _ ]) then<br class="">already established that fact prior to the call…but this leads me to<br class="">my final question: —should— I be doing this? I ask because<br class="">:- mode do_gencall(in, renderer, in(sexp), in, out) is det.<br class="">do_gencall(_L, R, sexp(_, [Functor|Args]), !T) :-<br class="">This obv. fails because the unification into head and tail could fail,<br class="">but if I declare it as semidet then obv. I have to check the call<br class="">further up the code, again I totally understand why but my question<br class="">then is, should I do this at all ? I have not used Haskell in a while<br class="">now, plumping for Mercury, but I was getting reasonably proficient at<br class="">the concept of `programming with types` and this feels similar. If I<br class="">instructed the compiler that the mode was something like<br class="">:- mode do_gencall(in, renderer, in(sexp-with-non-empty-args), in, out) is det.<br class="">then presumably the predicate could remain as `det`, everybody is<br class="">happy and my code feels more rigorous for it. I refer to the sample of<br class="">code in the file ‘./mercury-srcdist-20.06.1/browser/parse.m’ , lines<br class="">305 to 307:<br class="">:- pred lexer_arg(list(char)::in(non_empty_list), list(token)::out) is det.<br class="">lexer_arg([Head | Tail], Toks) :-<br class="">This clearly shows to me that by using non_empty_list the compiler is<br class="">happy to let me deconstruct the list in the clause head with no<br class="">problems. I am not sure how to combine the mode you showed me with the<br class="">addition of the non empty constraint as well that’s all!<br class=""></blockquote><br class="">As a separate named inst:<br class=""><br class=""> :- inst sexp_with_non_empty_args for snode/0<br class=""> ---> sexp(ground, non_empty_list).<br class=""><br class=""> :- mode do_gencall(in, renderer, in(sexp_with_non_empty_args),<br class=""> in, out) is det.<br class=""><br class="">or inline:<br class=""><br class=""> :- mode do_gencall(in, renderer, in(bound(sexp(ground, non_empty_list))),<br class=""> in, out) is det.<br class=""><br class="">Julien</div></div></blockquote></div><br class=""></div></div></div></body></html>