[m-users.] Higher-order predicate issue

Sean Charles (emacstheviking) objitsu at gmail.com
Sun Oct 3 08:11:20 AEDT 2021


Hi Peter,

Thank you very much indeed. It has taken me the best part of my day here but I have finally managed to understand things to the point where I now have what I would call ’standard higher order behaviours’ that Haskell provides for example. And more remarkably, I think, after many hours of writing small test programs to grok it, that I may be in serious danger of understanding what’s going on, at least in part!

The final working code feels clean now, I am sure you guys would shudder but here it is as  a summary:

:- type renderer == (pred(render_inst, rop_error, tcon, tcon)).
:- mode renderer == (pred(in, out, in, out) is det).

my top level processing function is now declared as:

:- pred translate_top_level_term(renderer, lsnode, tcon, tcon, io, io).
:- mode translate_top_level_term(renderer, in,     in,   out,  di, uo) is det.

and the intermediate level evaluation is:

:- pred eval(renderer, location, instruction, lsnode, renderout, tcon, tcon).
:- mode eval(renderer, in, in, in, out, in, out) is semidet.

It all works well but there is ONE fly left in the ointment… I currently have some inline code to decide on what target backend is going to do the rendering, currently there is only one but this code is to prove that I can have many:

        LCTarget = string.to_lower(Target),
        ( if LCTarget = "php" then
            Renderer = target_c.render
        else
            Renderer = target_c.render
        ),
        % Renderer = get_target_renderer(Target),

The commented out line I cannot get to work, basically I moved that code into a small helper function for code clarity:

:- func get_target_renderer(string::in) = (renderer::out).

get_target_renderer(T) = R :-
    LCTarget = string.to_lower(T),
    ( if LCTarget = "php" then
        R = target_c.render
    else
        R = target_c.render
    ).

It compiles but when I try to use it seven types of hell break loose and I don’t understand the message, pasted at the end, and I would very much appreciate it if you had the time to explain what I have done this time to upset the compiler that tolerates me so wonderfully most of the time.

Again, thanks for that reply, it got me thinking, learning and tinkering to the point of success, mostly!
Sean.

