currying higher-order predicates

Fergus Henderson fjh at
Tue Apr 22 12:04:42 AEST 1997

Bart Demoen, you wrote:
> Maybe I can get help from you with some other problem: the following
> is a bit clumsily declared I suppose, but the idea is: I have a
> closure which works on 2 arguments; I want to construct a closure that
> works on one argument by providing the first argument; how can I do
> that - in the code below, when I use call instead of apply, the
> compiler tells me to use apply;

Ah, not quite.  It tells you "if you are trying to call a higher-order
function, you should use apply".  But you're not doing that, you're
trying to curry (not call) a higher-order predicate (not function).

> when using apply, it tells me the types are wrong

> :- pred b(pred(list(int),int),pred(int)).
> :- mode b(((pred(in,out) is det) -> (pred(in,out) is det)),
> 	  (free -> (pred(out) is det))) is det.
> b(X,Y) :- Y = apply(X,[4,5,6]).

In Mercury call/N cannot be curried.
You can only curry predicates (or functions), and call/N is
a builtin language construct, not a predicate.
(The main reason for this is that allowing currying of call/N would
make type checking more difficult.)

There are several simple solutions:

	% in Mercury >= 0.7
	b(X,Y) :- Y = (pred(Z::out) is det :- X([4,5,6],Z).

	% in Mercury >= 0.5
	b(X,Y) :- Y = lambda([Z::out] is det, call(X, [4,5,6], Z)).

	% in Mercury >= 0.5
	b(X,Y) :- Y = my_call(X, [4,5,6]).

	:- pred my_call(pred(T1, T2), T1, T2).	% pred decl optional
	:- mode my_call(pred(in, out) is det, in, out) is det.
	my_call(X, Y, Z) :- call(X, Y, Z).

This is not documented very well.  I'll add some documentation to
the Mercury language reference manual, and add a pointer to that
documentation to the compiler error message.  Thanks for the suggestion.


Fergus Henderson <fjh at>   |  "I have always known that the pursuit
WWW: <>   |  of excellence is a lethal habit"
PGP: finger fjh at         |     -- the last words of T. S. Garp.

More information about the users mailing list