[m-users.] Reference manual 8.3.1, higher-order inst

Julien Fischer jfischer at opturion.com
Sat Apr 17 03:43:36 AEST 2021


Hi,

On Fri, 16 Apr 2021, fabrice nicol wrote:

> In the current ROTD Reference manual, chapter 8.3.1 on 'Building higher-order insts and modes', the inst/mode of higher-order predicates is defined as follows:
>
>       "If you want to define a predicate which returns a higher-order predicate term,
>
>        you would use a mode such as ‘free >> pred(…) is …’, or ‘out(pred(…) is … )’. For example:
>
>        :- pred foo(pred(int)).
>  :- mode foo(free >> pred(out) is det) is det.
> 
>  foo(sum([1,2,3]))."
> 
> Apparently though, at least from 20.06 on (not checked before), the
> 'free >>' part of of higher-order inst/mode declaration is outdated
> and causes compiler errors.

The mode declaration in the example is missing some parentheses.
It should be:

      :- mode foo(free >> (pred(out) is det)) is det.

(The parentheses are required because >> binds more strongly than is.)

However, it would be more usual to write the above as:

    :- mode foo(out(pred(out) is det)) is det.

> The following Mercury chunk code compiles and runs OK:
> 
> :- module new. 
> 
> :- interface.      
> 
> :- import_module io.  
> 
> :- pred main(io::di, io::uo) is det.
> 
> :- implementation.
> 
> :- import_module string, int.
> 
> :- pred check_10(pred(string, int), string).
> 
> :- mode check_10(pred(in, out) is det, in) is semidet.  
>                                                                                                                                      
> 
> check_10(Predicate, S) :- call(Predicate, S, L), L < 10. 
> 
> main(!IO) :- ( if check_10((pred(S::in, L::out) is det :- length(S, L)), "test_str")
> 
>              then  write_string("OK!", !IO) else write_string("NO!", !IO)).  
> 
> 
> Replacing 'pred(in, out)' with 'free >> pred(in, out)'  in the above mode declaration for 'check_10' causes a compiler (20.06 or DEV) error msg:
> 
> Error: no mode declaration for predicate `check_10'/2.
>    (Use `--infer-modes' to enable mode inference.)
>  Inferred :- mode check_10(di(/* unique */(pred(in, out) is det)),  di).                                                                                                                                                                   
>           
> In the mode declaration of the predicate `check_10': error: a
>  higher-order mode should have one of the following forms:
>   `pred(<mode1>, ...) is <detism>'
>    `any_pred(<mode1>, ...) is <detism>'
>    `func(<mode1>, ...) = <return_mode> is <detism>'
>    `any_func(<mode1>, ...) = <return_mode> is <detism>'

Same issue.  You'll obviously still get an error once you add
the parentheses since the resulting predicate is not mode correct.

> Also, for independent reasons, the example given in the manual
> (foo(sum[1,2,3])) does not compile. It triggers a "higher-order
> predicate unification error", but this is more understandable and can
> be fixed by changing the example.a

The above definitely won't compile since it should be sum([1, 2, 3]) not
sum[1, 2, 3]. With the parentheses added to the mode declaration and
an appropriate definition of sum/2, the verison in the reference manual
compiles,

I'm not quite sure how you arrived at the higher-order unification
error, possibly by changing the mode of the first argument to be an input?

> Unless I am mistaken or doing something wrong, a reference manual
> update would perhaps be appropriate.

Indeed, we'll correct it.

Julien.


More information about the users mailing list