% Unification on an explicit representation of terms % Purposely not using built-in meta-programming facilities of Prolog % type predicates for terms, sequences of terms, and substitutions % do not restrict terms that can represent variables or % function symbols isvar(X). isfunc(F). term(app(F, Ts)) :- isfunc(F), terms(Ts). term(var(X)) :- isvar(X). terms([]). terms([T | Ts]) :- term(T), terms(Ts). % for substitutions, do not enforce additional assumptions subst([]). subst([for(T, X) | Theta]) :- term(T), isvar(X), subst(Theta). % apply(t, theta, t') if t' = t theta apply(var(X), [], var(X)). apply(var(X), [for(T, X) | Theta], T). apply(var(X), [for(S, Y) | Theta], XTheta) :- X \= Y, apply(var(X), Theta, XTheta). apply(app(F, Ts), Theta, app(F, TsTheta)) :- applys(Ts, Theta, TsTheta). applys([], Theta, []). applys([T | Ts], Theta, [TTheta | TsTheta]) :- apply(T, Theta, TTheta), applys(Ts, Theta, TsTheta). % compose(sigma, theta, sigma') if sigma' = sigma theta compose([], Theta, Theta). compose([for(T,X) | Sigma], Theta, [for(TTheta,X) | SigmaTheta]) :- apply(T, Theta, TTheta), compose(Sigma, Theta, SigmaTheta). % unify(t, s, theta) if t =.= s | theta unify(var(X), var(X), []). unify(var(X), var(Y), [for(var(Y),X)]) :- X \= Y. unify(var(X), app(F, Ts), [for(app(F, Ts), X)]) :- not_occur(X, app(F, Ts)). unify(app(F, Ts), var(X), [for(app(F, Ts), X)]) :- not_occur(X, app(F, Ts)). unify(app(F, Ts), app(F, Ss), Theta) :- unifys(Ts, Ss, Theta). unifys([], [], []). unifys([T | Ts], [S | Ss], Theta1Theta2) :- unify(T, S, Theta1), applys(Ts, Theta1, Ts1), applys(Ss, Theta1, Ss1), unifys(Ts1, Ss1, Theta2), compose(Theta1, Theta2, Theta1Theta2). % not_occur(X, T) if x not in FV(T) not_occur(X, var(Y)) :- X \= Y. not_occur(X, app(F, Ts)) :- not_occurs(X, Ts). not_occurs(X, []). not_occurs(X, [T | Ts]) :- not_occur(X, T), not_occurs(X, Ts). /* % sample queries: % first should fail due to occurs-check unify(app(plus, [app(z, []), var(n), var(n)]), app(plus, [app(z, []), app(s, [var(m)]), var(m)]), Theta). % second one should succeed (see lecture notes) unify(app(plus, [app(s, [var(m1)]), var(n1), app(s, [var(p1)])]), app(plus, [app(s, [app(z, [])]), app(s, [app(s, [app(z, [])])]), var(p)]), Theta). % exponential example for n = 3 % there are 8 occs of "a" in subst for x0 unify(app(g, [var(x0), var(x1), var(x2), var(x3)]), app(g, [app(f, [var(x1), var(x1)]), app(f, [var(x2), var(x2)]), app(f, [var(x3), var(x3)]), app(a, [])]), Theta). */