————
translate.m:143: In clause for `translate(in, in, in, di, uo)':
translate.m:143:   mode error in conjunction. The next 13 error messages
translate.m:143:   indicate possible causes of this error.
translate.m:143:   
translate.m:126:   In clause for `translate(in, in, in, di, uo)':
translate.m:126:   in argument 1 (i.e. the predicate term) of higher-order
translate.m:126:   predicate call:
translate.m:126:   mode error: variable `Renderer' has instantiatedness
translate.m:126:   `ground',
translate.m:126:   expecting higher-order pred inst of arity 4.
translate.m:143:   
translate.m:128:   In clause for `translate(in, in, in, di, uo)':
translate.m:128:   in argument 1 of call to function `string.string'/1:
translate.m:128:   mode error: variable `Result' has instantiatedness `free',
translate.m:128:   expected instantiatedness was `ground'.
translate.m:143:   
translate.m:128:   In clause for `translate(in, in, in, di, uo)':
translate.m:128:   in argument 2 of call to predicate `io.format'/4:
translate.m:128:   mode error: variable `V_45' has instantiatedness `free',
translate.m:128:   expected instantiatedness was `ground'.
translate.m:143:   
translate.m:130:   In clause for `translate(in, in, in, di, uo)':
translate.m:130:   in argument 5 of call to predicate
translate.m:130:   `translate.translate_top_level_term'/6:
translate.m:130:   unique-mode error: the called procedure would clobber its
translate.m:130:   argument, but variable `STATE_VARIABLE_IO_46' is still live.
translate.m:143:   
translate.m:139:   In clause for `translate(in, in, in, di, uo)':
translate.m:139:   in argument 1 of call to function `list.reverse'/1:
translate.m:139:   mode error: variable `V_52' has instantiatedness `free',
translate.m:139:   expected instantiatedness was `ground'.
translate.m:143:   
translate.m:139:   In clause for `translate(in, in, in, di, uo)':
translate.m:139:   in argument 1 of functor `reverse/1':
translate.m:139:   mode error in unification of `STATE_VARIABLE_T_50' and
translate.m:139:   `translate.tcon(V_107, V_52, V_108, V_109)'.
translate.m:139:   Variable `STATE_VARIABLE_T_50' has instantiatedness `free',
translate.m:139:   term `translate.tcon(V_107, V_52, V_108, V_109)' has
translate.m:139:   instantiatedness
translate.m:139:     named inst translate.tcon(free, free, free, free).
translate.m:143:   
translate.m:140:   In clause for `translate(in, in, in, di, uo)':
translate.m:140:   in argument 1 of call to function `list.reverse'/1:
translate.m:140:   mode error: variable `V_53' has instantiatedness `free',
translate.m:140:   expected instantiatedness was `ground'.
translate.m:143:   
translate.m:140:   In clause for `translate(in, in, in, di, uo)':
translate.m:140:   in argument 1 of functor `reverse/1':
translate.m:140:   mode error in unification of `STATE_VARIABLE_T_50' and
translate.m:140:   `translate.tcon(V_110, V_111, V_112, V_53)'.
translate.m:140:   Variable `STATE_VARIABLE_T_50' has instantiatedness `free',
translate.m:140:   term `translate.tcon(V_110, V_111, V_112, V_53)' has
translate.m:140:   instantiatedness
translate.m:140:     named inst translate.tcon(free, free, free, free).
translate.m:143:   
translate.m:141:   In clause for `translate(in, in, in, di, uo)':
translate.m:141:   in argument 1 of call to function `list.reverse'/1:
translate.m:141:   mode error: variable `V_54' has instantiatedness `free',
translate.m:141:   expected instantiatedness was `ground'.
translate.m:143:   
translate.m:141:   In clause for `translate(in, in, in, di, uo)':
translate.m:141:   in argument 1 of functor `reverse/1':
translate.m:141:   mode error in unification of `STATE_VARIABLE_T_50' and
translate.m:141:   `translate.tcon(V_113, V_114, V_54, V_115)'.
translate.m:141:   Variable `STATE_VARIABLE_T_50' has instantiatedness `free',
translate.m:141:   term `translate.tcon(V_113, V_114, V_54, V_115)' has
translate.m:141:   instantiatedness
translate.m:141:     named inst translate.tcon(free, free, free, free).
translate.m:143:   
translate.m:143:   In clause for `translate(in, in, in, di, uo)':
translate.m:143:   in argument 1 of call to predicate
translate.m:143:   `io.unsafe_set_io_state'/1:
translate.m:143:   unique-mode error: the called procedure would clobber its
translate.m:143:   argument, but variable `STATE_VARIABLE_Dbg_106' is still
translate.m:143:   live.
translate.m:143:   
translate.m:128:   In clause for `translate(in, in, in, di, uo)':
translate.m:128:   in argument 2 of call to predicate `io.format'/4:
translate.m:128:   in list element #0:
translate.m:128:   mode error in unification of `V_47' and `string.s(V_48)'.
translate.m:128:   Variable `V_47' has instantiatedness `free',
translate.m:128:   term `string.s(V_48)' has instantiatedness
translate.m:128:   `named inst string.s(free)'.
translate.m:143:   
translate.m:128:   In clause for `translate(in, in, in, di, uo)':
translate.m:128:   in argument 2 of call to predicate `io.format'/4:
translate.m:128:   mode error in unification of `V_45' and `list.[V_47 |
translate.m:128:   V_49]'.
translate.m:128:   Variable `V_45' has instantiatedness `free',
translate.m:128:   term `list.[V_47 | V_49]' has instantiatedness
translate.m:128:   `named inst list.'[|]'(free, unique([]))’.

and here is the full section of code, with line numbers…...

