Translating λ-calculus into first-order logic
Table of Contents
1. λ-calculus to FOL
We've now looked at how to translate terms of the simply typed λ-calculus into expressions of first-order logic. We can do this based on a set of simply typed λ-terms that includes, for example, the following set of constants:
data Constant φ where C :: Constant E J :: Constant E Dog :: Constant (E :-> T) Teach :: Constant (E :-> (E :-> T)) And :: Constant (T :-> (T :-> T)) Or :: Constant (T :-> (T :-> T)) Imp :: Constant (T :-> (T :-> T)) Forall :: Constant ((E :-> T) :-> T) Exists :: Constant ((E :-> T) :-> T)
We may then use the following function to carry out this translation:
translateTerm :: (forall φ. In φ γ -> FOL.Var) -> Integer -> Term γ φ -> Either FOL.Term FOL.Form translateTerm g n (Var i) = Left (FOL.V (g i)) translateTerm g n (App (App (Con And) t) u) = Right (FOL.And t' u') where t' = case translateTerm g n t of Right t' -> t' u' = case translateTerm g n u of Right u' -> u' translateTerm g n (App (App (Con Or) t) u) = Right (FOL.Or t' u') where t' = case translateTerm g n t of Right t' -> t' u' = case translateTerm g n u of Right u' -> u' translateTerm g n (App (App (Con Imp) t) u) = Right (FOL.Or (FOL.Not t') u') where t' = case translateTerm g n t of Right t' -> t' u' = case translateTerm g n u of Right u' -> u' translateTerm g n (App (Con Forall) t) = Right (FOL.Forall (FOL.Var n) t') where t' = case translated of Right t' -> t' translated = translateTerm (\i -> case i of First -> FOL.Var n; Next j -> g j) (succ n) tapp tapp = normalForm (App (weaken t) (Var First)) translateTerm g n (App (Con Exists) t) = Right (FOL.Exists (FOL.Var n) t') where t' = case translated of Right t' -> t' translated = translateTerm (\i -> case i of First -> FOL.Var n; Next j -> g j) (succ n) tapp tapp = normalForm (App (weaken t) (Var First)) translateTerm _ _ (Con C) = Left (FOL.N (FOL.Name 0)) translateTerm _ _ (Con J) = Left (FOL.N (FOL.Name 1)) translateTerm _ _ (Con Dog) = Right (FOL.P 0 []) translateTerm _ _ (Con Teach) = Right (FOL.P 1 []) translateTerm g n (App t u) = case (translateTerm g n t, translateTerm g n u) of (Right (FOL.P i ts), Left u') -> Right (FOL.P i (ts ++ [u']))
To translate terms of type T, we may now employ the following function:
translateTermT :: Term Empty T -> FOL.Form translateTermT t = case translateTerm (\case) 0 t of Right t' -> t'
2. English to FOL
Now we can also translate English expressions to first-order logic! To do so,
we simply compose our old interpretation function interpExpr with
translateTermT (sliding normalForm in between, in order to ensure that terms
are in β-normal form before they are translated).
englishToFOL :: Expr S -> FOL.Form englishToFOL = translateTermT . normalForm . interpExpr
Indeed, we may check if some set of English sentences entails another English sentence (given some depth)!
entailsEnglish :: Int -> [Expr S] -> Expr S -> Bool entailsEnglish n sentences sentence = entails n (map englishToFOL sentences) (englishToFOL sentence)
For an example, consider the English sentence Julian taught Carina.
julianTaughtCarina :: Expr S julianTaughtCarina = (AppL (Lex (Word "julian" IsAnNP)) (AppR (Lex (Word "taught" ((IsAnNP ::\:: IsAnS) ::/:: IsAnNP))) (Lex (Word "carina" IsAnNP))))
We may check to see if this sentence entails itself, as follows, choosing a depth of 1:
>>> entailsEnglish 1 [julianTaughtCarina] julianTaughtCarina True
Excellent.
3. Exercise
Show, step by step, how the following Haskell expression is evaluated:
translateTermT (App (App (Con Teach) (Con C)) (Con J))
That is, start by unpacking the definition of translateTermT, then apply the
definition, given the pattern it is applied to, and so on, until you have a
first-order logic formula. The point of this exercise is to help in
understanding what translateTermT (and translateTerm) is actually doing, i.e.,
why it works. It's much easier to see what's going on after working through an
example.