Re: [m-users.] Returning a predicate from a function

Julien Fischer <[email protected]>
Newsgroups gmane.comp.lang.mercury.general
Message-ID <[email protected]>
Hi Mark,

On Thu, 22 Dec 2022, Mark Clements wrote:

> Dear Mercury users,
> 
> Is there any way to write a function that takes a predicate and returns a transformed predicate without (a) naming a new predicate or (b) using a
> lambda? In practice, I would like to move the lambda to a function. However, the following code gives an error: "Cannot unify two terms of type
> `(pred float)'". Can I assume that this is outside of Mercury's mode system?

Unifying (or comparing) higher-order terms is not allowed by Mercury,
but that's not the problem here ...

> :- module tests.
> :- interface.
> :- import_module io.
> :- pred main(io::di, io::uo) is det.
> 
> :- implementation.
> :- import_module float, ranges, solutions.
> :- use_module math.
> 
> main(!IO) :-
>     test1(!IO), % OK
>     test2(!IO). % Does not compile
> 
> :- pred test1(io::di, io::uo) is det.
> test1(!IO) :-
>     Data = (pred(Y::out) is nondet :- nondet_member(I,range(1,5)), Y = float(I)), % some data
>     LnData = (pred(Y::out) is nondet :- Data(X), Y = math.ln(X)), % a transformation
>     aggregate(LnData, print_line, !IO).
> 
> :- pred test2(io::di, io::uo) is det.
> test2(!IO) :-
>     Data = (pred(Y::out) is nondet :- nondet_member(I,range(1,5)), Y = float(I)), % some data
>     LnData = f_ln(Data), %% This transformation does not compile:(
>     aggregate(LnData, print_line, !IO).
> 
> :- func f_ln(pred(float)::(pred(out) is nondet)) = (pred(float)::(pred(out) is nondet)).

This function declaration doesn't say what you think it does;
specifically the expanded mode of the function return value as written
is:

     pred(out) is nondet >> pred(out) is nondet

That's effectively an input, which is why the compiler is complaining
about attempted higher-order unifications.  What we want is for the
expanded mode of the return value to be:

     free >> pred(out) is nondet

That is: the return value has inst free before a call to f_ln and has
inst (pred(out) is nondet) after a call to it.

The above mode is more usually written as:

     out(pred(out) is nondet)

Putting it all together the declaration of f_ln should be:

    :- func f_ln(pred(float)::(pred(out) is nondet)) = (pred(float)::(out(pred(out) is nondet))).

> f_ln(Pred) = (pred(Y::out) is nondet :- Pred(X), Y is math.ln(X)).

As others have mentioned, Mercury does not support Prolog's is, just use
=.

Julien.

_______________________________________________
users mailing list
[email protected]
https://lists.mercurylang.org/listinfo/users
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.