10Higher-order Predicates

Logic variables which contain predicates may be used as the operator in predicate expressions:

 > (%which () (%let (p) (%and (%= p %knows) (p 'Odysseus 'TeX))))

'()

First the logic variable p is unified with the predicate %knows. In the expression

(p 'Odysseus 'TeX)

p is replaced by its value %knows to become

(%knows 'Odysseus 'TeX)

which succeeds.

This allows us to reason about predicates themselves. For example:

 > (%which (p) (%member p (list %knows %parent)) (p 'Odysseus 'Penelope))

'((p . #<procedure:relation>))

> (%more)

#f

Here we test which of the predicates %knows and %parent succeed when given the arguments 'Odysseus and 'Penelope.

The goal (%knows 'Odysseus 'Penelope) succeeds, but (%parent 'Odysseus 'Penelope) fails. Hence the only possible value for p is %knows.

However, logic variables used as a predicate must be instantiated. Since the set of defined predicates is not enumerable by Racklog, an unbound query will fail:

 > (%which (p) (p 'Odysseus 'Penelope)) #f

We can define a higher-order predicate which tests for unary predicates that succeed with 'Odysseus as their argument:

 (define (%odyssean p) (p 'Odysseus))

For example:

 > (%which () (%odyssean %computer-literate)) '()

This succeeds because (%computer-literate 'Odysseus) succeeds.

 > (%which () (%odyssean %compound)) #f

This fails because (%compound 'Odysseus) fails.

This also works if the predicate argument is a logic variable:

 > (%which (p) (%member p (list %computer-literate %compound)) (%odyssean p))

'((p . #<procedure:%computer-literate>))

Compare this with the example above.

Racklog also provides two predicates for defining relations involving arbitrary predicates.

10.1%apply

The %apply predicate is analogous to convential Racket apply.

The goal

(%apply P L)

succeeds if L is a list with elements E, ..., and if P is a predicate that accepts as many arguments as there are Es, and if the goal (P E ...) succeeds. For example:

 > (%which () (%apply %knows '(Odysseus TeX))) '()

In this case, the goal

(%apply %knows '(Odysseus TeX))

is equivalent to

(%knows 'Odysseus 'TeX)

The list argument to %apply must be sufficiently instantiated to determine its length. The following goals succeed:

 > (%which () (%apply %knows (list 'Odysseus 'TeX))) '() > (%which (X) (%apply %knows (list X 'TeX))) '((X . Odysseus))

but it is not possible to use %apply with a list of unknown length:

 > (%which (X Y) (%apply %knows (cons X Y))) #f

10.2%andmap

The %andmap predicate is analogous to convential Racket andmap.

The goal

(%andmap P L ...+)

succeeds if all the Ls are lists of equal length, and the goal (P E ...) succeeds for each set of elements E, ... of the Ls. For example:

 > (%which () (%andmap %knows '(Odysseus Penelope) '(TeX Prolog))) '()

In this case, the goal

(%andmap %knows '(Odysseus Penelope) '(TeX Prolog))

is equivalent to

 (%and (%knows 'Odysseus 'TeX) (%knows 'Penelope 'Prolog))