Once you have created a higher-order predicate term (sometimes known as a closure), the next thing you want to do is to call it. For predicates, you use the builtin goal call/N:
call(Closure2, Arg1, Arg2)
A higher-order predicate call. ‘call(Closure)’ just calls the specified higher-order predicate term. The other forms append the specified arguments onto the argument list of the closure before calling it.
For example, the goal
Result to the sum of ‘[1, 2, 3]’, i.e. to 6.
For functions, you use the builtin expression apply/N:
apply(Closure2, Arg1, Arg2)
A higher-order function application. Such a term denotes the result of invoking the specified higher-order function term with the specified arguments.
For example, given the definition of ‘Double’ above, the goal
List = apply(Double, [1, 2, 3])
would be equivalent to
List = scalar_product(2, [1, 2, 3])
and so for a suitable implementation of the function ‘scalar_product/2’
this would bind
List to ‘[2, 4, 6]’.
One extremely useful higher-order predicate in the Mercury standard library is ‘solutions/2’, which has the following declaration:
:- pred solutions(pred(T), list(T)). :- mode solutions(pred(out) is nondet, out) is det.
The term which you pass to ‘solutions/2’ is a higher-order predicate term. You can pass the name of a one-argument predicate, or you can pass a several-argument predicate with all but one of the arguments supplied (a closure). The declarative semantics of ‘solutions/2’ can be defined as follows:
solutions(Pred, List) is true iff all [X] (call(Pred, X) <=> list.member(X, List)) and List is sorted.
where ‘call(Pred, X)’
invokes the higher-order predicate term
Pred with argument
and where ‘list.member/2’
is the standard library predicate for list membership.
In other words, ‘solutions(Pred, List)’ finds all the values of
for which ‘call(Pred, X)’ is true,
collects these solutions in a list,
sorts the list, and returns that list as its result.
Here is an example: the standard library defines a predicate
:- pred list.perm(list(T), list(T)). :- mode list.perm(in, out) is nondet.
which succeeds iff List is a permutation of List0. Hence the following call to solutions
should return all the possible permutations of the list ‘[3,1,2]’ in sorted order:
L = [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]].
See also ‘unsorted_solutions/2’ and ‘solutions_set/2’, which are defined in the standard library module ‘solutions’ and documented in the Mercury Library Reference Manual.