101 translate(Options, Target, AstTerms, !IO) :-
102         % TODO: Env = map.init(string, univ),
103         % TODO: replace !IO with a stream I open into a file!
104     some [!T]
105     (
106         % LCTarget = string.to_lower(Target),
107         % ( if LCTarget = "php" then
108         %     Renderer = target_c.render
109         % else
110         %     Renderer = target_c.render
111         % ),
112         Renderer = get_target_renderer(Target),
113
114         trace[io(!Dbg), runtime(env("FELT_TRN"))]
115         (ttrace(0, "selected target:%s\n%s\n",
116             [s(string(Renderer)), s(string(AstTerms))],
117             !Dbg)),
118
119         !:T = tcon(
120             Options,    % command line
121             [],         % output
122             [],         % warnings
123             []         % errors
124         ),
125
126         Renderer(include([pstring(pos(0,0,0),"testing")]),
127                 Result,!T),
128         io.format("TESTED OUTPUT: %s",[s(string(Result))], !IO),
129
130         translate_top_level_term(
131             Renderer,
132             AstTerms,
133             !T,
134             !IO
135         ),
136
137             % CodeList MAY be invalid of errors are present.
138             %          ^^^
139         Code     = reverse(output(!.T)),
140         Errors   = reverse(errors(!.T)), %sort by pos(!,_,_)
141         Warnings = reverse(warnings(!.T)),
142
143         trace[io(!Dbg), runtime(env("FELT_TRN"))]
144         (
145             ttrace(0, "%s:WARNINGS%s", [s(colour(yellow)),
146                 s(colour(reset))], !Dbg),
147             list.foldl(io.print_line, Warnings, !Dbg),
148
149             ttrace(0, "%s:ERRORS%s", [s(colour(red)),
150                 s(colour(reset))], !Dbg),
151             list.foldl(io.print_line, Errors, !Dbg),
152
153             ttrace(0, "%s:TRANSLATIONS%s", [s(colour(green)),
154                 s(colour(reset))], !Dbg),
155             list.foldl(io.print_line, Code, !Dbg),
156
157             io.format("\n**************\n", [], !Dbg),
158             list.foldl(render_op(0, Options), Code, !Dbg),
159             io.format("\n**************\n", [], !Dbg)
160         )
161     ).







> On 2 Oct 2021, at 02:57, Peter Wang <novalazy at gmail.com> wrote:
> 
> On Fri, 01 Oct 2021 21:27:40 +0100 "Sean Charles (emacstheviking)" <objitsu at gmail.com <mailto:objitsu at gmail.com>> wrote:
>> Hi,
>> 
>> I am trying to pass around a predicate to execute at a later point in my translation process:
>> 
>> :- type renderer == (pred(instruction, lstring, rop_error, tcon, tcon)).
>> :- inst renderer == (pred(in, in, out, in, out) is det).
>> 
>> then to set the renderer:
>> 
>>    Renderer = target_c.render
>> 
>> then I have a work in progress evaluation predicate:
>> 
>> :- pred eval(renderer::in, location::in, instruction::in, lsnode::in,
>>    renderout::out, tcon::in, tcon::out) is semidet.
> 
> The mode 'in' is defined as 'ground >> ground',
> so the pred-mode declaration declares that the first argument has
> initial inst 'ground' and final inst 'ground'.
> 
>> 
>> eval(Render, Pos, defvar, Args, Result, !T) :-
>>    trace[io(!Dbg), runtime(env("FELT_TRN"))]
>>    (sdump($pred, $line, Args, !Dbg)),
>> 
>>    ( if Args = [tk(Pos, VarName)] then
>>            %
>>            % this it not working well
>>            % ...what can be done to make it better ?
>>            %
>> 348     Render(defvar, lstring(Pos, VarName), CodeM, !T),
> 
> Renderer has inst 'ground' here, meaning it has no higher-order inst
> information, so it cannot be called. (It is possible to call a
> higher-order *function* term without higher-order inst information,
> but that is a special case.)
> 
> You need to change the mode of the first argument from 'in' to
> 'in(renderer)', which expands to 'renderer >> renderer',
> where 'renderer' refers to the inst you have defined earlier.
> There is no implied connection between the type name 'renderer'
> and the inst name 'renderer'.
> 
> Peter

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20211002/b8c5d94d/attachment-0001.html>


More information about the users mailing list