[m-users.] higher order issue: `ground` seen but expecting higher-order pred

Sean Charles (emacstheviking) objitsu at gmail.com
Thu Oct 6 03:13:40 AEDT 2022


I must be to stupid to get it, unusually, I am pasting the entire source file as it stands along with the error message, I just don't get it. I just don't today, apologies for the long post of source code. I've tried re-reading the relevant parts of the documentation but it's just not sinking in, the language is too technically dry and formal for my uneducated brain.

SOURCE CODE:

➜  fbnf cat -n fbnf.m
     1	%-----------------------------------------------------------------------------%
     2	%
     3	% File: fbnf.m
     4	% Main author: Sean Charles
     5	% Date: Sat Oct  1 19:48:26 2022
     6	%
     7	% FORTH but not FORTH
     8	%
     9	%-----------------------------------------------------------------------------%
    10	:- module fbnf.
    11
    12	:- interface.
    13	:- import_module io.
    14
    15	:- pred main(io::di, io::uo) is det.
    16
    17
    18	:- implementation.
    19
    20	:- import_module bool.
    21	:- import_module list.
    22	:- import_module map.
    23	:- import_module maybe.
    24	:- import_module stack.
    25	:- import_module string.
    26
    27
    28	%----------------------------------------------------------------------------%
    29
    30	main(!IO) :-
    31	    io.command_line_arguments(Args, !IO),
    32	    Arg = string.join_list(" ", Args),
    33	    io.format("ARG: %s\n", [s(Arg)], !IO),
    34
    35	    ( if string.is_empty(Arg) then
    36	        repl(initial_state, _, !IO)
    37	    else
    38	        interpret(string.words(Arg), initial_state, State1, !IO),
    39	        repl(State1, _, !IO)
    40	    ).
    41
    42	%----------------------------------------------------------------------------%
    43
    44	:- type lstr == list(string).
    45
    46	    % This is the WORD handler definition
    47	    %
    48	%:- type word_handler == (pred(fstate, fstate, io, io, lstr, lstr)).
    49	%:- inst word_handler == (pred(in, out, di, uo, in, out)is det).
    50
    51	:- type word_handler
    52	    --->   word_handler(
    53	              pred(
    54	                fstate::in, fstate::out,
    55	                io::di, io::uo,
    56	                lstr::in, lstr::out) is det
    57	           ).
    58
    59	:- type word_map == map(string, word_handler).
    60	:- type stack_entry == stack(int).
    61
    62	    %
    63	    % FBNF operating state
    64	    %
    65	:- type fstate
    66	    --->    fstate(
    67	                fs_compiling    :: bool,
    68	                fs_terminate    :: bool,
    69	                fs_dict         :: word_map,
    70	                fs_stack        :: stack_entry,
    71	                fs_error        :: maybe(string)
    72	            ).
    73
    74
    75	    % Create the initial state of the machine.
    76	    %
    77	:- func initial_state = (fstate::out) is det.
    78
    79	initial_state =
    80	    fstate(
    81	        no,                         % interpret mode
    82	        no,                         % terminate requested ?
    83	        initial_dictionary,         % core words
    84	        stack.init : stack_entry,   % initial empty stack
    85	        no                          % no error message
    86	    ).
    87
    88
    89	    % Create default system WORDS dictionary.
    90	    % Here we pre-load all the stock words that the user can build on
    91	    % during the course of the session.
    92	    %
    93	:- func initial_dictionary = (word_map::out) is det.
    94
    95	initial_dictionary = Map :-
    96	    some [!Words] (
    97	        !:Words = map.init,
    98
    99	        map.set(":",     word_handler(define_word), !Words),
   100	        map.set("bye",   word_handler(session_end), !Words),
   101	        map.set("words", word_handler(list_words),  !Words),
   102
   103	        Map = !.Words
   104	   ).
   105
   106	%----------------------------------------------------------------------------%
   107	%----------------------------------------------------------------------------%
   108	%
   109	%               System WORD Implementations
   110	%
   111	%----------------------------------------------------------------------------%
   112	%----------------------------------------------------------------------------%
   113
   114	    % ":" - define a new word.
   115	    %
   116	:- pred define_word(fstate::in, fstate::out, io::di, io::uo,
   117	    lstr::in, lstr::out) is det.
   118
   119	define_word(!State, !IO) -->
   120	    {
   121	        io.format("DEFINE WORD\n", [], !IO)
   122	    }.
   123
   124	    % "BYE" - terminate the current session.
   125	    %
   126	:- pred session_end(fstate::in, fstate::out, io::di, io::uo,
   127	    lstr::in, lstr::out) is det.
   128
   129	session_end(!State, !IO) -->
   130	    {
   131	        io.format("BYE\n", [], !IO)
   132	    }.
   133	    % "WORDS" - list all defined words.
   134	    %
   135	:- pred list_words(fstate::in, fstate::out, io::di, io::uo,
   136	    lstr::in, lstr::out) is det.
   137
   138	list_words(!State, !IO) -->
   139	    {
   140	        io.format("WORDS\n", [], !IO)
   141	    }.
   142
   143	%----------------------------------------------------------------------------%
   144
   145	    % Read-Eval-Print-Loop
   146	    %
   147	:- pred repl(fstate::in, fstate::out, io::di, io::uo) is det.
   148
   149	repl(!State, !IO) :-
   150	    io.format("fbnf> ", [], !IO),
   151	    io.flush_output(!IO),
   152	    io.read_line_as_string(Res, !IO),
   153	    (
   154	        Res = ok(Str),
   155	        interpret(string.words(Str), !State, !IO),
   156	        repl(!State, !IO)
   157	    ;
   158	        Res = error(Err),
   159	        io.format("error: %s\n", [s(io.error_message(Err))], !IO),
   160	        repl(!State, !IO)
   161	    ;
   162	        Res = eof,
   163	        io.format("Bye!\n", [], !IO)
   164	    ).
   165
   166	%----------------------------------------------------------------------------%
   167
   168	% from "Starting FORTH" ...
   169	%
   170	% This will activate a word called INTERPRET, also known as the “text
   171	% interpreter.” The text interpreter scans the input stream, looking for strings
   172	% of characters separated by spaces. When a string is found, it is looked up in
   173	% the dictionary.
   174	%
   175	% If the word is in the dictionary, it is pointed out to a word called EXECUTE.
   176	% EXECUTE executes the definition (in this case an asterisk is printed).
   177	% Finally, the interpreter says everything’s “ok.”
   178
   179	    % 'INTERPRET'
   180	    % Process the current input stream of user tokens.
   181	    % If an error is detected then we abort the loop and abandon the input.
   182	    % Anything processed up to the error remains intact though this may or may
   183	    % not lead to a safe state (TBD).
   184	    %
   185	:- pred interpret(list(string)::in, fstate::in, fstate::out,
   186	    io::di, io::uo) is det.
   187
   188	interpret(Words, !State, !IO) :-
   189	    compiling(no, !State),
   190	    interp1(Words, !State, !IO).
   191
   192
   193	:- pred interp1(list(string)::in, fstate::in, fstate::out,
   194	    io::di, io::uo) is det.
   195
   196	interp1([], !_, !_).
   197
   198	interp1([W|Ws], !State, !IO) :-
   199	    io.format("interp1: %s\n", [s(W)], !IO),
   200	    execute(W, Ws, Rest, !State, !IO),
   201	    flush_error(HadError, !State, !IO),
   202	    ( if HadError = yes then
   203	        true % abandon ship.
   204	    else
   205	        interp1(Rest, !State, !IO)
   206	    ).
   207
   208	    % 'EXECUTE'
   209	    % Find the word in the dictionary so we can invoke it, if it's not
   210	    % found we want to record the error and terminate processing.
   211	    %
   212	:- pred execute(string::in, list(string)::in, list(string)::out,
   213	    fstate::in, fstate::out, io::di, io::uo) is det.
   214
   215	execute(Word, Words, Rest, !State, !IO) :-
   216	    Dict =  fs_dict(!.State),
   217	    ( if map.search(Dict, Word, word_handler(Entry)) then
   218	        Entry(!State, !IO)
   219	    else
   220	        set_error(string.format("word not found: %s\n",
   221	            [s(Word)]), !State)
   222	    ),
   223	    Rest = Words.
   224
   225	%----------------------------------------------------------------------------%
   226	%----------------------------------------------------------------------------%
   227	%
   228	% STATE change operations
   229	%
   230	%----------------------------------------------------------------------------%
   231	%----------------------------------------------------------------------------%
   232
   233	    % Set 'compiling' mode as indicated.
   234	    %
   235	:- pred compiling(bool::in, fstate::in, fstate::out) is det.
   236
   237	compiling(Mode, !State) :-
   238	    !:State = !.State ^fs_compiling := Mode.
   239
   240	:- func is_compiling(fstate::in) = (bool::out) is det.
   241
   242	is_compiling(S) = S ^fs_compiling.
   243
   244
   245	    % Set an error message into the state.
   246	    %
   247	:- pred set_error(string::in, fstate::in, fstate::out) is det.
   248
   249	set_error(Message, !State) :-
   250	    !:State = !.State ^fs_error := yes(Message).
   251
   252	    % Flush (by writing) the current error message.
   253	    % Flushed will be 'yes' if there was an error in the state record
   254	    % and this will cause the current processing to abort.
   255	    %
   256	:- pred flush_error(bool::out, fstate::in, fstate::out, io::di, io::uo) is det.
   257
   258	flush_error(Flushed, !State, !IO) :-
   259	    (if yes(Error) = !.State ^ fs_error then
   260	        io.format("error: %s\n", [s(Error)], !IO),
   261	        Flushed = yes
   262	    else
   263	        Flushed = no
   264	    ).
   265
   266	%----------------------------------------------------------------------------%
   267	:- end_module fbnf.
   268	%----------------------------------------------------------------------------%

