| author | lcp | 
| Mon, 22 Aug 1994 10:56:45 +0200 | |
| changeset 122 | 6927e1cb2c07 | 
| parent 90 | 5c7a69cef18b | 
| child 128 | 89669c58e506 | 
| permissions | -rw-r--r-- | 
| 0 | 1 | (* Title: HOL/hol.ML | 
| 2 | ID: $Id$ | |
| 3 | Author: Tobias Nipkow | |
| 4 | Copyright 1991 University of Cambridge | |
| 5 | ||
| 6 | For hol.thy | |
| 7 | Derived rules from Appendix of Mike Gordons HOL Report, Cambridge TR 68 | |
| 8 | *) | |
| 9 | ||
| 10 | open HOL; | |
| 11 | ||
| 12 | signature HOL_LEMMAS = | |
| 13 | sig | |
| 14 | val allE: thm | |
| 15 | val all_dupE: thm | |
| 16 | val allI: thm | |
| 17 | val arg_cong: thm | |
| 18 | val fun_cong: thm | |
| 19 | val box_equals: thm | |
| 40 | 20 | val case_tac: string -> int -> tactic | 
| 0 | 21 | val ccontr: thm | 
| 22 | val classical: thm | |
| 23 | val cong: thm | |
| 24 | val conjunct1: thm | |
| 25 | val conjunct2: thm | |
| 26 | val conjE: thm | |
| 27 | val conjI: thm | |
| 28 | val contrapos: thm | |
| 29 | val disjCI: thm | |
| 30 | val disjE: thm | |
| 31 | val disjI1: thm | |
| 32 | val disjI2: thm | |
| 33 | val eqTrueI: thm | |
| 34 | val eqTrueE: thm | |
| 35 | val ex1E: thm | |
| 36 | val ex1I: thm | |
| 37 | val exCI: thm | |
| 38 | val exI: thm | |
| 39 | val exE: thm | |
| 40 | val excluded_middle: thm | |
| 41 | val FalseE: thm | |
| 42 | val False_neq_True: thm | |
| 43 | val iffCE : thm | |
| 44 | val iffD1: thm | |
| 45 | val iffD2: thm | |
| 46 | val iffE: thm | |
| 47 | val iffI: thm | |
| 48 | val impCE: thm | |
| 49 | val impE: thm | |
| 50 | val not_sym: thm | |
| 51 | val notE: thm | |
| 52 | val notI: thm | |
| 53 | val notnotD : thm | |
| 54 | val rev_mp: thm | |
| 55 | val select_equality: thm | |
| 56 | val spec: thm | |
| 57 | val sstac: thm list -> int -> tactic | |
| 58 | val ssubst: thm | |
| 59 | val stac: thm -> int -> tactic | |
| 60 | val strip_tac: int -> tactic | |
| 61 | val swap: thm | |
| 62 | val sym: thm | |
| 63 | val trans: thm | |
| 64 | val TrueI: thm | |
| 65 | end; | |
| 66 | ||
| 67 | structure HOL_Lemmas : HOL_LEMMAS = | |
| 68 | ||
| 69 | struct | |
| 70 | ||
| 71 | (** Equality **) | |
| 72 | ||
| 73 | val sym = prove_goal HOL.thy "s=t ==> t=s" | |
| 74 | (fn prems => [cut_facts_tac prems 1, etac subst 1, rtac refl 1]); | |
| 75 | ||
| 76 | (*calling "standard" reduces maxidx to 0*) | |
| 77 | val ssubst = standard (sym RS subst); | |
| 78 | ||
| 79 | val trans = prove_goal HOL.thy "[| r=s; s=t |] ==> r=t" | |
| 80 | (fn prems => | |
| 81 | [rtac subst 1, resolve_tac prems 1, resolve_tac prems 1]); | |
| 82 | ||
| 83 | (*Useful with eresolve_tac for proving equalties from known equalities. | |
| 84 | a = b | |
| 85 | | | | |
| 86 | c = d *) | |
| 87 | val box_equals = prove_goal HOL.thy | |
| 88 | "[| a=b; a=c; b=d |] ==> c=d" | |
| 89 | (fn prems=> | |
| 90 | [ (rtac trans 1), | |
| 91 | (rtac trans 1), | |
| 92 | (rtac sym 1), | |
| 93 | (REPEAT (resolve_tac prems 1)) ]); | |
| 94 | ||
| 95 | (** Congruence rules for meta-application **) | |
| 96 | ||
| 97 | (*similar to AP_THM in Gordon's HOL*) | |
| 98 | val fun_cong = prove_goal HOL.thy "(f::'a=>'b) = g ==> f(x)=g(x)" | |
| 99 | (fn [prem] => [rtac (prem RS subst) 1, rtac refl 1]); | |
| 100 | ||
| 101 | (*similar to AP_TERM in Gordon's HOL and FOL's subst_context*) | |
| 102 | val arg_cong = prove_goal HOL.thy "x=y ==> f(x)=f(y)" | |
| 103 | (fn [prem] => [rtac (prem RS subst) 1, rtac refl 1]); | |
| 104 | ||
| 105 | val cong = prove_goal HOL.thy | |
| 90 
5c7a69cef18b
added parentheses made necessary by change of constrain's precedence
 clasohm parents: 
84diff
changeset | 106 | "[| f = g; (x::'a) = y |] ==> f(x) = g(y)" | 
| 0 | 107 | (fn [prem1,prem2] => | 
| 108 | [rtac (prem1 RS subst) 1, rtac (prem2 RS subst) 1, rtac refl 1]); | |
| 109 | ||
| 110 | (** Equality of booleans -- iff **) | |
| 111 | ||
| 112 | val iffI = prove_goal HOL.thy | |
| 113 | "[| P ==> Q; Q ==> P |] ==> P=Q" | |
| 114 | (fn prems=> [ (REPEAT (ares_tac (prems@[impI, iff RS mp RS mp]) 1)) ]); | |
| 115 | ||
| 116 | val iffD2 = prove_goal HOL.thy "[| P=Q; Q |] ==> P" | |
| 117 | (fn prems => | |
| 118 | [rtac ssubst 1, resolve_tac prems 1, resolve_tac prems 1]); | |
| 119 | ||
| 120 | val iffD1 = sym RS iffD2; | |
| 121 | ||
| 122 | val iffE = prove_goal HOL.thy | |
| 123 | "[| P=Q; [| P --> Q; Q --> P |] ==> R |] ==> R" | |
| 124 | (fn [p1,p2] => [REPEAT(ares_tac([p1 RS iffD2, p1 RS iffD1, p2, impI])1)]); | |
| 125 | ||
| 126 | (** True **) | |
| 127 | ||
| 66 | 128 | val TrueI = prove_goalw HOL.thy [True_def] "True" | 
| 129 | (fn _ => [rtac refl 1]); | |
| 0 | 130 | |
| 131 | val eqTrueI = prove_goal HOL.thy "P ==> P=True" | |
| 132 | (fn prems => [REPEAT(resolve_tac ([iffI,TrueI]@prems) 1)]); | |
| 133 | ||
| 134 | val eqTrueE = prove_goal HOL.thy "P=True ==> P" | |
| 135 | (fn prems => [REPEAT(resolve_tac (prems@[TrueI,iffD2]) 1)]); | |
| 136 | ||
| 137 | (** Universal quantifier **) | |
| 138 | ||
| 66 | 139 | val allI = prove_goalw HOL.thy [All_def] "(!!x::'a. P(x)) ==> !x. P(x)" | 
| 140 | (fn prems => [resolve_tac (prems RL [eqTrueI RS ext]) 1]); | |
| 0 | 141 | |
| 66 | 142 | val spec = prove_goalw HOL.thy [All_def] "! x::'a.P(x) ==> P(x)" | 
| 143 | (fn prems => [rtac eqTrueE 1, resolve_tac (prems RL [fun_cong]) 1]); | |
| 0 | 144 | |
| 145 | val allE = prove_goal HOL.thy "[| !x.P(x); P(x) ==> R |] ==> R" | |
| 146 | (fn major::prems=> | |
| 147 | [ (REPEAT (resolve_tac (prems @ [major RS spec]) 1)) ]); | |
| 148 | ||
| 149 | val all_dupE = prove_goal HOL.thy | |
| 150 | "[| ! x.P(x); [| P(x); ! x.P(x) |] ==> R |] ==> R" | |
| 151 | (fn prems => | |
| 152 | [ (REPEAT (resolve_tac (prems @ (prems RL [spec])) 1)) ]); | |
| 153 | ||
| 154 | ||
| 155 | (** False ** Depends upon spec; it is impossible to do propositional logic | |
| 156 | before quantifiers! **) | |
| 157 | ||
| 84 | 158 | val FalseE = prove_goalw HOL.thy [False_def] "False ==> P" | 
| 159 | (fn [major] => [rtac (major RS spec) 1]); | |
| 0 | 160 | |
| 161 | val False_neq_True = prove_goal HOL.thy "False=True ==> P" | |
| 162 | (fn [prem] => [rtac (prem RS eqTrueE RS FalseE) 1]); | |
| 163 | ||
| 164 | ||
| 165 | (** Negation **) | |
| 166 | ||
| 66 | 167 | val notI = prove_goalw HOL.thy [not_def] "(P ==> False) ==> ~P" | 
| 168 | (fn prems=> [rtac impI 1, eresolve_tac prems 1]); | |
| 0 | 169 | |
| 66 | 170 | val notE = prove_goalw HOL.thy [not_def] "[| ~P; P |] ==> R" | 
| 75 | 171 | (fn prems => [rtac (prems MRS mp RS FalseE) 1]); | 
| 0 | 172 | |
| 173 | (** Implication **) | |
| 174 | ||
| 175 | val impE = prove_goal HOL.thy "[| P-->Q; P; Q ==> R |] ==> R" | |
| 176 | (fn prems=> [ (REPEAT (resolve_tac (prems@[mp]) 1)) ]); | |
| 177 | ||
| 178 | (* Reduces Q to P-->Q, allowing substitution in P. *) | |
| 179 | val rev_mp = prove_goal HOL.thy "[| P; P --> Q |] ==> Q" | |
| 180 | (fn prems=> [ (REPEAT (resolve_tac (prems@[mp]) 1)) ]); | |
| 181 | ||
| 182 | val contrapos = prove_goal HOL.thy "[| ~Q; P==>Q |] ==> ~P" | |
| 183 | (fn [major,minor]=> | |
| 184 | [ (rtac (major RS notE RS notI) 1), | |
| 185 | (etac minor 1) ]); | |
| 186 | ||
| 187 | (* ~(?t = ?s) ==> ~(?s = ?t) *) | |
| 188 | val [not_sym] = compose(sym,2,contrapos); | |
| 189 | ||
| 190 | ||
| 191 | (** Existential quantifier **) | |
| 192 | ||
| 66 | 193 | val exI = prove_goalw HOL.thy [Ex_def] "P(x) ==> ? x::'a.P(x)" | 
| 194 | (fn prems => [rtac selectI 1, resolve_tac prems 1]); | |
| 0 | 195 | |
| 66 | 196 | val exE = prove_goalw HOL.thy [Ex_def] | 
| 197 | "[| ? x::'a.P(x); !!x. P(x) ==> Q |] ==> Q" | |
| 198 | (fn prems => [REPEAT(resolve_tac prems 1)]); | |
| 0 | 199 | |
| 200 | ||
| 201 | (** Conjunction **) | |
| 202 | ||
| 66 | 203 | val conjI = prove_goalw HOL.thy [and_def] "[| P; Q |] ==> P&Q" | 
| 0 | 204 | (fn prems => | 
| 66 | 205 | [REPEAT (resolve_tac (prems@[allI,impI]) 1 ORELSE etac (mp RS mp) 1)]); | 
| 0 | 206 | |
| 66 | 207 | val conjunct1 = prove_goalw HOL.thy [and_def] "[| P & Q |] ==> P" | 
| 0 | 208 | (fn prems => | 
| 66 | 209 | [resolve_tac (prems RL [spec] RL [mp]) 1, REPEAT(ares_tac [impI] 1)]); | 
| 0 | 210 | |
| 66 | 211 | val conjunct2 = prove_goalw HOL.thy [and_def] "[| P & Q |] ==> Q" | 
| 0 | 212 | (fn prems => | 
| 66 | 213 | [resolve_tac (prems RL [spec] RL [mp]) 1, REPEAT(ares_tac [impI] 1)]); | 
| 0 | 214 | |
| 215 | val conjE = prove_goal HOL.thy "[| P&Q; [| P; Q |] ==> R |] ==> R" | |
| 216 | (fn prems => | |
| 217 | [cut_facts_tac prems 1, resolve_tac prems 1, | |
| 218 | etac conjunct1 1, etac conjunct2 1]); | |
| 219 | ||
| 220 | (** Disjunction *) | |
| 221 | ||
| 66 | 222 | val disjI1 = prove_goalw HOL.thy [or_def] "P ==> P|Q" | 
| 223 | (fn [prem] => [REPEAT(ares_tac [allI,impI, prem RSN (2,mp)] 1)]); | |
| 0 | 224 | |
| 66 | 225 | val disjI2 = prove_goalw HOL.thy [or_def] "Q ==> P|Q" | 
| 226 | (fn [prem] => [REPEAT(ares_tac [allI,impI, prem RSN (2,mp)] 1)]); | |
| 0 | 227 | |
| 66 | 228 | val disjE = prove_goalw HOL.thy [or_def] "[| P | Q; P ==> R; Q ==> R |] ==> R" | 
| 0 | 229 | (fn [a1,a2,a3] => | 
| 66 | 230 | [rtac (mp RS mp) 1, rtac spec 1, rtac a1 1, | 
| 0 | 231 | rtac (a2 RS impI) 1, atac 1, rtac (a3 RS impI) 1, atac 1]); | 
| 232 | ||
| 233 | (** CCONTR -- classical logic **) | |
| 234 | ||
| 235 | val ccontr = prove_goal HOL.thy "(~P ==> False) ==> P" | |
| 236 | (fn prems => | |
| 237 | [rtac (True_or_False RS (disjE RS eqTrueE)) 1, atac 1, | |
| 66 | 238 | rtac spec 1, fold_tac [False_def], resolve_tac prems 1, | 
| 239 | rtac ssubst 1, atac 1, rewtac not_def, | |
| 0 | 240 | REPEAT (ares_tac [impI] 1) ]); | 
| 241 | ||
| 66 | 242 | val ccontr = prove_goalw HOL.thy [not_def] "(~P ==> False) ==> P" | 
| 0 | 243 | (fn prems => | 
| 66 | 244 | [rtac (True_or_False RS (disjE RS eqTrueE)) 1, atac 1, | 
| 245 | rtac spec 1, fold_tac [False_def], resolve_tac prems 1, | |
| 246 | rtac ssubst 1, atac 1, REPEAT (ares_tac [impI] 1) ]); | |
| 247 | ||
| 248 | val classical = prove_goal HOL.thy "(~P ==> P) ==> P" | |
| 249 | (fn prems => [rtac ccontr 1, REPEAT (ares_tac (prems@[notE]) 1)]); | |
| 0 | 250 | |
| 251 | ||
| 252 | (*Double negation law*) | |
| 253 | val notnotD = prove_goal HOL.thy "~~P ==> P" | |
| 254 | (fn [major]=> | |
| 255 | [ (rtac classical 1), (eresolve_tac [major RS notE] 1) ]); | |
| 256 | ||
| 257 | ||
| 258 | (** Unique existence **) | |
| 259 | ||
| 66 | 260 | val ex1I = prove_goalw HOL.thy [Ex1_def] | 
| 0 | 261 | "[| P(a); !!x. P(x) ==> x=a |] ==> ?! x. P(x)" | 
| 262 | (fn prems => | |
| 66 | 263 | [REPEAT (ares_tac (prems@[exI,conjI,allI,impI]) 1)]); | 
| 0 | 264 | |
| 66 | 265 | val ex1E = prove_goalw HOL.thy [Ex1_def] | 
| 0 | 266 | "[| ?! x.P(x); !!x. [| P(x); ! y. P(y) --> y=x |] ==> R |] ==> R" | 
| 267 | (fn major::prems => | |
| 66 | 268 | [rtac (major RS exE) 1, REPEAT (etac conjE 1 ORELSE ares_tac prems 1)]); | 
| 0 | 269 | |
| 270 | ||
| 271 | (** Select: Hilbert's Epsilon-operator **) | |
| 272 | ||
| 273 | val select_equality = prove_goal HOL.thy | |
| 274 | "[| P(a); !!x. P(x) ==> x=a |] ==> (@x.P(x)) = a" | |
| 275 | (fn prems => [ resolve_tac prems 1, | |
| 276 | rtac selectI 1, | |
| 277 | resolve_tac prems 1 ]); | |
| 278 | ||
| 279 | (** Classical intro rules for disjunction and existential quantifiers *) | |
| 280 | ||
| 281 | val disjCI = prove_goal HOL.thy "(~Q ==> P) ==> P|Q" | |
| 282 | (fn prems=> | |
| 283 | [ (rtac classical 1), | |
| 284 | (REPEAT (ares_tac (prems@[disjI1,notI]) 1)), | |
| 285 | (REPEAT (ares_tac (prems@[disjI2,notE]) 1)) ]); | |
| 286 | ||
| 287 | val excluded_middle = prove_goal HOL.thy "~P | P" | |
| 288 | (fn _ => [ (REPEAT (ares_tac [disjCI] 1)) ]); | |
| 289 | ||
| 290 | (*Classical implies (-->) elimination. *) | |
| 291 | val impCE = prove_goal HOL.thy "[| P-->Q; ~P ==> R; Q ==> R |] ==> R" | |
| 292 | (fn major::prems=> | |
| 293 | [ rtac (excluded_middle RS disjE) 1, | |
| 294 | REPEAT (DEPTH_SOLVE_1 (ares_tac (prems @ [major RS mp]) 1))]); | |
| 295 | ||
| 296 | (*Classical <-> elimination. *) | |
| 297 | val iffCE = prove_goal HOL.thy | |
| 298 | "[| P=Q; [| P; Q |] ==> R; [| ~P; ~Q |] ==> R |] ==> R" | |
| 299 | (fn major::prems => | |
| 300 | [ (rtac (major RS iffE) 1), | |
| 301 | (REPEAT (DEPTH_SOLVE_1 | |
| 302 | (eresolve_tac ([asm_rl,impCE,notE]@prems) 1))) ]); | |
| 303 | ||
| 304 | val exCI = prove_goal HOL.thy "(! x. ~P(x) ==> P(a)) ==> ? x.P(x)" | |
| 305 | (fn prems=> | |
| 306 | [ (rtac ccontr 1), | |
| 307 | (REPEAT (ares_tac (prems@[exI,allI,notI,notE]) 1)) ]); | |
| 308 | ||
| 309 | (*Required by the "classical" module*) | |
| 310 | val swap = prove_goal HOL.thy "~P ==> (~Q ==> P) ==> Q" | |
| 311 | (fn major::prems=> | |
| 312 | [ rtac ccontr 1, rtac (major RS notE) 1, REPEAT (ares_tac prems 1)]); | |
| 313 | ||
| 40 | 314 | (* case distinction *) | 
| 315 | ||
| 316 | val case_split_thm = prove_goal HOL.thy "[| P ==> Q; ~P ==> Q |] ==> Q" | |
| 317 | (fn [p1,p2] => [cut_facts_tac [excluded_middle] 1, etac disjE 1, | |
| 318 | etac p2 1, etac p1 1]); | |
| 319 | ||
| 320 | fun case_tac a = res_inst_tac [("P",a)] case_split_thm;
 | |
| 321 | ||
| 0 | 322 | (** Standard abbreviations **) | 
| 323 | ||
| 324 | fun stac th = rtac(th RS ssubst); | |
| 325 | fun sstac ths = EVERY' (map stac ths); | |
| 326 | fun strip_tac i = REPEAT(resolve_tac [impI,allI] i); | |
| 327 | ||
| 48 
21291189b51e
changed "." to "$" and Cons to infix "#" to eliminate ambiguity
 clasohm parents: 
40diff
changeset | 328 | |
| 0 | 329 | end; | 
| 330 | ||
| 331 | open HOL_Lemmas; |