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.

Author: Julian Grove

Created: 2023-11-16 Thu 22:26

Validate