4.1 The Language PRO L 107
As another, more realistic example, consider the ternary predicate app/3 that de-
scribes the concatenation of two lists:
app
(X, Y, Z) ⇐ X =[], Y = Z
app
(X, Y, Z) ⇐ X =[H|X
], Z =[H|Z
], app(X
, Y, Z
)
⇐
app(X, [Y, c] , [a, b, Z])
The first rule states that the list Z is the concatenation of lists X and Y in case X is
the empty list and Y is equal to Z. The second rule states that the list Z is also the
concatenation of lists X and Y if X and Z both contain H as the first element, and the
concatenation of the remaining part X
of X together with Y results in the remaining
part Z
of Z. Note that in logic programming languages, it is common practice to use
a slightly differentsyntax for the representation of lists: Head and body are separated
by means of the infix operator
|.
For a list with the elements X
1
,...,X
n
, we occasionally use the abbreviation
[X
1
,...,X
n
]. In contrastto OCAML,listelementsareseparated by acomma, instead
of a semicolon. Thus,
[]describes the empty list, [H|Z
] is the application of the list
constructor to H and Z
, and [a, b, Z] is the abbreviation for [a|[b|[Z|[ ]]]].
The programming language P
RO L allows not only queries about a result of a
concatenation. The different arguments of predicates are rather (at least in principle)
equivalent. Thus, rules and facts can be considered as constraints on the arguments
that must be satisfied for a fact to be derivable. The predicate app/3, for example,
formalizes what it means for a list Z to be the concatenation of lists X and Y.Itis
then left to the evaluation of the P
RO L program, to determine variable assignments
that satisfy these constraints.
AP
RO L program p is constructed as follows:
t ::
= a | X | _ | f (t
1
,...,t
n
)
g ::= q(t
1
,...,t
k
) | X = t
c ::
= q(X
1
,...,X
k
) ⇐ g
1
,...,g
r
a ::= ⇐ g
1
,...,g
r
p ::= c
1
...c
m
a
Aterm t is either an atom a, a variable X,ananonymous variable _, or theapplication
of a constructor f
/n to terms t
1
,...,t
n
. According to this convention the arity is an
important part of a constructor.
A goal g is either a literal, that is a call of a predicate q
/k for argument terms
t
1
,...,t
k
,oraunification X = t. In unifications, the left-hand side is always as-
sumedtobeavariableX, while the right side is an arbitrary term t.
Aclause c consists of a head and abody.Everyheadisoftheformq
(X
1
,...,X
k
)
with a predicate q/k and a list of (pairwise different) formal parameters. A body
consists of a (possibly empty) sequence of goals.
Aquery consistsofasequenceofgoals.Finally,a program consistsofasequence
of clauses, followed by a query.