%{ This article represents a (partially unsuccessful) attempt to remove the "ugly" portion from the global soundness proof in the [[verifications and uses]] article. The language of propositions and rules (and, as a result, the argument for global completeness) is unchanged from the [[verifications and uses]], and so we omit it here. This article is an intermediate point between the [[verifications and uses]] article and the [[verifications and uses with zippers]] article. | hidden = true }% prop : type. atom : type. %block bl_atom : block {qp : atom}. a : atom -> prop. ⊃ : prop -> prop -> prop. %infix right 9 ⊃. ∧ : prop -> prop -> prop. %infix right 8 ∧. hyp : prop -> type. verif : prop -> type. use : prop -> type. %block bl_hyp : some {A : prop} block {x : hyp A}. var : hyp A -> use A. atm : use (a Q) -> verif (a Q). ⊃I : (hyp A -> verif B) -> verif (A ⊃ B). ⊃E : use (A ⊃ B) -> verif A -> use B. ∧I : verif A -> verif B -> verif (A ∧ B). ∧E₁ : use (A ∧ B) -> use A. ∧E₂ : use (A ∧ B) -> use B. %{ Rather than the (somewhat ugly) process used to find the main variable in the [[verifications and uses]] example, in this example we will create a sort-of zipper data structure that allows us to "pull out" the head variable from the inside of a term. }% %{ == Defining pseudo-zippers == }% %{ A [[w:zipper|zipper data structure]] is a way of describing paths into complex structures. A "real" zipper over an atomic term has the structure of a ''spine'' in a [[spine form]] presentation of logic; what we present here isn't "really" a spine (or a zipper). }% zip : prop -> prop -> type. end : zip A A. ⊃Z : zip A (B₁ ⊃ B₂) -> verif B₁ -> zip A B₂. ∧Z₁ : zip A (B₁ ∧ B₂) -> zip A B₁. ∧Z₂ : zip A (B₁ ∧ B₂) -> zip A B₂. use' : prop -> type. · : hyp A -> zip A B -> use' B. %infix none 10 ·. %{ For instance, the use' corresponding to (⊃E (⊃E (⊃E (var x) N1) N2) N3) is x · (⊃Z (⊃Z (⊃Z end N1) N2) N3) --- the head variable x has been brought out to the top of the term, but the subterm N1 is still nested more deeply than the subterms N2 and N3. In a conversion to spine form, we would not only expose the head variable x but would make N1 the "least deeply nested" subterm and make N3 the "most deeply nested" subterm. }% %{ == Zipping and unzipping == }% %{ We need to both show that we can zip and unzip a use into a use', and vice versa. These two proofs are essentially the same logic program run in opposite directions, but Twelf only allows us to assign a single mode to a metatheorem, so rather than just copying and pasted we have "cleaned up" both the unzip and rezip functions a bit. }% unzip : use B -> use' B -> type. - : unzip (⊃E R N) (X · ⊃Z Z N) <- unzip R (X · Z). - : unzip (∧E₁ R) (X · ∧Z₁ Z) <- unzip R (X · Z). - : unzip (∧E₂ R) (X · ∧Z₂ Z) <- unzip R (X · Z). - : unzip (var X) (X · end). %mode unzip +R -R'. %worlds (bl_atom | bl_hyp) (unzip _ _). %total R (unzip R _). rezip : hyp A -> zip A B -> use B -> type. - : rezip X (⊃Z Z N) (⊃E R N) <- rezip X Z R. - : rezip X (∧Z₁ Z) (∧E₁ R) <- rezip X Z R. - : rezip X (∧Z₂ Z) (∧E₂ R) <- rezip X Z R. - : rezip X end (var X). %mode rezip +X +Z -R. %worlds (bl_atom | bl_hyp) (rezip _ _ _). %total Z (rezip _ Z _). %{ == Global soundness == }% hsubst_n : {A} verif A -> (hyp A -> verif B) -> verif B -> type. hsubst_r : {A} verif A -> (hyp A -> use' (a Q)) -> verif (a Q) -> type. hsubst_rr : {A} verif A -> (hyp A -> zip C B) -> zip C B' -> type. hsubst_rn : {A}{B} verif A -> (hyp A -> zip A B) -> verif B -> type. %mode hsubst_n +A +M₀ +M -N. %mode hsubst_r +A +M₀ +R -N. %mode hsubst_rr +A +M₀ +R -R'. %mode hsubst_rn +A +B +M₀ +R -N. - : hsubst_n A M₀ ([x] ⊃I [y] M x y) (⊃I [y] N y) <- {y : hyp B₁} hsubst_n A M₀ ([x] M x y) (N y : verif B₂). - : hsubst_n A M₀ ([x] ∧I (M₁ x) (M₂ x)) (∧I N₁ N₂) <- hsubst_n A M₀ ([x] M₁ x) (N₁ : verif B₁) <- hsubst_n A M₀ ([x] M₂ x) (N₂ : verif B₂). - : hsubst_n A M₀ ([x] atm (R x)) N <- ({x : hyp A} unzip (R x) (R' x)) <- hsubst_r A M₀ ([x] (R' x)) N. - : hsubst_r A M₀ ([x] x · Z x) N <- hsubst_rn A _ M₀ ([x] Z x) N. - : hsubst_r A M₀ ([x] Y · Z x) (atm R) <- hsubst_rr A M₀ ([x] Z x) Z' <- rezip Y Z' R. - : hsubst_rr A M₀ ([x] ⊃Z (Z x) (M x)) (⊃Z Z' N) <- hsubst_rr A M₀ ([x] Z x) Z' <- hsubst_n A M₀ ([x] M x) N. - : hsubst_rr A M₀ ([x] ∧Z₁ (Z x)) (∧Z₁ Z') <- hsubst_rr A M₀ ([x] Z x) Z'. - : hsubst_rr A M₀ ([x] ∧Z₂ (Z x)) (∧Z₂ Z') <- hsubst_rr A M₀ ([x] Z x) Z'. - : hsubst_rr A M₀ ([x] end) end. - : hsubst_rn A _ M₀ ([x] ⊃Z (Z x) (M x)) N' <- hsubst_rn A _ M₀ ([x] Z x) ((⊃I [y] N y) : verif (B₁ ⊃ B₂)) <- hsubst_n A M₀ ([x] M x) (M' : verif B₁) <- hsubst_n B₁ M' ([y] N y) (N' : verif B₂). - : hsubst_rn A _ M₀ ([x] ∧Z₁ (Z x)) N₁ <- hsubst_rn A _ M₀ ([x] Z x) (∧I N₁ N₂ : verif (B₁ ∧ B₂)). - : hsubst_rn A _ M₀ ([x] ∧Z₂ (Z x)) N₂ <- hsubst_rn A _ M₀ ([x] Z x) (∧I N₁ N₂ : verif (B₁ ∧ B₂)). - : hsubst_rn A _ M₀ ([x] end) M₀. %worlds (bl_atom | bl_hyp) (hsubst_n _ _ _ _) (hsubst_rr _ _ _ _) (hsubst_rn _ _ _ _ _) (hsubst_r _ _ _ _) . %reduces B <= A (hsubst_rn A B _ _ _). %{ == Failure of termination checking == }% %{ The fact that our representation uses both proofs use A and proofs use' A means that we will run afowl of Twelf's termination checker --- an unzipped term has a different size than the corresponding zipped term. We could certainly convince Twelf that zipping and unzipping preserved size by using the same tree-like [[structural metric]] used in the [[concrete representation]] case study, but that would be notationally heavy and unenlightening. Another option is to ask Twelf to trust us: }% %trustme %reduces R' = R (unzip R R'). %. However, for some reason (possibly because the types of the two terms is different) this does not work. and we still get an error message from the final %total declaration. %total {(A B C D) (M R S T)} (hsubst_n A _ M _) (hsubst_rr C _ S _) (hsubst_rn D _ _ T _) (hsubst_r B _ R _).