Lecture 22 - Tue Nov 16 Notes by Dale Miller ----------------------- Implication in goals: D => G Add the clause D to the current program and attempt to prove G. Universal quantifier: pi x\ G Add a new constant, say c, and attempt to prove G[c/x] The sterile jar program ________________________________________________________________ module sterile. kind jar, germ type. type sterile jar -> o. type in germ -> jar -> o. type bug germ -> o. type dead germ -> o. type heated jar -> o. type j jar. sterile J :- pi b\ (bug b, in b J) => dead b. dead B :- heated J, in B J. heated j. ________________________________________________________________ If you load the query against this module, you will find that the query ?- sterile j. will succeed. The clause we showed for type checking an object-level abstract with simple types typeof (abs R) (arrow A B) :- pi x\ typeof x A => typeof (R x) B. makes use of both of these connectives. Here, a new constant is introduced and it will play the role of the bound variable, and a type for that variable is added to the program (for typeof). Consider briefly the program of unification using higher-order variables and meta-level alpha, beta, and eta conversion. In first-order logic, it is decidable (in linear time) whether or not a unification problem and be solved, and if it can be solved, a most general unifier can be produced. In higher-order unification, determining if a problem is solvable is undecidable, in general, and there is not necessarily a single most general unifier. Backtracking may need to occur over the choice of unifiers. Consider the following small signature: kind i type. type a i. type f i -> i. type g i -> i -> i. The query ?- (F a) = (g a a). has four solutions: F = w\ (g w w) F = w\ (g a w) F = w\ (g w a) F = w\ (g a a) The query ?- u\ (F (f u)) = u\ (f (F u)). has an infinite number of unifiers, namely, F = w\w, F = w\(f w), F = w\(f (f w)) , F = w\(f (f (f w))), ... A lambda Prolog interpreter will systematically explore this choices via backtracking. As another example of the use of higher-order quantification, meta-level (lambda Prolog-level) beta reduction, and higher-order unification, consider the following module containing some declarations regarding Church numeral representation in the simple theory of types. ________________________________________________________________ module church. kind i type. type zero, one, two, three, four ((i -> i) -> i -> i) -> o. type plus, mult (((i -> i) -> i -> i) -> ((i -> i) -> i -> i) -> ((i -> i) -> i -> i)) -> o. zero (f\x\x). one (f\x\ f x). two (f\x\ f (f x)). three (f\x\ f (f (f x))). four (f\x\ f (f (f (f x)))). plus (n\m\f\x\ (n f) (m f x)). mult (n\m\f\x\ (n (m f) x)). % Solve (x + 2) = 3. type testa ((i -> i) -> i -> i) -> o. testa X :- two Two, three Three, plus Plus, (Plus X Two) = Three. % Solve (x * x) = 4. type testb ((i -> i) -> i -> i) -> o. testb X :- four Four, mult Mult, (Mult X X) = Four. ________________________________________________________________ We can now solve two equations for integer solutions using just higher-order unification. For example, ________________________________________________________________ Terzo> #load "church.mod". [reading file church.mod] module church [closed file church.mod] Terzo> #query church. ?- testa X. X = x\ x1\ x x1 ; no more solutions ?- testb X. X = x\ x1\ x (x x1) ; no more solutions ?- ________________________________________________________________ That is, the one solution is the number 1 and the other the number 2.