diff -r 000000000000 -r a5a9c433f639 src/ZF/qpair.ML --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ZF/qpair.ML Thu Sep 16 12:20:38 1993 +0200 @@ -0,0 +1,299 @@ +(* Title: ZF/qpair.ML + ID: $Id$ + Author: Lawrence C Paulson, Cambridge University Computer Laboratory + Copyright 1993 University of Cambridge + +For qpair.thy. + +Quine-inspired ordered pairs and disjoint sums, for non-well-founded data +structures in ZF. Does not precisely follow Quine's construction. Thanks +to Thomas Forster for suggesting this approach! + +W. V. Quine, On Ordered Pairs and Relations, in Selected Logic Papers, +1966. + +Many proofs are borrowed from pair.ML and sum.ML + +Do we EVER have rank(a) < rank() ? Perhaps if the latter rank + is not a limit ordinal? +*) + + +open QPair; + +(**** Quine ordered pairing ****) + +(** Lemmas for showing that uniquely determines a and b **) + +val QPair_iff = prove_goalw QPair.thy [QPair_def] + " = <-> a=c & b=d" + (fn _=> [rtac sum_equal_iff 1]); + +val QPair_inject = standard (QPair_iff RS iffD1 RS conjE); + +val QPair_inject1 = prove_goal QPair.thy " = ==> a=c" + (fn [major]=> + [ (rtac (major RS QPair_inject) 1), (assume_tac 1) ]); + +val QPair_inject2 = prove_goal QPair.thy " = ==> b=d" + (fn [major]=> + [ (rtac (major RS QPair_inject) 1), (assume_tac 1) ]); + + +(*** QSigma: Disjoint union of a family of sets + Generalizes Cartesian product ***) + +val QSigmaI = prove_goalw QPair.thy [QSigma_def] + "[| a:A; b:B(a) |] ==> : QSigma(A,B)" + (fn prems=> [ (REPEAT (resolve_tac (prems@[singletonI,UN_I]) 1)) ]); + +(*The general elimination rule*) +val QSigmaE = prove_goalw QPair.thy [QSigma_def] + "[| c: QSigma(A,B); \ +\ !!x y.[| x:A; y:B(x); c= |] ==> P \ +\ |] ==> P" + (fn major::prems=> + [ (cut_facts_tac [major] 1), + (REPEAT (eresolve_tac [UN_E, singletonE] 1 ORELSE ares_tac prems 1)) ]); + +(** Elimination rules for :A*B -- introducing no eigenvariables **) + +val QSigmaE2 = + rule_by_tactic (REPEAT_FIRST (etac QPair_inject ORELSE' bound_hyp_subst_tac) + THEN prune_params_tac) + (read_instantiate [("c","")] QSigmaE); + +val QSigmaD1 = prove_goal QPair.thy " : QSigma(A,B) ==> a : A" + (fn [major]=> + [ (rtac (major RS QSigmaE2) 1), (assume_tac 1) ]); + +val QSigmaD2 = prove_goal QPair.thy " : QSigma(A,B) ==> b : B(a)" + (fn [major]=> + [ (rtac (major RS QSigmaE2) 1), (assume_tac 1) ]); + +val QSigma_cong = prove_goalw QPair.thy [QSigma_def] + "[| A=A'; !!x. x:A' ==> B(x)=B'(x) |] ==> \ +\ QSigma(A,B) = QSigma(A',B')" + (fn prems=> [ (prove_cong_tac (prems@[RepFun_cong]) 1) ]); + +val QSigma_empty1 = prove_goal QPair.thy "QSigma(0,B) = 0" + (fn _ => [ (fast_tac (ZF_cs addIs [equalityI] addSEs [QSigmaE]) 1) ]); + +val QSigma_empty2 = prove_goal QPair.thy "A <*> 0 = 0" + (fn _ => [ (fast_tac (ZF_cs addIs [equalityI] addSEs [QSigmaE]) 1) ]); + + +(*** Eliminator - qsplit ***) + +val qsplit = prove_goalw QPair.thy [qsplit_def] + "qsplit(%x y.c(x,y), ) = c(a,b)" + (fn _ => [ (fast_tac (ZF_cs addIs [the_equality] addEs [QPair_inject]) 1) ]); + +val qsplit_type = prove_goal QPair.thy + "[| p:QSigma(A,B); \ +\ !!x y.[| x:A; y:B(x) |] ==> c(x,y):C() \ +\ |] ==> qsplit(%x y.c(x,y), p) : C(p)" + (fn major::prems=> + [ (rtac (major RS QSigmaE) 1), + (etac ssubst 1), + (REPEAT (ares_tac (prems @ [qsplit RS ssubst]) 1)) ]); + +(*This congruence rule uses NO typing information...*) +val qsplit_cong = prove_goalw QPair.thy [qsplit_def] + "[| p=p'; !!x y.c(x,y) = c'(x,y) |] ==> \ +\ qsplit(%x y.c(x,y), p) = qsplit(%x y.c'(x,y), p')" + (fn prems=> [ (prove_cong_tac (prems@[the_cong]) 1) ]); + + +val qpair_cs = ZF_cs addSIs [QSigmaI] addSEs [QSigmaE2, QSigmaE, QPair_inject]; + +(*** qconverse ***) + +val qconverseI = prove_goalw QPair.thy [qconverse_def] + "!!a b r. :r ==> :qconverse(r)" + (fn _ => [ (fast_tac qpair_cs 1) ]); + +val qconverseD = prove_goalw QPair.thy [qconverse_def] + "!!a b r. : qconverse(r) ==> : r" + (fn _ => [ (fast_tac qpair_cs 1) ]); + +val qconverseE = prove_goalw QPair.thy [qconverse_def] + "[| yx : qconverse(r); \ +\ !!x y. [| yx=; :r |] ==> P \ +\ |] ==> P" + (fn [major,minor]=> + [ (rtac (major RS ReplaceE) 1), + (REPEAT (eresolve_tac [exE, conjE, minor] 1)), + (hyp_subst_tac 1), + (assume_tac 1) ]); + +val qconverse_cs = qpair_cs addSIs [qconverseI] + addSEs [qconverseD,qconverseE]; + +val qconverse_of_qconverse = prove_goal QPair.thy + "!!A B r. r<=QSigma(A,B) ==> qconverse(qconverse(r)) = r" + (fn _ => [ (fast_tac (qconverse_cs addSIs [equalityI]) 1) ]); + +val qconverse_type = prove_goal QPair.thy + "!!A B r. r <= A <*> B ==> qconverse(r) <= B <*> A" + (fn _ => [ (fast_tac qconverse_cs 1) ]); + +val qconverse_of_prod = prove_goal QPair.thy "qconverse(A <*> B) = B <*> A" + (fn _ => [ (fast_tac (qconverse_cs addSIs [equalityI]) 1) ]); + +val qconverse_empty = prove_goal QPair.thy "qconverse(0) = 0" + (fn _ => [ (fast_tac (qconverse_cs addSIs [equalityI]) 1) ]); + + +(*** qsplit for predicates: result type o ***) + +goalw QPair.thy [qfsplit_def] "!!R a b. R(a,b) ==> qfsplit(R, )"; +by (REPEAT (ares_tac [refl,exI,conjI] 1)); +val qfsplitI = result(); + +val major::prems = goalw QPair.thy [qfsplit_def] + "[| qfsplit(R,z); !!x y. [| z = ; R(x,y) |] ==> P |] ==> P"; +by (cut_facts_tac [major] 1); +by (REPEAT (eresolve_tac (prems@[asm_rl,exE,conjE]) 1)); +val qfsplitE = result(); + +goal QPair.thy "!!R a b. qfsplit(R,) ==> R(a,b)"; +by (REPEAT (eresolve_tac [asm_rl,qfsplitE,QPair_inject,ssubst] 1)); +val qfsplitD = result(); + + +(**** The Quine-inspired notion of disjoint sum ****) + +val qsum_defs = [qsum_def,QInl_def,QInr_def,qcase_def]; + +(** Introduction rules for the injections **) + +goalw QPair.thy qsum_defs "!!a A B. a : A ==> QInl(a) : A <+> B"; +by (REPEAT (ares_tac [UnI1,QSigmaI,singletonI] 1)); +val QInlI = result(); + +goalw QPair.thy qsum_defs "!!b A B. b : B ==> QInr(b) : A <+> B"; +by (REPEAT (ares_tac [UnI2,QSigmaI,singletonI] 1)); +val QInrI = result(); + +(** Elimination rules **) + +val major::prems = goalw QPair.thy qsum_defs + "[| u: A <+> B; \ +\ !!x. [| x:A; u=QInl(x) |] ==> P; \ +\ !!y. [| y:B; u=QInr(y) |] ==> P \ +\ |] ==> P"; +by (rtac (major RS UnE) 1); +by (REPEAT (rtac refl 1 + ORELSE eresolve_tac (prems@[QSigmaE,singletonE,ssubst]) 1)); +val qsumE = result(); + +(** QInjection and freeness rules **) + +val [major] = goalw QPair.thy qsum_defs "QInl(a)=QInl(b) ==> a=b"; +by (EVERY1 [rtac (major RS QPair_inject), assume_tac]); +val QInl_inject = result(); + +val [major] = goalw QPair.thy qsum_defs "QInr(a)=QInr(b) ==> a=b"; +by (EVERY1 [rtac (major RS QPair_inject), assume_tac]); +val QInr_inject = result(); + +val [major] = goalw QPair.thy qsum_defs "QInl(a)=QInr(b) ==> P"; +by (rtac (major RS QPair_inject) 1); +by (etac (sym RS one_neq_0) 1); +val QInl_neq_QInr = result(); + +val QInr_neq_QInl = sym RS QInl_neq_QInr; + +(** Injection and freeness equivalences, for rewriting **) + +goal QPair.thy "QInl(a)=QInl(b) <-> a=b"; +by (rtac iffI 1); +by (REPEAT (eresolve_tac [QInl_inject,subst_context] 1)); +val QInl_iff = result(); + +goal QPair.thy "QInr(a)=QInr(b) <-> a=b"; +by (rtac iffI 1); +by (REPEAT (eresolve_tac [QInr_inject,subst_context] 1)); +val QInr_iff = result(); + +goal QPair.thy "QInl(a)=QInr(b) <-> False"; +by (rtac iffI 1); +by (REPEAT (eresolve_tac [QInl_neq_QInr,FalseE] 1)); +val QInl_QInr_iff = result(); + +goal QPair.thy "QInr(b)=QInl(a) <-> False"; +by (rtac iffI 1); +by (REPEAT (eresolve_tac [QInr_neq_QInl,FalseE] 1)); +val QInr_QInl_iff = result(); + +val qsum_cs = + ZF_cs addIs [QInlI,QInrI] addSEs [qsumE,QInl_neq_QInr,QInr_neq_QInl] + addSDs [QInl_inject,QInr_inject]; + +(** <+> is itself injective... who cares?? **) + +goal QPair.thy + "u: A <+> B <-> (EX x. x:A & u=QInl(x)) | (EX y. y:B & u=QInr(y))"; +by (fast_tac qsum_cs 1); +val qsum_iff = result(); + +goal QPair.thy "A <+> B <= C <+> D <-> A<=C & B<=D"; +by (fast_tac qsum_cs 1); +val qsum_subset_iff = result(); + +goal QPair.thy "A <+> B = C <+> D <-> A=C & B=D"; +by (SIMP_TAC (ZF_ss addrews [extension,qsum_subset_iff]) 1); +by (fast_tac ZF_cs 1); +val qsum_equal_iff = result(); + +(*** Eliminator -- qcase ***) + +goalw QPair.thy qsum_defs "qcase(c, d, QInl(a)) = c(a)"; +by (rtac (qsplit RS trans) 1); +by (rtac cond_0 1); +val qcase_QInl = result(); + +goalw QPair.thy qsum_defs "qcase(c, d, QInr(b)) = d(b)"; +by (rtac (qsplit RS trans) 1); +by (rtac cond_1 1); +val qcase_QInr = result(); + +val prems = goalw QPair.thy [qcase_def] + "[| u=u'; !!x. c(x)=c'(x); !!y. d(y)=d'(y) |] ==> \ +\ qcase(c,d,u)=qcase(c',d',u')"; +by (REPEAT (resolve_tac ([refl,qsplit_cong,cond_cong] @ prems) 1)); +val qcase_cong = result(); + +val major::prems = goal QPair.thy + "[| u: A <+> B; \ +\ !!x. x: A ==> c(x): C(QInl(x)); \ +\ !!y. y: B ==> d(y): C(QInr(y)) \ +\ |] ==> qcase(c,d,u) : C(u)"; +by (rtac (major RS qsumE) 1); +by (ALLGOALS (etac ssubst)); +by (ALLGOALS (ASM_SIMP_TAC (ZF_ss addrews + (prems@[qcase_QInl,qcase_QInr])))); +val qcase_type = result(); + +(** Rules for the Part primitive **) + +goal QPair.thy "Part(A <+> B,QInl) = {QInl(x). x: A}"; +by (fast_tac (qsum_cs addIs [PartI,equalityI] addSEs [PartE]) 1); +val Part_QInl = result(); + +goal QPair.thy "Part(A <+> B,QInr) = {QInr(y). y: B}"; +by (fast_tac (qsum_cs addIs [PartI,equalityI] addSEs [PartE]) 1); +val Part_QInr = result(); + +goal QPair.thy "Part(A <+> B, %x.QInr(h(x))) = {QInr(y). y: Part(B,h)}"; +by (fast_tac (qsum_cs addIs [PartI,equalityI] addSEs [PartE]) 1); +val Part_QInr2 = result(); + +goal QPair.thy "!!A B C. C <= A <+> B ==> Part(C,QInl) Un Part(C,QInr) = C"; +by (rtac equalityI 1); +by (rtac Un_least 1); +by (rtac Part_subset 1); +by (rtac Part_subset 1); +by (fast_tac (ZF_cs addIs [PartI] addSEs [qsumE]) 1); +val Part_qsum_equality = result();