ERROR OUTPUT:
➜  fbnf cat fbnf.err
fbnf.m:218: In clause for predicate `execute'/7:
fbnf.m:218:   in argument 1 (i.e. the predicate term) of higher-order predicate
fbnf.m:218:   call:
fbnf.m:218:   type error: variable `Entry' has type
fbnf.m:218:     `pred(
fbnf.m:218:       fbnf.fstate :: builtin.in,
fbnf.m:218:       fbnf.fstate :: builtin.out,
fbnf.m:218:       io.state :: builtin.di,
fbnf.m:218:       io.state :: builtin.uo,
fbnf.m:218:       list.list(string) :: builtin.in,
fbnf.m:218:       list.list(string) :: builtin.out
fbnf.m:218:     ) is det',
fbnf.m:218:   expected type was
fbnf.m:218:     `pred(
fbnf.m:218:       V_7,
fbnf.m:218:       V_8,
fbnf.m:218:       V_9,
fbnf.m:218:       V_10
fbnf.m:218:     )'.
fbnf.m:218:   The partial type assignment was:
fbnf.m:218:     Word_8: string
fbnf.m:218:     Words_9: list.list(string)
fbnf.m:218:     Rest_10: list.list(string)
fbnf.m:218:     Dict_13: tree234.tree234(string, fbnf.word_handler)
fbnf.m:218:     Entry_14: (pred((fbnf.fstate :: builtin.in), (fbnf.fstate ::
fbnf.m:218:     builtin.out), (io.state :: builtin.di), (io.state ::
fbnf.m:218:     builtin.uo), (list.list(string) :: builtin.in),
fbnf.m:218:     (list.list(string) :: builtin.out)) is det)
fbnf.m:218:     STATE_VARIABLE_State_0_15: fbnf.fstate
fbnf.m:218:     STATE_VARIABLE_State_16: fbnf.fstate
fbnf.m:218:     STATE_VARIABLE_IO_0_17: io.state
fbnf.m:218:     STATE_VARIABLE_IO_18: io.state
fbnf.m:218:     V_19: fbnf.word_handler


