.type T <: symbol

.decl A (a:T, b:T)
.decl B (a:T, b:T)
.decl C (a:T, b:T)

// Both, x and z are grounded
A(x,z) :- B(x,y), C(y,z).

// Ungrounded -- negation is not an atom
A(x,z) :- B(x,y), !C(y,z).

// x in the head and constraint is not grounded
A(x,z) :- B(z,y), z > x.

// l in negation is not grounded
A(x,z) :- B(x,y), C(y,z), !C(y,l).

// l in constraint is not grounded
A(x,z) :- B(x,y), C(y,z), y > l.

.decl N (a:T, b:number)

// unary functor ord(x) grounded if x grounded
N(x,z) :- B(x,y), z = ord(y).

// binary functor cat(x, y) grounded if x and y grounded
A(x,z) :- B(x,y), z = cat(x, y).

// ternary functor substr(y, 0, 1) grounded if y, 0, and 1 are grounded
A(x,z) :- B(x,y), z = substr(y, 0, 1).

// binary functor cat(x, y) not grounded if y not grounded
A(x,z) :- B(x, _), z = cat(x, y).
