Three kinds of rules that we can use for the simplification process
X + 0 = X.
X + (succ Y) = succ (X + Y).
the following rules are inductive consequences and can be used for
simplification:
0 + Y = Y.
(succ X) + Y = succ (X + Y).
type letters = a | b | c.
pred on: letters * letters.
on (a, b).
on (b, c).
pred above: letters * letters.
above (X, Y) :- on (X, Y).
above (X, Y) :- above (X, Z), on (Z, Y).
solve above (a, a).
... infinite loop ...
solve above (a, c).
... infinite loop ...
With normalization we can reach a result:
pred on: letters * letters.
on (a, b).
on (b, c).
pred above: letters * letters.
above (X, Y) :- on (X, Y).
above (X, Y) :- above (X, Z), on (Z, Y).
norm ~ above (X, X).
norm ~ above (X, Y) :- above (Y, X).
solve above (a, a).
> false.
solve above (a, c).
> false.
The technique of normalization is also useful to handle equations
between constructors, that cannot be handled by pure narrowing.
The next example defined the function less-than-or-equal-to over
integer numbers with a predecessor constructor:
type nat = 0 | succ nat | pre nat.
fun leq : nat -> nat -> bool.
leq 0 0.
~ leq 0 (pre 0).
leq 0 (succ X) :- leq 0 X.
~ leq 0 (pre X) :- ~ leq 0 X.
leq (succ X) Y = leq X (pre Y).
leq (pre X) Y = leq X (succ Y).
norm succ (pre X) = X.
norm pre (succ X) = X.
Go to index