It's basically the same error I had last time via a different route as far as my limited brain can tell. Some days this higher-order stuff just makes no sense to me at all how Mercury does it.

Sorry.


> On 5 Oct 2022, at 08:59, Sean Charles (emacstheviking) <objitsu at gmail.com> wrote:
> 
> Thanks Julien, I will try that.
> 
> About the state vars/DCG... yes, I don't like it either and today I am going to remove the DCG style... I am such an old Prolog stalwart that sometimes I do it without realising it!  :D    And my brain isn't 100% yet; as I told Volker, I recently had 70% of my liver removed (cancer) and the resulting brain fog has been, shall we say, amusing to observe and very frustrating to live with, but it gets clearer ever day now.
> 
> I do remember a post from Volker a long time ago on a very similar matter but try as I might I just couldn't find it for reference.
> 
> Thanks again,
> Sean.
> 
> 
>> On 5 Oct 2022, at 04:25, Julien Fischer <jfischer at opturion.com> wrote:
>> 
>> 
>> Hi,
>> 
>> On Tue, 4 Oct 2022, Sean Charles (emacstheviking) wrote:
>> 
>>> I am fleshing out a VERY loose forth type system, I have the following definitions to allow me to set up a map of word names and there handlers:
>>> :- type lstr == list(string).
>>> :- type word_handler == (pred(fstate, fstate, io, io, lstr, lstr)).
>>> :- inst word_handler == (pred(in, out, di, uo, in, out)is det).
>>> :- type word_map == map(string, word_handler).
>>> :- type stack_entry == stack(int).
>> 
>> As Volker mentioned, this won't work as the inst of nearly every output
>> argument in the map module is ground and the higher-order inst will be
>> lost.
>> 
>> An alternative would be to use combined higher-order types and insts and
>> define the word_handler type as:
>> 
>>   :- type word_handler
>>       --->   word_handler(pred(fstate::in, fstate::out, io::di, io::uo, lstr::in, lstr::out) is det).
>> 
>> That should do what you want with fairly minimal changes elsewhere
>> (mainly accounting for the the word_handler wrapper that is now around
>> the higher-order term).
>> 
>> ...
>> 
>>> I am not sure the DCG style will remain but it's pure proof of concept / exploratory at the moment.
>> 
>> IMO, mixing DCGs and state variables like that looks weird.
>> 
>> Julien.
> 

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


More information about the users mailing list