-- 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