Informally, one of the two types in CLP( ) is given by the real numbers, and the other by the remaining ground (variable-free) terms. Strictly speaking, CLP( ) is a statically typed language in the sense that variables, uninterpreted functors and predicates in a program must be used in a consistent way with respect to their type. That is, each variable and each argument of every predicate and uninterpreted functor is first acknowledged to be of a certain type. The program is then considered to be ill-typed if, for example, a variable appears both in a functor constraint and an arithmetic constraint; similarly, the program is ill-typed if one occurrence of a predicate or uninterpreted functor has a number in the first argument while, in another occurrence, it has a functor term in the first argument.
For programming convenience, however, CLP( ) does not perform such type-checking at compile time. This decision is based on the fact that it is often useful to overload a symbol; for example, one may want a database p of both numbers and letters:
p(2).
p(a).
p(b).
p(1).
and one may run a goal containing p(X) and some constraints used for selection within the database. Note that by not performing type-checking, one can have a runtime type error. That is, an execution sequence which fails because of a ``type clash''. Often such failures indicate that there is an error in the program. The CLP( ) system will not distinguish such failures from failures obtained from well-typed constraints.
A straightforward way of thinking about the type issue when writing CLP( ) programs is that whenever an arithmetic term appears in a rule, for each variable X therein, we can implicitly add a corresponding atom real(X) to the body of the rule. The system predicate real/1 is true just in case there is a real solution for X in the context of the current collection of constraints.