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
would bind ‘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
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 ‘X’, and where ‘list.member/2’ is the standard library predicate for list membership. In other words, ‘solutions(Pred, List)’ finds all the values of ‘X’ for which ‘call(Pred, X)’ is true, collects these solutions in a list, sorts the list, and returns that list as its result. Here’s an example: the standard library defines a predicate ‘list.perm(List0, List)’
:- 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.