-- 8th Summer School on Formal Techniques
-- Menlo College, Atherton, California, US
--
-- 21-25 May 2018
--
-- Lecture 2: Representing Logics and Programming Languages in Agda
--
-- File 4: Normal IPL derivations
{-# OPTIONS --allow-unsolved-metas #-}
module Normal where
open import Library
open import IPL
open import Substitution using (Ren; liftRen)
-- The following Flag indicates whether we deal with a
--
-- lin) straight-line elimination using only impE and andE
-- branch) an elimination that ends in a orE or falseE
data Flag : Set where
lin : Flag -- Just impE and andE
branch : Flag -- lin followed by a single orE or falseE
-- The following grammar defines normal derivations (Nf),
-- which are constructed from introductions and then
-- possibly an elimination from a hypothesis.
mutual
-- Normal derivations (Nf = normal form).
-- We can recursively apply introduction rules
-- and then switch to elimination from a hypothesis.
data Nf (Γ : Cxt) : (A : Form) → Set where
trueI : Nf Γ True
impI : ∀{A B} (t : Nf (Γ ∙ A) B) → Nf Γ (A ⇒ B)
andI : ∀{A B} (t : Nf Γ A) (u : Nf Γ B) → Nf Γ (A ∧ B)
orI₁ : ∀{A B} (t : Nf Γ A) → Nf Γ (A ∨ B)
orI₂ : ∀{A B} (t : Nf Γ B) → Nf Γ (A ∨ B)
hyp : ∀{A C f} (x : Hyp Γ A) (es : Elims Γ A C f) → Nf Γ C
-- Elims Γ A C f eliminates proposition A into C, using
-- possibly several impE and andE steps first, and then
-- possibly a final falseE or orE step.
-- All side derivations are in Nf.
data Elims (Γ : Cxt) : (A C : Form) (f : Flag) → Set where
[] : ∀{A} → Elims Γ A A lin
_∷_ : ∀{A B C f} (e : Elim Γ A B) (es : Elims Γ B C f) → Elims Γ A C f
falseE : ∀{C} → Elims Γ False C branch
orE : ∀{A B C} (t₁ : Nf (Γ ∙ A) C) (t₂ : Nf (Γ ∙ B) C) → Elims Γ (A ∨ B) C branch
-- Elim Γ A C contains single a single impE or andE elimination.
data Elim (Γ : Cxt) : (A C : Form) → Set where
impE : ∀{A B} (t : Nf Γ A) → Elim Γ (A ⇒ B) B
andE₁ : ∀{A B} → Elim Γ (A ∧ B) A
andE₂ : ∀{A B} → Elim Γ (A ∧ B) B
-- Normal derivations are trivially consistent:
-- There is no normal proof of False in the empty context.
nf-consistent : Nf ε False → ⊥
nf-consistent (hyp () _)
-- We can also refute more complex propositions, e.g. classical principles.
module RefuteLEM where
-- The law of the excluded middle does not hold in general,
-- e.g., not for atomic propositions.
postulate a : Base
A = Atom a
not-LEM : Nf ε (A ∨ ¬ A) → ⊥
not-LEM = {!!}
-- The challenge is to show that Nf is still a complete proof system for IPL.
-- That means that whenever t : Γ ⊢ C, there exists also a normal derivation v : Nf Γ C.
-- This theorem is also called normalization, because it takes a proof t
-- and returns its normal form.
-- In the remainder of this file, we prove the normalization theorem.
-- Proving the normalization theorem amounts to supply the "missing rules" for Nf.
-- For instance, there is a rule impI on normal derivations, but no rule
--
-- impE : (t : Nf Γ (A ⇒ B)) (u : Nf Γ A) → Nf Γ B
--
-- We will show that this rule is admissible. It can be shown by
-- lexicographic induction on (A, t). However, the inductive argument
-- is not trivial, it requires us to define a normalizing substitution.
-- First, we show the admissibility of conjucntion and absurdity elimination
-- which are straightforward.
-- Conjunction elimination (andE₁!).
-- For admissibility of andE₁ on normal derivations, consider the cases
-- for t : Nf Γ (A ∧ B).
--
-- Either t is (andI t₁ t₂) with t₁ : Nf Γ A and t₂ : Nf Γ B.
-- In this case we just return t₁.
--
-- Otherwise t is (hyp x es) which means that the conjunction is
-- proven from hypothesis (x : Hyp Γ X) by eliminations
-- es : Elims Γ X (A ∧ B) f.
--
-- In this case, we would simply wish to append a andE₁ elimination
-- to es. This is possible if f = lin. In case f = Branch, we
-- have to distribute andE₁ to the branches.
-- For falseE, there are zero branches, and for orE, there
-- are two branches of type Nf (Γ ∙ _) (A ∧ B).
-- We turn these into Nf (Γ ∙ _) A by recursively applying andE₁!.
-- Since the branches are subterms of the original term t,
-- the recursion is valid (i.e., does not lead to infinite regression).
mutual
andE₁! : ∀{Γ A B} → Nf Γ (A ∧ B) → Nf Γ A
andE₁! t = {!!}
andElims₁ : ∀ {Γ X A B f} (es : Elims Γ X (A ∧ B) f) → Elims Γ X A f
andElims₁ es = {!!}
-- Admissibility of andE₂ is analogous.
mutual
andE₂! : ∀{Γ A B} → Nf Γ (A ∧ B) → Nf Γ B
andE₂! t = {!!}
andElims₂ : ∀ {Γ X A B f} (es : Elims Γ X (A ∧ B) f) → Elims Γ X B f
andElims₂ es = {!!}
-- Absurdity elimination (falseE!).
-- The only normal derivation of False is from a hypothesis X
-- using eliminations es : Elims Γ X False f.
-- To eliminate False into a proposition A, we append falseE
-- to es if f = Lin, or distribute it over the brances if
-- f = branch.
mutual
falseE! : ∀ {Γ A} → Nf Γ False → Nf Γ A
falseE! t = {!!}
falseElims : ∀ {Γ X A f} → Elims Γ X False f → Elims Γ X A branch
falseElims es = {!!}
-- First we have to prove some basic properties, for instance
-- that normal derivations are stable under context extensions
-- and permutations.
-- The following mutual functions prove that Nf, Elim, and Elims
-- are stable under renaming.
-- This is a routine induction. Whenever we go under a binder,
-- like in impI or orE, we need to lift the renaming
-- to account for the new hypothesis.
mutual
renNf : ∀{Γ Δ A} (r : Ren Γ Δ) (t : Nf Δ A) → Nf Γ A
renNf r t = {!!}
renElims : ∀{Γ Δ A B f} (r : Ren Γ Δ) (es : Elims Δ A B f) → Elims Γ A B f
renElims r es = {!!}
renElim : ∀{Γ Δ A B} (r : Ren Γ Δ) (e : Elim Δ A B) → Elim Γ A B
renElim r e = {!!}
-- We will need the following three instances of renaming,
-- called weakenings. These add an unused hypothesis on top
-- (weak and weakElim) or just below the top (weak').
weak : ∀{Γ A C} (t : Nf Γ C) → Nf (Γ ∙ A) C
weak = renNf pop
weakElim : ∀{Γ A B C} (e : Elim Γ B C) → Elim (Γ ∙ A) B C
weakElim = renElim pop
weak' : ∀{Γ A B C} (t : Nf (Γ ∙ B) C) → Nf (Γ ∙ A ∙ B) C
weak' = renNf (liftRen pop)
-- Hereditary substitution.
-- When showing the admissibility of
--
-- impE : (t : Nf Γ (A ⇒ B)) (u : Nf Γ A) → Nf Γ B
--
-- we have to treat the case that t = impI t' with
-- t' : Nf (Γ ∙ A) B. How do we get a Nf Γ B?
-- We substitute all uses of the top hypothesis in t' by u.
--
-- However, if A is not an atomic proposition,
-- this hypothesis might be under eliminations es,
-- thus, we have to normalize the elimination of u by es.
-- This might in turn trigger a substitution, for instance,
-- if u is itself an impI u' and the first elimination of es
-- is an impE v.
--
-- Thus, a substitution might trigger new substitutions,
-- and this process is called "hereditary substitution(s)".
-- How can we be sure this process ever terminates?
-- It turns out at all subsequent substitutions triggered
-- by a substitution of u : Nf Γ A for a hypothesis x : Hyp Γ A,
-- are substitutions of a u' : Nf Γ' A' for an a' : Hyp Γ' A',
-- where A' is a subproposition of A.
-- Thus, we can define substitution of u : Nf Γ A into t' : Nf (Γ ∙ A) B
-- by an outer recursion on A and an inner recursion on t'.
-- As a first step, we define the type of substitutions
-- Sub A Γ Δ of a Nf Γ A into something in context Γ.
-- Such a substitution replaces each hypothesis Hyp Δ C
-- by a "result" Res A Γ C where the result can be a
-- Nf Γ A if A = C and must be a hypothesis otherwise.
data Res A Γ : (C : Form) → Set where
rnf : (t : Nf Γ A) → Res A Γ A
rhyp : ∀{C} (x : Hyp Γ C) → Res A Γ C
Sub : (A : Form) (Γ Δ : Cxt) → Set
Sub A Γ Δ = ∀{C} → Hyp Δ C → Res A Γ C
-- Routinely, we prove that results can be weakened.
weakRes : ∀{Γ A B C} (t : Res A Γ C) → Res A (Γ ∙ B) C
weakRes (rnf t) = rnf (weak t)
weakRes (rhyp x) = rhyp (pop x)
-- We construct substitutions by the following two methods.
-- A singleton substitution sg t is constructed from a single normal form t.
-- It replaces the top hypothesis by t and all other hypotheses by themselves.
sg : ∀ {Γ A} (t : Nf Γ A) → Sub A Γ (Γ ∙ A)
sg t top = rnf t
sg t (pop x) = rhyp x
-- We can lift a substitution to one more hypothesis which remains fixed.
lift : ∀{A Γ Δ B} (s : Sub A Γ Δ) → Sub A (Γ ∙ B) (Δ ∙ B)
lift s top = rhyp top
lift s (pop x) = weakRes (s x)
-- Substitution of (s : Sub A Γ Δ) into normal forms (t : Nf Δ C)
-- is now defined by lexicographic induction on (A, t),
-- mutually with many auxiliary functions like substitution
-- into eliminations, elimination of a normal form,
-- and admissiblity of impE and orE for normal forms.
-- Thanks to the dependent typing, most cases are forced.
-- And Agda's termination checker scrutinizes our definition,
-- to ensure correct use of the induction hypotheses.
mutual
-- Substitution is homeomorphic except for the case (hyp x es)
-- in which we have to apply the substitution s to hypothesis x
-- and eliminate the result by es.
subst : ∀ A {Γ Δ} (s : Sub A Γ Δ) {C} (t : Nf Δ C) → Nf Γ C
subst A s (hyp x es) = elimsRes A (s x) (substElims A s es)
subst A s t = {!!}
substElims : ∀ A {Γ Δ} (s : Sub A Γ Δ) {B C f} (es : Elims Δ B C f) → Elims Γ B C f
substElims A s es = {!!}
substElim : ∀ A {Γ Δ} (s : Sub A Γ Δ) {B C} (e : Elim Δ B C) → Elim Γ B C
substElim A s e = {!!}
-- If the result of substituting x is just an hypothesis y,
-- we can just put the eliminations es back.
-- Otherwise, if the result is a normal form t, we have
-- to eliminate it recursively by es.
-- This might trigger new substitutions in cases impE or orE.
elimsRes : ∀ A {Γ B C f} (r : Res A Γ B) (es : Elims Γ B C f) → Nf Γ C
elimsRes A (rhyp y) es = hyp y es
elimsRes A (rnf t) es = elims A t es
-- "elims" is the place where types are actually getting smaller
-- but terms might get bigger by invokation of impE! and orE!.
elims : ∀ A {Γ C f} (t : Nf Γ A) (es : Elims Γ A C f) → Nf Γ C
elims A t [] = t
elims .(A ⇒ B) t (impE {A} {B} u ∷ es) = elims B (impE! A t u) es
elims .(A ∧ B) t (andE₁ {A} {B} ∷ es) = elims A (andE₁! t) es
elims .(A ∧ B) t (andE₂ {A} {B} ∷ es) = elims B (andE₂! t) es
elims .False t falseE = falseE! t
elims .(A ∨ B) t (orE {A} {B} t₁ t₂) = orE! A B t t₁ t₂
-- The admissible eliminations of implication and disjunction,
-- impE! and orE!, are invoked by "elims" and in turn invoke
-- substitution. It is crucial that they are called with
-- a strictly smaller proposition than the original call to subst had.
-- Implication elimination
-- Triggers new substitutions in case of (impI t). In the other case,
-- we append the (impE u) to the eliminations es, distributing it to the
-- branches in case of falseE or orE.
impE! : ∀ A {Γ B} (t : Nf Γ (A ⇒ B)) (u : Nf Γ A) → Nf Γ B
impE! A (impI t) u = subst A (sg u) t
impE! A (hyp x es) u = hyp x (impElims A es u)
impElims : ∀ A {Γ B X f} (es : Elims Γ X (A ⇒ B) f) (u : Nf Γ A) → Elims Γ X B f
impElims A (e ∷ es) u = e ∷ impElims A es u
impElims A [] u = impE u ∷ []
impElims A (falseE) u = falseE
impElims A (orE t₁ t₂) u = orE (impE! A t₁ (weak u)) (impE! A t₂ (weak u))
-- Disjunction elimination
-- Triggers new substitutions in case of orI. Otherwise, append
-- an orE to the eliminations, possibly distributing it to the branches.
orE! : ∀ A B {Γ C} (t : Nf Γ (A ∨ B)) (u : Nf (Γ ∙ A) C) (v : Nf (Γ ∙ B) C) → Nf Γ C
orE! A B t u v = {!!}
orElims : ∀ A B {Γ C X f} (es : Elims Γ X (A ∨ B) f)
(u : Nf (Γ ∙ A) C)
(v : Nf (Γ ∙ B) C) → Elims Γ X C branch
orElims A B es u v = {!!}
-- Normalization.
-- Finally, we can show that each derivation of Γ ⊢ A
-- also has a normal derivation.
--
-- The proof is by induction on the derivation, using
-- the admissible elimination rules to compose the
-- results of the induction hypotheses.
nf : ∀{Γ A} (t : Γ ⊢ A) → Nf Γ A
nf t = {!!}
-- QED -}
-- Acknowledgements.
--
-- I learned the trick of doing hereditary substitutions by just
-- /structural/ recursion on types from Conor McBride.
-- He sent me some Agda code that accomplished this for the STLC using
-- the left-to-right elimination vectors we extended here to sum types.
--
-- I could have learned it from Felix Joachimski and Ralph Matthes
-- as well. The normalization algorithm presented here should be
-- the computational content of their strong normalization proof
-- for lambda-calculus with permutative conversions (AML 2003).
-- However, I did not have the formalization skills back then
-- I have now to translate their generous vector notation into
-- the statically well-typed Elims.
-- Literature.
-- Dag Prawitz:
-- Natural Deduction: A Proof-Theoretical Study
-- Dover Publications (1965)
-- Felix Joachimski, Ralph Matthes:
-- Short proofs of normalization for the simply-typed lambda-calculus,
-- permutative conversions and Gödel's T.
-- Arch. Math. Log. 42(1): 59-87 (2003)
-- Kevin Watkins, Iliano Cervesato, Frank Pfenning, David Walker:
-- A concurrent logical framework {I}: Judgements and properties.
-- Technical report CMU-CS02-101,
-- School of Computer Science, Carnegie Mellon University, Pittsburgh (2003)
-- Andreas Abel:
-- Implementing a normalizer using sized heterogeneous types.
-- J. Funct. Program. 19(3-4): 287-310 (2009)
-- Chantal Keller, Thorsten Altenkirch:
-- Hereditary Substitutions for Simple Types, Formalized.
-- MSFP@ICFP 2010: 3-10
-- Harley D. Eades III, Aaron Stump
-- Exploring the Reach of Hereditary Substitution.
-- International Conference on Types for Proofs and Programs, TYPES 2011, Bergen, Norway.
-- Abstract: https://sites.google.com/site/types2011/program/types2011-talkswabstracts#Eades
-- Talk: http://metatheorem.org/includes/talks/2012-TYPES.pdf
-- Paper: http://metatheorem.org/includes/pubs/TYPES-2012.pdf