1(* ===================================================================== *) 2(* *) 3(* FILE : quotient.sml *) 4(* VERSION : 2.2 *) 5(* DESCRIPTION : Functions for creating a quotient type. *) 6(* *) 7(* AUTHOR : Peter Vincent Homeier *) 8(* DATE : April 15, 2005 *) 9(* COPYRIGHT : Copyright (c) 2005 by Peter Vincent Homeier *) 10(* *) 11(* ===================================================================== *) 12 13 14(* ===================================================================== *) 15(* Q U O T I E N T T Y P E S D E F I N E D *) 16(* ===================================================================== *) 17 18(* --------------------------------------------------------------------- *) 19(* This file defines the function "define_quotient_types", which takes *) 20(* one or more existing types with partial equivalence relations defined *) 21(* on them, and creates new types which are isomorphic to the *) 22(* equivalence classes of the old types. *) 23(* *) 24(* In addition to creating the new types, functions are defined in the *) 25(* HOL logic to translate between the old and new types in both *) 26(* directions. *) 27(* *) 28(* The arguments to "define_quotient_types" include an "equivalence" *) 29(* theorem which states that the equivalence relation is in fact *) 30(* reflexive, symmetric, and transitive. *) 31(* --------------------------------------------------------------------- *) 32 33structure quotient :> quotient = 34struct 35 36open HolKernel Parse boolLib; 37 38(* In interactive sessions, do: 39 40app load ["pairTheory", "sumTheory", "listTheory", "listLib"]; 41 42*) 43 44 45open pairTheory; 46open pairSyntax; 47open pairTools; 48open sumTheory; 49open listTheory; 50open listLib; 51open combinTheory; 52open quotientTheory; 53open quotient_listTheory; 54open quotient_pairTheory; 55open quotient_sumTheory; 56open quotient_optionTheory; 57open Rsyntax; 58 59structure Parse = 60struct 61 open Parse 62 val (Type,Term) = parse_from_grammars(quotient_option_grammars) 63 fun == q _ = Type q 64end 65open Parse 66 67 68(* In interactive sessions, omit the chatting section below. *) 69 70val chatting = ref false; (* When chatting is false, 71 gives no output of lifting. 72 When chatting is true, then 73 every type, constant, and theorem lifted 74 is printed. *) 75 76val _ = register_btrace("quotient", chatting); 77 78(* End of chatting section. *) 79 80 81val caching = ref true; (* should be pure efficiency gain *) 82 83 84structure Map = Redblackmap 85 86(* Redblackmap has the same signature as Binarymap. *) 87 88val quotient_cache = ref ((Map.mkDict Type.compare) :(hol_type, thm) Map.dict); 89 90val hits = ref 0; 91val misses = ref 0; 92 93fun reset_cache () = 94 (quotient_cache := (Map.mkDict Type.compare : (hol_type, thm)Map.dict); 95 hits := 0; misses := 0) 96 97fun list_cache () = (if !chatting andalso !caching then ( 98 print ( "Hits = " ^ Int.toString (!hits) ^ 99 ", Misses = " ^ Int.toString (!misses) ^ 100 ", Cache size = " ^ 101 Int.toString (Map.numItems (!quotient_cache)) 102 ^ "\n")) 103 else (); 104 Map.listItems (!quotient_cache)) 105 106 107 108local 109 val tm = Term `!P:'a list -> bool. 110 P [] /\ (!t. P t ==> !x. P (x::t)) ==> !l. P l` 111 val eq = Thm.ALPHA (concl listTheory.list_induction) tm 112 val list_induction' = EQ_MP eq listTheory.list_induction 113in 114val LIST_INDUCT_TAC =INDUCT_THEN list_induction' ASSUME_TAC 115end; 116 117fun del_imps tm = if is_imp tm then (del_imps o #conseq o dest_imp) tm 118 else tm; 119 120fun get_ants tm = 121 let val {ant,conseq} = (dest_imp o snd o strip_forall) tm 122 in 123 ant :: get_ants conseq 124 end 125 handle _ => [] 126 127fun GEN_QUOT_TYVARS th = 128 (* need to move type vars in tyop ants to genvars, 129 to avoid clashes with type vars external to "th" *) 130 let val ants = get_ants (concl th) 131 val vs = mk_set (flatten (map type_vars_in_term ants)) 132 val sub = map (fn v => (v |-> Type.gen_tyvar())) vs 133 in INST_TYPE sub th 134 end 135 136fun CAREFUL_INST_TYPE sub th = 137(* e.g., sub = [{redex = ``:'a``, residue = ``:'a term1``}, 138 {redex = ``:'c``, residue = ``:'b``}] : 139 {redex : hol_type, residue : hol_type} list *) 140(* e.g., sub = [{redex = ``:'b`, residue = ``:'a term1``}] : 141 {redex : hol_type, residue : hol_type} list *) 142 let val tyvars = type_varsl (map #residue sub) 143 val redexs = map #redex sub 144 val (asl,con) = dest_thm th 145 val th_tyvars = U (map type_vars_in_term (con::asl)) 146 val old = subtract (intersect tyvars th_tyvars) redexs 147 val newsub = map (fn v => (v |-> gen_tyvar())) old 148 in 149 INST_TYPE (sub @ newsub) th 150 end; 151 152 153fun C_MATCH_MP imp th = 154 let val imp1 = GEN_QUOT_TYVARS imp 155 val ant = (#ant o dest_imp o snd o strip_forall o concl) imp1 156 val subj = (snd o strip_forall o concl) th 157 val (_, ty_sub) = match_term ant subj 158 val imp' = (*CAREFUL_*)INST_TYPE ty_sub imp1 159 in 160 MATCH_MP imp' th 161 end; 162 163fun C_MATCH_MP2 imp th1 th2 = 164 let val imp1 = GEN_QUOT_TYVARS imp 165 val {ant=ant1, conseq} = (dest_imp o snd o strip_forall o concl) imp1 166 val {ant=ant2, conseq} = (dest_imp o snd o strip_forall) conseq 167 val subj1 = (snd o strip_forall o concl) th1 168 val subj2 = (snd o strip_forall o concl) th2 169 val (_, ty_sub1) = match_term ant1 subj1 170 val (_, ty_sub2) = match_term ant2 subj2 171 val imp' = (*CAREFUL_*)INST_TYPE (ty_sub1 @ ty_sub2) imp1 172 in 173 MATCH_MP (MATCH_MP imp' th1) th2 174 end; 175 176 177fun REWRITE_THM th = REWRITE_TAC[th]; 178 179val rec UNDISCH_ALL_TAC :tactic = fn (asl,gl) => 180 if asl = [] then ALL_TAC (asl,gl) 181 else (UNDISCH_TAC (hd asl) 182 THEN UNDISCH_ALL_TAC) (asl,gl); 183 184val PROVE = Tactical.default_prover; 185 186fun upto from to = 187 if from>to then [] 188 else from::upto (from+1) to; 189 190fun wargs tylist = 191 let val nums = upto 1 (length tylist) 192(* val nms = map (fn n => implode ("T"::(explode(chr(n + ord"0"))))) nums in*) 193 val nms = map (fn n => "T"^Lib.int_to_string n) nums 194 in 195 map Psyntax.mk_var (zip nms tylist) 196 end; 197 198 199 200(* {tyname} is a string, denoting the name of the new quotient type. 201 {abs} is a string, denoting the name of the new onto function from the 202 original type to the new quotient type. 203 {rep} is a string, denoting the name of the new 1-1 function from the 204 new quotient type to the original type. 205 {equiv} is an "equivalence theorem" for the appropriate type, of the form 206 !(x:'a) (y:'a). R x y = (R x = R y) 207 where 'a is the type being lifted to the new quotient type, and 208 where R :'a -> 'a -> bool is an equivalence relation on 'a 209OR {equiv} is a "partial equivalence theorem", of the form 210 (?(x:'a). R x x) /\ (!(x:'a) (y:'a). R x y = R x x /\ R y y /\ (R x = R y)) 211 where 'a is the type being lifted to the new quotient type, and 212 where R :'a -> 'a -> bool is a partial equivalence relation on 'a 213*) 214 215(* Partial equivalence test case: 216 217val R = ���\x y:'a. Q x /\ Q y /\ (f x = f y :'b)���; 218 219val FUN_PEQUIV = store_thm 220 ("FUN_PEQUIV", 221 (���!(f:'a->'b) Q. 222 (?x. Q x) ==> 223 (?x. ^R x x) /\ 224 (!x y. ^R x y = 225 ^R x x /\ 226 ^R y y /\ 227 (^R x = ^R y))���), 228 PROVE_TAC[] 229 ); 230 231val NONZERO_EXISTS = store_thm 232 ("NONZERO_EXISTS", 233 (���?n. (\n. ~(n = 0)) n���), 234 RW_TAC arith_ss [] 235 ); 236 237val tyname = "mod7"; 238val abs = "mod7_ABS"; 239val rep = "mod7_REP"; 240val equiv = ISPEC ``\n. n MOD 7`` (MATCH_MP FUN_PEQUIV NONZERO_EXISTS); 241 242*) 243 244 245fun define_partial_quotient_type tyname abs rep equiv = 246 let 247 248 (* Extract the existing type, ty, and the equivalence relation, REL. *) 249 val equiv = PURE_REWRITE_RULE[PARTIAL_EQUIV_def] equiv 250 val (exist,pequiv) = CONJ_PAIR equiv 251 val (v, exist_tm) = boolSyntax.dest_exists (concl exist) 252 val ty = type_of v 253 val REL = rator (rator exist_tm) 254 val pty = (==`:^ty -> ^ty -> bool`==) 255 val _ = assert (curry op = (type_of REL)) pty 256 257 (* Prove that the partial equivalence relation is symmetric. *) 258 val (rs,Rrs) = ((I ## lhs) o strip_forall o concl) pequiv 259 val (th1,(th2,th3)) = ((I ## CONJ_PAIR) o CONJ_PAIR) 260 (CONV_RULE (REWR_CONV pequiv) (ASSUME Rrs)) 261 val sym1 = GENL rs (DISCH_ALL (CONV_RULE (REWR_CONV (GSYM pequiv)) 262 (LIST_CONJ [th2, th1, SYM th3]))) 263 val sym = GENL rs 264 (IMP_ANTISYM_RULE (SPECL rs sym1) (SPECL (rev rs) sym1)) 265 266(* We will now define the new type, and call it nty here. We represent 267 nty values as (isomorphic to) equivalence classes of ty objects. 268 The classes are functions from ty to bool. However, not all such 269 functions are also suitable equivalence classes. We must restrict 270 the type ty->bool by a predicate. 271 272 We take the predicate P to be 273 274 P : (ty -> bool) -> bool 275 P = \c. ?r. REL r r /\ (c = REL r) 276 277 That is, consider the sets of ty-values which are REL-equivalent. 278 Let each such set be represented by its characteristic function, 279 of type ty -> bool. Then any set of ty-values c is such an equivalence 280 set if and only if there is some ty-value, r, which is reflexive on REL 281 and the set of its equivalents is the same as that of the given set c. 282 283 If P c, then c is a suitable function to represent an nty. 284*) 285 286(* First we show that there is such a set of objects, that the 287 predicate P is non-empty. *) 288 289 val r = Term.variant (free_vars REL) (mk_var{Name="r", Ty=ty}) 290 val rcl = mk_comb{Rator=REL, Rand=r} 291 val Rrr = mk_comb{Rator=rcl, Rand=r} 292 val cty = type_of rcl 293 val c = Term.variant (free_vars rcl) (mk_var{Name="c", Ty=cty}) 294 val c' = prim_variant (c::free_vars rcl) c 295 val P = (���\ ^c. ?^r. ^Rrr /\ (^c = ^rcl)���) 296 val x = Term.variant (free_vars P) (mk_var{Name="x", Ty=ty}) 297 val xcl = mk_comb{Rator=REL, Rand=x} 298 val Rxx = mk_comb{Rator=xcl, Rand=x} 299 val ty_exists = 300 CHOOSE (x,exist) 301 (EXISTS (���?^c. ^P ^c���, xcl) 302 (EQ_MP (SYM (BETA_CONV (mk_comb{Rator=P, Rand=xcl}))) 303 (EXISTS (���?^r. ^Rrr /\ (^xcl = ^rcl)���, x) 304 (CONJ (ASSUME Rxx) (REFL xcl))))) 305 handle e => Raise e 306 307(* or, alternatively, 308 val ty_exists = TAC_PROOF(([], 309 ���?^c. ^P ^c���), 310 STRIP_ASSUME_TAC exist 311 THEN FIRST_ASSUM (fn th => EXISTS_TAC(rator(concl th))) 312 THEN CONV_TAC BETA_CONV 313 THEN FIRST_ASSUM (fn th => EXISTS_TAC(rand (concl th))) 314 THEN CONJ_TAC 315 THENL 316 [ POP_ASSUM ACCEPT_TAC, 317 REFL_TAC 318 ]) 319*) 320 321(* Then we can define the new type obj using 'new_type_definition'. *) 322(* This actually creates the new quotient type. *) 323 324 val TY_DEF = new_type_definition( tyname, ty_exists ) 325 val nty = (hd o #Args o dest_type o type_of o #Bvar o dest_exists 326 o concl) TY_DEF 327 328(* This creates the new type, "nty", but only implicitly establishes its 329 relationships to the original type of equivalence classes on ty. 330 To define the bijections to and from the new type, we use 331 'define_new_type_bijections'. This defines 332 ty_ABS : (ty -> bool) -> nty 333 ty_REP : nty -> (ty -> bool) . 334*) 335 val ty_bijections = define_new_type_bijections{ 336 name = tyname ^ "_bijections", 337 ABS = abs ^ "_CLASS", 338 REP = rep ^ "_CLASS", 339 tyax = TY_DEF} 340 val ABS_REP = CONJUNCT1 ty_bijections 341 val AR1 = (#lhs o dest_eq o #Body o dest_forall o concl) ABS_REP 342 val {Rator=cty_ABS, Rand=AR2} = dest_comb AR1 343 val cty_REP = #Rator(dest_comb AR2) 344(* or, 345 val cty_ABS = mk_const{Name = tyname ^ "_ABS_CLASS", 346 Ty = mk_type{Tyop="fun", Args=[cty,nty]}} 347 val cty_REP = mk_const{Name = tyname ^ "_REP_CLASS", 348 Ty = mk_type{Tyop="fun", Args=[nty,cty]}} 349*) 350 351(* ty_bijections looks like 352 (!a. cty_ABS (cty_REP a) = a) /\ 353 (!r. (\c. ?r. REL r r /\ (c = REL r)) r = 354 (cty_REP (cty_ABS r) = r)) 355but it could look like 356 (!a. cty_ABS (cty_REP a) = a) /\ 357 (!c. (?r. REL r r /\ (c = REL r)) = 358 (cty_REP (cty_ABS c) = c)) 359*) 360 361(* These bijections can be described more naturally and usefully. *) 362 val cty_ABS_REP = save_thm 363 (tyname ^ "_ABS_REP_CLASS", 364 CONV_RULE (RAND_CONV (RAND_CONV (ALPHA_CONV c THENC 365 ABS_CONV (LAND_CONV BETA_CONV)))) 366 ty_bijections) 367(* 368 val cty_ABS_REP = store_thm 369 (tyname ^ "_ABS_REP_CLASS", 370 (���(!a. ^cty_ABS (^cty_REP a) = a) /\ 371 (!^c. ^(beta_conv (mk_comb{Rator=P, Rand=c})) = 372 (^cty_REP (^cty_ABS ^c) = ^c))���), 373 REWRITE_TAC[ty_bijections] 374 THEN REWRITE_TAC[GSYM ty_bijections] 375 THEN BETA_TAC 376 THEN GEN_TAC 377 THEN REFL_TAC) 378*) 379 380(* We now use standard functions to prove that these bijection functions 381 are one-to-one and onto. The ABS function is one-to-one on its 382 defined domain. 383*) 384 val cty_REP_one_one = prove_rep_fn_one_one cty_ABS_REP 385 val cty_REP_onto = prove_rep_fn_onto cty_ABS_REP 386 val cty_ABS_one_one = 387 CONV_RULE (RAND_CONV (ALPHA_CONV c THENC 388 ABS_CONV (RAND_CONV (ALPHA_CONV c' THENC 389 ABS_CONV 390 (LAND_CONV BETA_CONV THENC 391 RAND_CONV (LAND_CONV BETA_CONV)))))) 392 (prove_abs_fn_one_one ty_bijections) 393 val cty_ABS_onto = 394 CONV_RULE (RAND_CONV (ABS_CONV (RAND_CONV (ALPHA_CONV c THENC 395 ABS_CONV (RAND_CONV BETA_CONV))))) 396 (prove_abs_fn_onto ty_bijections) 397 398(* 399> val obj_REP_one_one = 400 |- !a a'. (obj_REP a = obj_REP a') = a = a' 401> val obj_REP_onto = 402 |- !r. (\c. ?a. c = ALPHA_obj a) r = (?a. r = obj_REP a) 403> val obj_ABS_one_one = 404 |- !r r'. 405 (\c. ?a. c = ALPHA_obj a) r ==> 406 (\c. ?a. c = ALPHA_obj a) r' ==> 407 ((obj_ABS r = obj_ABS r') = r = r') 408> val obj_ABS_onto = 409 |- !a. ?r. (a = obj_ABS r) /\ (\c. ?a. c = ALPHA_obj a) r 410*) 411 412(* ===================================================================== *) 413(* define function to yield representative objects of the new objects *) 414(* ty_REP : nty -> ty, etc. *) 415(* We use the Hilbert choice operator (@) to not predjudice the choice. *) 416(* ===================================================================== *) 417 418 val ty_REP = mk_var{Name = rep, 419 Ty = mk_type{Tyop="fun", Args=[nty,ty]}} 420 val ty_REP_def = 421 new_definition(rep ^ "_def", 422 ���^ty_REP a = $@ (^cty_REP a)���) 423 val ty_REP = (rator o lhs o #Body o dest_forall o concl) ty_REP_def 424 425(* ===================================================================== *) 426(* define function to yield new objects from the base objects *) 427(* ty_ABS : ty -> nty, etc. *) 428(* We use the one-argument version of the curried equivalence relation. *) 429(* ===================================================================== *) 430 431 val ty_ABS = mk_var{Name = abs, 432 Ty = mk_type{Tyop="fun", Args=[ty,nty]}} 433 val ty_ABS_def = 434 new_definition(abs ^ "_def", 435 ���^ty_ABS r = ^cty_ABS (^REL r)���) 436 val ty_ABS = (rator o lhs o #Body o dest_forall o concl) ty_ABS_def 437 438(* ======================= *) 439(* L E M M A S *) 440(* ======================= *) 441 442 val r'tm = mk_var{Name="r'", Ty=ty} 443 val r'cl = mk_comb{Rator=REL, Rand=r'tm} 444 val rr'cl = mk_comb{Rator=rcl, Rand=r'tm} 445 val req = mk_eq{lhs=rcl, rhs=r'cl} 446 447 val atm = mk_var{Name="a", Ty=nty} 448 val ABS_REP = CONJUNCT1 cty_ABS_REP 449 val REP_ABS = CONJUNCT2 cty_ABS_REP 450 451 val ty_REP_REL = 452 GEN atm 453 (EQ_MP (SYM (SPEC (mk_comb{Rator=cty_REP, Rand=atm}) REP_ABS)) 454 (AP_TERM cty_REP (SPEC atm ABS_REP))) 455 456(* Alternative proof: 457 val ty_REP_REL = 458 (GEN atm o REWRITE_RULE[GSYM REP_ABS] 459 o AP_TERM cty_REP o SPEC atm) ABS_REP 460*) 461 462 val cty_REP_ABS = TAC_PROOF(([], 463 (���!r. ^REL r r ==> 464 (^cty_REP (^cty_ABS (^REL r)) = ^REL r)���)), 465 GEN_TAC 466 THEN DISCH_TAC 467 THEN PURE_REWRITE_TAC[GSYM REP_ABS] 468 THEN EXISTS_TAC r 469 THEN ASM_REWRITE_TAC[]) 470 471 fun DISCH_EQN th = 472 case List.find is_eq (rev (hyp th)) of 473 SOME t => DISCH t th 474 | NONE => raise Fail "quotient.DISCH_EQN: This should never happen" 475 fun DISCH_ALL_REV th = foldr (fn (a,th) => DISCH a th) th (hyp th) 476 477 val cty_ABS_11 = 478 let val aeq = mk_eq{lhs=mk_comb{Rator=cty_ABS, Rand=rcl}, 479 rhs=mk_comb{Rator=cty_ABS, Rand=r'cl}} 480 val th1 = AP_TERM cty_REP (ASSUME aeq) 481 val th2 = cty_REP_ABS 482 val x = mk_var{Name="x", Ty=cty} 483 val y = mk_var{Name="y", Ty=cty} 484 val th3 = SUBST [x |-> UNDISCH (SPEC r th2), 485 y |-> UNDISCH (SPEC r'tm th2)] 486 (mk_eq{lhs=x, rhs=y}) 487 th1 488 val th4 = DISCH_EQN th3 489 val th5 = DISCH_ALL (AP_TERM cty_ABS (ASSUME req)) 490 in 491 GENL[r,r'tm] (DISCH_ALL_REV (IMP_ANTISYM_RULE th4 th5)) 492 end; 493 494(* Alternative proof: 495 val cty_ABS_11 = TAC_PROOF(([], 496 (���!r r'. ^REL r r ==> ^REL r' r' ==> 497 ((^cty_ABS (^REL r) = ^cty_ABS (^REL r')) = 498 (^REL r = ^REL r'))���)), 499 GEN_TAC THEN GEN_TAC 500 THEN DISCH_TAC THEN DISCH_TAC 501 THEN EQ_TAC 502 THENL 503 [ DISCH_THEN (MP_TAC o AP_TERM cty_REP) 504 THEN IMP_RES_THEN REWRITE_THM cty_REP_ABS, 505 506 DISCH_THEN REWRITE_THM 507 ]) 508*) 509 510 val ty_REL_SELECT_REL = 511 GEN r (DISCH_ALL (SYM (last (CONJUNCTS 512 (CONV_RULE (REWR_CONV pequiv) 513 (UNDISCH (ISPECL [rcl,r] SELECT_AX))))))); 514 515 516(* ================================================= *) 517(* Q U O T I E N T P R O P E R T I E S *) 518(* ================================================= *) 519 520(* Prove the quotient type bijection properties for ABS and REP. *) 521 522 val ABS_REP_tm = (���^ty_ABS (^ty_REP a)���) 523 val inst = ASSUME (���^cty_REP a = ^rcl���) 524 val REP_a_tm = mk_comb{Rator=ty_REP, Rand=atm} 525 526 val ty_ABS_REP = 527 (GEN atm o 528 PURE_REWRITE_RULE[ABS_REP] o 529 CHOOSE (r, SPEC atm ty_REP_REL) o 530 UNDISCH o CONV_RULE (REWR_CONV AND_IMP_INTRO) o 531 DISCH_ALL o DISCH_EQN o 532 PURE_REWRITE_RULE[SYM inst] o 533 PURE_REWRITE_RULE[UNDISCH (SPEC r ty_REL_SELECT_REL)] o 534 PURE_REWRITE_RULE[inst]) 535 (PURE_REWRITE_CONV[ty_ABS_def,ty_REP_def] ABS_REP_tm) 536 537 val REL_REP_REFL = TAC_PROOF(([], 538 (���!a. ^REL (^ty_REP a) (^ty_REP a)���)), 539 GEN_TAC 540 THEN STRIP_ASSUME_TAC (SPEC atm ty_REP_REL) 541 THEN ASM_REWRITE_TAC[ty_REP_def] 542 THEN IMP_RES_THEN REWRITE_THM ty_REL_SELECT_REL 543 THEN MATCH_MP_TAC sym1 544 THEN IMP_RES_THEN REWRITE_THM ty_REL_SELECT_REL 545 THEN FIRST_ASSUM ACCEPT_TAC) 546 547(* 548 val ty_REP_REFL = GEN atm (SPEC REP_a_tm refl) 549*) 550 551 val equiv_ty_ABS = TAC_PROOF(([], 552 (���!r r'. ^REL r r' = 553 ^REL r r /\ ^REL r' r' /\ (^ty_ABS r = ^ty_ABS r')���)), 554 GEN_TAC THEN GEN_TAC 555 THEN CONV_TAC (LAND_CONV (REWR_CONV pequiv)) 556 THEN PURE_REWRITE_TAC[ty_ABS_def] 557 THEN EQ_TAC 558 THEN STRIP_TAC 559 THEN REPEAT CONJ_TAC 560 THEN TRY (FIRST_ASSUM ACCEPT_TAC) 561 THEN FIRST_ASSUM REWRITE_THM 562 THEN POP_ASSUM MP_TAC 563 THEN IMP_RES_THEN (IMP_RES_THEN REWRITE_THM) cty_ABS_11) 564 565(* alternative proofs: 566*) 567 568 val QUOTIENT_thm = REWRITE_RULE[GSYM QUOTIENT_def] 569 (LIST_CONJ [ty_ABS_REP, REL_REP_REFL, equiv_ty_ABS]) 570 571 in 572 save_thm(tyname^"_QUOTIENT", QUOTIENT_thm) 573 end; 574 575 576 577fun is_match_term tm1 tm2 = 578 (match_term tm1 tm2; true) handle _ => false; 579 580(* 581val equiv_tm = 582 ���!(x:'a) (y:'a). R x y = (R x = R y)���; 583 584val partial_equiv_tm = 585 ���(?(x:'a). R x x) /\ 586 (!(x:'a) (y:'a). R x y = R x x /\ R y y /\ (R x = R y))���; 587*) 588 589val equiv_tm = 590 ���EQUIV (R :'a -> 'a -> bool)���; 591 592val partial_equiv_tm = 593 ���PARTIAL_EQUIV (R :'a -> 'a -> bool)���; 594 595fun is_equiv th = is_match_term equiv_tm (concl th); 596 597fun is_partial_equiv th = is_match_term partial_equiv_tm (concl th); 598 599fun check_equiv th = 600 is_equiv th orelse is_partial_equiv th orelse 601 raise HOL_ERR { 602 origin_structure = "quotient", 603 origin_function = "check_equiv", 604 message = "The following is neither an equivalence nor a partial equivalence theorem:\n" ^ 605 thm_to_string th ^ "\n" 606 } 607 608fun distinct [] = true 609 | distinct (x::xs) = not (mem x xs) andalso distinct xs 610 611fun dest_EQUIV_cond tm = 612 let val (vrs, body) = strip_forall tm 613 val {ant, conseq} = Rsyntax.dest_imp body 614 val (E, R) = strip_comb ant 615 val Ename = #Name (Rsyntax.dest_const E) 616 val _ = assert (curry op = "EQUIV") Ename 617 val _ = assert (curry op = 1) (length R) 618 val R = el 1 R 619 val tau = fst (dom_rng (type_of R)) 620 in 621 (tau,R,conseq) 622 end 623 624fun strip_EQUIV_cond tm = 625 let val (tau,R,conseq) = dest_EQUIV_cond tm 626 val (taus,Rs,conseq) = strip_EQUIV_cond conseq 627 in 628 (tau::taus, R::Rs, conseq) 629 end 630 handle _ => ([],[],tm) 631 632fun check_tyop_equiv th = 633 let val (taus, Rs, uncond_tm) = strip_EQUIV_cond (concl th) 634 val _ = assert (all is_vartype) taus 635 val _ = assert distinct taus 636 val _ = assert distinct Rs 637 in 638 Term.free_vars (concl th) = [] andalso 639 is_match_term equiv_tm uncond_tm orelse raise Match 640 end 641 handle e => raise HOL_ERR { 642 origin_structure = "quotient", 643 origin_function = "check_tyop_equiv", 644 message = "The following does not have the form of a type quotient extension theorem:\n" ^ 645 thm_to_string th ^ "\n" 646 } 647 648 649fun dest_QUOTIENT_cond tm = 650 let val (vrs, body) = strip_forall tm 651 val {ant, conseq} = Rsyntax.dest_imp body 652 val (Q, R_abs_rep) = strip_comb ant 653 val Qname = #Name (Rsyntax.dest_const Q) 654 val _ = assert (curry op = "QUOTIENT") Qname 655 val _ = assert (curry op = vrs) R_abs_rep 656 val _ = assert (curry op = 3) (length R_abs_rep) 657 val R = el 1 R_abs_rep 658 val abs = el 2 R_abs_rep 659 val rep = el 3 R_abs_rep 660 val (tau,ksi) = dom_rng (type_of abs) 661 in 662 (tau,ksi,R,abs,rep,conseq) 663 end 664 665fun strip_QUOTIENT_cond tm = 666 let val (tau,ksi,R,abs,rep,conseq) = dest_QUOTIENT_cond tm 667 val (taus,ksis,Rs,abss,reps,conseq) = strip_QUOTIENT_cond conseq 668 in 669 (tau::taus, ksi::ksis, R::Rs, abs::abss, rep::reps, conseq) 670 end 671 handle _ => ([],[],[],[],[],tm) 672 673val quotient_tm = ���QUOTIENT R (abs:'a -> 'b) rep���; 674 675fun check_tyop_quotient th = 676 let val (taus, ksis, Rs, abss, reps, uncond_tm) = 677 strip_QUOTIENT_cond (concl th) 678 val _ = assert (all is_vartype) (append taus ksis) 679 val _ = assert distinct (append taus ksis) 680 val _ = assert distinct (append (append Rs abss) reps) 681 in 682 Term.free_vars (concl th) = [] andalso 683 is_match_term quotient_tm uncond_tm orelse raise Match 684 end 685 handle e => raise HOL_ERR { 686 origin_structure = "quotient", 687 origin_function = "check_tyop_quotient", 688 message = "The following does not have the form of a quotient type extension theorem:\n" ^ 689 thm_to_string th ^ "\n" 690 } 691 692fun check_tyop_simp th = 693 let val tm = concl th 694 val (l,r) = Psyntax.dest_eq tm 695 val (name,rty) = Psyntax.dest_const r 696 val (cn,args) = strip_comb l 697 val _ = assert (all (curry op = name o fst o Psyntax.dest_const)) args 698 val atys = map (fst o dom_rng o type_of) args 699 val tys = (snd o Psyntax.dest_type o fst o dom_rng) rty 700 val _ = assert (curry op = []) (set_diff atys tys) 701 in 702 true 703 end 704 handle e => raise HOL_ERR { 705 origin_structure = "quotient", 706 origin_function = "check_tyop_simp", 707 message = "The following does not have the form of a simplification theorem for either\nrelation extension simplification or map function extension simplification:\n" ^ 708 thm_to_string th ^ "\n" 709 } 710 711 712fun define_quotient_type tyname abs rep equiv = 713 let val equiv = PURE_REWRITE_RULE (map GSYM [EQUIV_def,PARTIAL_EQUIV_def]) equiv 714 in 715 define_partial_quotient_type tyname abs rep 716 (if is_partial_equiv equiv 717 then equiv 718 else MATCH_MP EQUIV_IMP_PARTIAL_EQUIV equiv) 719 end 720 721 722(* This section is code to construct a quotient from a normal equivalence; 723 It is now superceeded by the more general code for a partial equivalance. 724 725 726 else 727 728 let 729 730 (* Extract the existing type, ty, and the equivalence relation, REL. *) 731 val (vs, equiv_tm) = strip_forall (concl equiv) 732 val v = hd vs 733 val ty = type_of v 734 val REL = rator (rator (lhs equiv_tm)) 735 val pty = (==`:^ty -> ^ty -> bool`==) 736 val _ = assert (curry op = (type_of REL)) pty 737 738 val refl = GEN v (EQ_MP (SYM (SPECL[v,v] equiv)) 739 (REFL (mk_comb{Rator=REL, Rand=v}))) 740 741(* We will now define the new type, and call it nty here. 742 We represent nty values as equivalence classes of ty objects. 743 The classes are functions from ty to bool. However, not all such 744 functions are also suitable equivalence classes. We must restrict 745 the type ty->bool by a predicate. 746 747 We take the predicate P to be 748 749 P : (ty -> bool) -> bool 750 P = \c. ?r. c = REL r 751 752 That is, consider the sets of ty-values which are REL-equivalent. 753 Let each such set be represented by its characteristic function, 754 of type ty -> bool. Then any set of ty-values is such an equivalence 755 set if and only if there is some ty, a, whose characteristic 756 function is the same as that of the given set. 757 758 If P x, then x is a suitable function to represent an obj. 759*) 760 761(* First we show that there is such a set of objects, that the 762 predicate P is non-empty. *) 763 764 val rtm = mk_var{Name="r", Ty=ty} 765 val rcl = mk_comb{Rator=REL, Rand=rtm} 766 val cty = type_of rcl 767 val P = (���\c. ?r. c = ^rcl���) 768 val ty_exists = 769 EXISTS (���?x. ^P x���, rcl) 770 (EQ_MP (SYM (BETA_CONV (mk_comb{Rator=P, Rand=rcl}))) 771 (EXISTS (���?a. ^rcl = ^REL a���, rtm) (REFL rcl))) 772(* or, 773 val ty_exists = TAC_PROOF(([], 774 ���?x. ^P x���), 775 EXISTS_TAC rcl 776 THEN BETA_TAC 777 THEN EXISTS_TAC rtm 778 THEN REFL_TAC) 779*) 780 781(* Then we can define the new type obj using 'new_type_definition'. *) 782 val TY_DEF = new_type_definition( tyname, ty_exists ) 783 val nty = (hd o #Args o dest_type o type_of o #Bvar o dest_exists 784 o concl) TY_DEF 785 786(* This creates the new type, "nty", but only implicitly establishes its 787 relationships to the original type of equivalence classes on ty. 788 To define the bijections to and from the new type, we use 789 'define_new_type_bijections'. This defines 790 ty_ABS : (ty -> bool) -> nty 791 ty_REP : nty -> (ty -> bool) . 792*) 793 val ty_bijections = define_new_type_bijections{ 794 name = tyname ^ "_bijections", 795 ABS = abs ^ "_CLASS", 796 REP = rep ^ "_CLASS", 797 tyax = TY_DEF} 798 val ABS_REP = CONJUNCT1 ty_bijections 799 val AR1 = (#lhs o dest_eq o #Body o dest_forall o concl) ABS_REP 800 val {Rator=cty_ABS, Rand=AR2} = dest_comb AR1 801 val cty_REP = #Rator(dest_comb AR2) 802(* or, 803 val cty_ABS = mk_const{Name = tyname ^ "_ABS_CLASS", 804 Ty = mk_type{Tyop="fun", Args=[cty,nty]}} 805 val cty_REP = mk_const{Name = tyname ^ "_REP_CLASS", 806 Ty = mk_type{Tyop="fun", Args=[nty,cty]}} 807*) 808 809(* These bijections can be described more naturally and usefully. *) 810 val cty_ABS_REP = store_thm 811 (tyname ^ "_ABS_REP_CLASS", 812 (���(!a. ^cty_ABS (^cty_REP a) = a) /\ 813 (!r. ^cty_REP (^cty_ABS (^REL r)) = ^REL r)���), 814 REWRITE_TAC[ty_bijections] 815 THEN REWRITE_TAC[GSYM ty_bijections] 816 THEN BETA_TAC 817 THEN GEN_TAC 818 THEN EXISTS_TAC rtm 819 THEN REFL_TAC) 820 821(* We now use standard functions to prove that these bijection functions 822 are one-to-one and onto. The ABS function is one-to-one on its 823 defined domain. 824*) 825 val cty_REP_one_one = prove_rep_fn_one_one ty_bijections 826 val cty_REP_onto = prove_rep_fn_onto ty_bijections 827 val cty_ABS_one_one = prove_abs_fn_one_one ty_bijections 828 val cty_ABS_onto = prove_abs_fn_onto ty_bijections 829 830(* 831> val obj_REP_one_one = 832 |- !a a'. (obj_REP a = obj_REP a') = a = a' 833> val obj_REP_onto = 834 |- !r. (\c. ?a. c = ALPHA_obj a) r = (?a. r = obj_REP a) 835> val obj_ABS_one_one = 836 |- !r r'. 837 (\c. ?a. c = ALPHA_obj a) r ==> 838 (\c. ?a. c = ALPHA_obj a) r' ==> 839 ((obj_ABS r = obj_ABS r') = r = r') 840> val obj_ABS_onto = 841 |- !a. ?r. (a = obj_ABS r) /\ (\c. ?a. c = ALPHA_obj a) r 842*) 843 844(* ===================================================================== *) 845(* define function to yield representative objects of the new objects *) 846(* ty_REP : nty -> ty, etc. *) 847(* We use the Hilbert choice operator (@) to not predjudice the choice. *) 848(* ===================================================================== *) 849 850 val ty_REP = mk_var{Name = rep, 851 Ty = mk_type{Tyop="fun", Args=[nty,ty]}} 852 val ty_REP_def = 853 new_definition(rep ^ "_def", 854 ���^ty_REP a = $@ (^cty_REP a)���) 855 val ty_REP = (#Rator o dest_comb o #lhs o dest_eq 856 o #Body o dest_forall o concl) ty_REP_def 857 858(* ===================================================================== *) 859(* define function to yield new objects from the base objects *) 860(* ty_ABS : ty -> nty, etc. *) 861(* We use the one-argument version of the curried equivalence relation. *) 862(* ===================================================================== *) 863 864 val ty_ABS = mk_var{Name = abs, 865 Ty = mk_type{Tyop="fun", Args=[ty,nty]}} 866 val ty_ABS_def = 867 new_definition(abs ^ "_def", 868 ���^ty_ABS r = ^cty_ABS (^REL r)���) 869 val ty_ABS = (#Rator o dest_comb o #lhs o dest_eq 870 o #Body o dest_forall o concl) ty_ABS_def 871 872(* ======================= *) 873(* L E M M A S *) 874(* ======================= *) 875 876 val r'tm = mk_var{Name="r'", Ty=ty} 877 val r'cl = mk_comb{Rator=REL, Rand=r'tm} 878 val rr'cl = mk_comb{Rator=rcl, Rand=r'tm} 879 val req = mk_eq{lhs=rcl, rhs=r'cl} 880 881 val atm = mk_var{Name="a", Ty=nty} 882 val ABS_REP = CONJUNCT1 ty_bijections 883 val REP_ABS = CONJUNCT2 ty_bijections 884 885 val ty_REP_REL = 886 let val th1 = 887 EQ_MP (SYM (SPEC (mk_comb{Rator=cty_REP, Rand=atm}) REP_ABS)) 888 (AP_TERM cty_REP (SPEC atm ABS_REP)) 889 in 890 GEN atm (EQ_MP (BETA_CONV (concl th1)) th1) 891 end 892 893(* Alternative proof: 894 val ty_REP_REL = 895 (GEN atm o BETA_RULE o REWRITE_RULE[GSYM REP_ABS] 896 o AP_TERM cty_REP o SPEC atm) ABS_REP 897*) 898 899 val cty_ABS_11 = 900 let val aeq = mk_eq{lhs=mk_comb{Rator=cty_ABS, Rand=rcl}, 901 rhs=mk_comb{Rator=cty_ABS, Rand=r'cl}} 902 val th1 = AP_TERM cty_REP (ASSUME aeq) 903 val th2 = CONJUNCT2 cty_ABS_REP 904 val x = mk_var{Name="x", Ty=cty} 905 val y = mk_var{Name="y", Ty=cty} 906 val th3 = SUBST [x |-> SPEC rtm th2, y |-> SPEC r'tm th2] 907 (mk_eq{lhs=x, rhs=y}) 908 th1 909 val th4 = DISCH_ALL th3 910 val th5 = DISCH_ALL (AP_TERM cty_ABS (ASSUME req)) 911 in 912 GENL[rtm,r'tm] (IMP_ANTISYM_RULE th4 th5) 913 end; 914 915(* Alternative proof: 916 val cty_ABS_11 = TAC_PROOF(([], 917 (���!r r'. (^cty_ABS (^REL r) = ^cty_ABS (^REL r')) = 918 (^REL r = ^REL r')���)), 919 GEN_TAC THEN GEN_TAC 920 THEN EQ_TAC 921 THENL 922 [ DISCH_THEN (MP_TAC o AP_TERM cty_REP) 923 THEN REWRITE_TAC[cty_ABS_REP], 924 925 DISCH_THEN REWRITE_THM 926 ]) 927*) 928 929 val ty_REL_SELECT_REL = 930 let val th1 = MP (ISPECL [rcl,rtm] SELECT_AX) (SPEC rtm refl) 931 val th2 = SPECL[rtm,#Rand(dest_comb(concl th1))] equiv 932 in 933 GEN rtm (SYM (EQ_MP th2 th1)) 934 end; 935 936(* Alternative proof: 937 val ty_REL_SELECT_REL = 938 (SYM o REWRITE_RULE[equiv]) 939 (MP (ISPECL [rcl,rtm] SELECT_AX) (SPEC rtm refl)) 940*) 941 942 943(* ================================================= *) 944(* Q U O T I E N T P R O P E R T I E S *) 945(* ================================================= *) 946 947(* Prove the quotient type bijection properties for ABS and REP. *) 948 949 val ABS_REP_tm = (���^ty_ABS (^ty_REP a)���) 950 val inst = ASSUME (���^cty_REP a = ^rcl���) 951 val REP_a_tm = mk_comb{Rator=ty_REP, Rand=atm} 952 953 val ty_ABS_REP = 954 (GEN atm o 955 REWRITE_RULE[ABS_REP] o 956 CHOOSE (rtm, SPEC atm ty_REP_REL) o 957 REWRITE_RULE[SYM inst] o 958 REWRITE_RULE[ty_REL_SELECT_REL] o 959 REWRITE_RULE[inst]) 960 (REWRITE_CONV[ty_ABS_def,ty_REP_def] ABS_REP_tm) 961 962 val ty_REP_REFL = GEN atm (SPEC REP_a_tm refl) 963 964 val equiv_ty_ABS = TAC_PROOF(([], 965 (���!r r'. ^REL r r' = 966 ^REL r r /\ ^REL r' r' /\ (^ty_ABS r = ^ty_ABS r')���)), 967 GEN_TAC THEN GEN_TAC 968 THEN PURE_REWRITE_TAC[EQT_INTRO (SPEC rtm refl)] 969 THEN REWRITE_TAC[ty_ABS_def] 970 THEN REWRITE_TAC[cty_ABS_11] 971 THEN CONV_TAC (LAND_CONV (REWR_CONV equiv)) 972 THEN REFL_TAC) 973 974(* alternative proofs: 975 976 GEN_TAC THEN GEN_TAC 977 THEN REWRITE_TAC[GSYM cty_REP_one_one] 978 THEN REWRITE_TAC[ty_ABS_def] 979 THEN REWRITE_TAC[cty_ABS_REP] 980 THEN REWRITE_TAC[equiv]) 981 982 val equiv_ty_ABS = 983 (GEN rtm o GEN r'tm o SYM o 984 REWRITE_CONV[ty_ABS_def,cty_ABS_11,equiv]) 985 (���^ty_ABS r = ^ty_ABS r'���) 986*) 987 988 val QUOTIENT_thm = REWRITE_RULE[GSYM QUOTIENT_def] 989 (LIST_CONJ [ty_ABS_REP, ty_REP_REFL, equiv_ty_ABS]) 990 991 in 992 save_thm(tyname^"_QUOTIENT", QUOTIENT_thm) 993 end 994 end; 995 996End of code for a quotient from a normal equivalence. *) 997 998 999 1000(* Equivalence theorems have the form: 1001 EQUIV R 1002 which can be translated into the equivalent 1003 !x y. R x y = (R x = R y) 1004 1005 Here are routines to create equivalence theorems, 1006 and to convert them into theorems of 1007 reflexivity, symmetry, and transitivity. *) 1008 1009fun equiv_refl equiv = 1010 CONJUNCT1 (CONV_RULE (REWRITE_CONV[EQUIV_def] 1011 THENC REWR_CONV EQUIV_REFL_SYM_TRANS) equiv) 1012 1013fun equiv_sym equiv = 1014 CONJUNCT1 (CONJUNCT2 (CONV_RULE (REWRITE_CONV[EQUIV_def] 1015 THENC REWR_CONV EQUIV_REFL_SYM_TRANS) equiv)) 1016 1017fun equiv_trans equiv = 1018 CONJUNCT2 (CONJUNCT2 (CONV_RULE (REWRITE_CONV[EQUIV_def] 1019 THENC REWR_CONV EQUIV_REFL_SYM_TRANS) equiv)) 1020 1021fun refl_sym_trans_equiv refl sym trans = 1022 CONV_RULE (REWR_CONV (GSYM EQUIV_REFL_SYM_TRANS) 1023 THENC ONCE_REWRITE_CONV[GSYM EQUIV_def] ) 1024 (CONJ refl (CONJ sym trans)) 1025 1026 1027fun mkRELty ty = ty --> ty --> bool; 1028 1029 1030fun identity_equiv ty = 1031 INST_TYPE [{redex=alpha, residue=ty}] IDENTITY_EQUIV; 1032 1033fun pair_equiv left_EQUIV right_EQUIV = 1034 MATCH_MP (MATCH_MP PAIR_EQUIV left_EQUIV) right_EQUIV; 1035 1036fun sum_equiv left_EQUIV right_EQUIV = 1037 MATCH_MP (MATCH_MP SUM_EQUIV left_EQUIV) right_EQUIV; 1038 1039fun list_equiv elem_EQUIV = 1040 MATCH_MP LIST_EQUIV elem_EQUIV; 1041 1042fun option_equiv elem_EQUIV = 1043 MATCH_MP OPTION_EQUIV elem_EQUIV; 1044 1045 1046fun find_base tm = (find_base o #conseq o dest_imp o snd o strip_forall) tm 1047 handle _ => tm 1048 1049fun equiv_type th = 1050 (fst o dom_rng o type_of o rand o find_base o concl) th 1051 (* (#Ty o dest_var o #Bvar o dest_forall o find_base o concl) th *) 1052 handle e => raise HOL_ERR { 1053 origin_structure = "quotient", 1054 origin_function = "equiv_type", 1055 message ="Invalid structure of equivalence theorem:\n" 1056 ^ thm_to_string th ^ "\n" 1057 } 1058 1059fun make_equiv equivs tyop_equivs ty = 1060 let val base_tys = map equiv_type equivs 1061 val all_equivs = equivs @ tyop_equivs 1062 val etys = map equiv_type all_equivs 1063 val etys_equivs = zip etys all_equivs 1064 1065 fun contains_base ty = 1066 if is_vartype ty then false 1067 else if mem ty base_tys then true 1068 else exists contains_base (#Args (dest_type ty)) 1069 1070 fun prim_make_equiv ty = 1071 tryfind (fn (ety, equiv) => 1072 CAREFUL_INST_TYPE (match_type ety ty) equiv) 1073 etys_equivs 1074 1075 fun main_make_equiv ty = 1076 if not (contains_base ty) then identity_equiv ty 1077 else 1078 let val {Tyop, Args} = dest_type ty 1079 val ths = map main_make_equiv Args 1080 val tyop = prim_make_equiv ty 1081 (* this may be one of the base equiv theorems, 1082 or one of the tyop conditional equiv ths. *) 1083 (* may need to move type vars in tyop to genvars, 1084 to avoid clashes with type vars in "ths" *) 1085 val vs = (map type_vars_in_term o get_ants o concl) tyop 1086 val vs = mk_set (flatten vs) 1087 val gs = map (fn v => Type.gen_tyvar()) vs 1088 val sub = map2 (fn v => fn g => {redex=v,residue=g}) 1089 vs gs 1090 val tyop' = INST_TYPE sub tyop 1091 in foldl (fn (arg,qth) => MATCH_MP qth arg 1092 handle _ => qth) 1093 tyop' ths 1094 end 1095 handle _ => identity_equiv ty 1096 in 1097 main_make_equiv ty 1098 handle _ =>raise HOL_ERR { 1099 origin_structure = "quotient", 1100 origin_function = "make_equiv", 1101 message = "Could not form the " ^ 1102 "equivalence theorem for " ^ 1103 type_to_string ty 1104 } 1105 end; 1106 1107 1108 1109fun identity_quotient ty = 1110 INST_TYPE [{redex=alpha, residue=ty}] IDENTITY_QUOTIENT; 1111 1112 1113fun pair_quotient left_QUOTIENT right_QUOTIENT = 1114 REWRITE_RULE[PAIR_REL_EQ,PAIR_MAP_I] 1115 (C_MATCH_MP2 PAIR_QUOTIENT left_QUOTIENT right_QUOTIENT); 1116 1117 1118fun sum_quotient left_QUOTIENT right_QUOTIENT = 1119 REWRITE_RULE[SUM_REL_EQ,SUM_MAP_I] 1120 (C_MATCH_MP2 SUM_QUOTIENT left_QUOTIENT right_QUOTIENT); 1121 1122 1123fun list_quotient elem_QUOTIENT = 1124 REWRITE_RULE[LIST_REL_EQ,LIST_MAP_I] 1125 (C_MATCH_MP LIST_QUOTIENT elem_QUOTIENT); 1126 1127 1128fun option_quotient base_QUOTIENT = 1129 REWRITE_RULE[OPTION_REL_EQ,OPTION_MAP_I] 1130 (C_MATCH_MP OPTION_QUOTIENT base_QUOTIENT); 1131 1132 1133fun fun_quotient domain_QUOTIENT range_QUOTIENT = 1134 REWRITE_RULE[FUN_REL_EQ,FUN_MAP_I] 1135 (C_MATCH_MP2 FUN_QUOTIENT domain_QUOTIENT range_QUOTIENT); 1136 1137 1138 1139 1140 1141(**) 1142fun ptm s tm = if !chatting then (print s; print_term tm; print "\n"; tm) 1143 else tm; 1144 1145fun pth s th = if !chatting then (print s; print_thm th; print "\n"; th) 1146 else th; 1147(**) 1148 1149fun quotient_type th = (hd o tl o #Args o dest_type o type_of 1150 o rand o find_base o concl) th 1151 handle e => raise HOL_ERR { 1152 origin_structure = "quotient", 1153 origin_function = "quotient_type", 1154 message ="Invalid structure of quotient theorem:\n" 1155 ^ thm_to_string th ^ "\n" 1156 } 1157 1158fun make_hyp_quotient hyp_quots quots tyop_quots ty = 1159 let val base_tys = map quotient_type quots 1160 val hqtys = map quotient_type hyp_quots 1161 val hqty_quots = zip hqtys hyp_quots 1162 val all_quots = quots @ tyop_quots 1163 val qtys = map quotient_type all_quots 1164 val qty_quots = zip qtys all_quots 1165 fun contains_base ty = 1166 if is_vartype ty then false 1167 else if (*mem ty base_tys*) exists (can (match_type ty)) base_tys then true 1168 else exists contains_base (#Args (dest_type ty)) 1169 fun prim_make_quotient ty = 1170 assoc ty hqty_quots 1171 handle e => 1172 tryfind (fn (rty,qth) => CAREFUL_INST_TYPE (match_type rty ty) qth) 1173 qty_quots 1174 fun main_make_quotient ty = 1175 (if is_vartype ty then assoc ty hqty_quots 1176 else 1177 if not (contains_base ty) then identity_quotient ty 1178 else 1179 let val {Tyop, Args} = dest_type ty 1180 val ths = map main_make_quotient Args 1181 in 1182 let val tyop = prim_make_quotient ty 1183 (* this may be one of the base quotient theorems, 1184 or one of the tyop conditional quotient ths. *) 1185 (* may need to move type vars in tyop to genvars, 1186 to avoid clashes with type vars in "ths" *) 1187 val vs = (map type_vars_in_term o get_ants o concl) 1188 tyop 1189 val vs = mk_set (flatten vs) 1190 val gs = map (fn v => Type.gen_tyvar()) vs 1191 val sub = map2 (fn v => fn g => {redex=v,residue=g}) 1192 vs gs 1193 val tyop' = INST_TYPE sub tyop 1194 in foldl (fn (arg,qth) => MATCH_MP qth arg 1195 handle _ => qth) 1196 tyop' ths 1197 end 1198 end) 1199 handle _ => identity_quotient ty 1200 in 1201 main_make_quotient ty 1202 end; 1203 1204fun make_quotient quots tyop_quots ty = make_hyp_quotient [] quots tyop_quots ty 1205 1206 1207(* 1208structure Parse: 1209datatype fixity = RF of term_grammar.rule_fixity | Binder 1210 1211structure term_grammar: 1212datatype rule_fixity = 1213 Infix of associativity * int | Closefix | Suffix of int | Prefix of int 1214 1215structure HOLgrammars : 1216datatype associativity = LEFT | RIGHT | NONASSOC 1217*) 1218 1219 1220 1221 1222fun fun_tys fty = 1223 let val {Tyop, Args} = dest_type fty 1224 val _ = assert (curry op = "fun") Tyop 1225 val dty = hd Args 1226 val rty = hd (tl Args) 1227 in 1228 dty :: fun_tys rty 1229 end 1230 handle _ => [fty]; 1231 1232fun sub_tys ty = 1233 let val {Tyop, Args} = dest_type ty 1234 in 1235 ty :: flatten (map sub_tys Args) 1236 end 1237 handle _ => [ty]; 1238 1239fun dest_cons l = (hd l, tl l); 1240 1241 1242fun form_hyp_abs_rep_functions hyp_quot_ths quot_ths tyops tyop_simps = 1243 1244 let val hargs = map (snd o strip_comb o concl) hyp_quot_ths 1245 val hRELs = map hd hargs 1246 val habss = map (hd o tl) hargs 1247 val hreps = map (hd o tl o tl) hargs 1248 val hratys = map (#Args o dest_type o type_of) habss 1249 val hrtys = map hd hratys 1250 val hatys = map (hd o tl) hratys 1251 1252 val hrtys_atys = zip hrtys hatys 1253 val hatys_rtys = zip hatys hrtys 1254 val hrtys_abss = zip hrtys habss 1255 val hatys_reps = zip hatys hreps 1256 val hrtys_RELs = zip hrtys hRELs 1257 1258 val args = map (snd o strip_comb o concl) quot_ths 1259 val RELs = map hd args 1260 val abss = map (hd o tl) args 1261 val reps = map (hd o tl o tl) args 1262 val ratys = map (#Args o dest_type o type_of) abss 1263 val rtys = map hd ratys 1264 val atys = map (hd o tl) ratys 1265 1266 val rtys_atys = zip rtys atys 1267 val rtys_abss = zip rtys abss 1268 val atys_reps = zip atys reps 1269 val rtys_RELs = zip rtys RELs 1270 1271 (* we use ML op = to match types for hrtys, hatys *) 1272 (* we use Type.match_type, Type.type_subst to match types for rtys, atys *) 1273 1274 fun prim_absty ty = assoc ty hrtys_atys 1275 handle _ => 1276 tryfind (fn (rty,aty) => 1277 type_subst (match_type rty ty) aty) 1278 rtys_atys 1279 handle _ => ty 1280 1281 fun prim_repty ty = assoc ty hatys_rtys 1282 handle _ => 1283 tryfind (fn (rty,aty) => 1284 type_subst (match_type aty ty) rty) 1285 rtys_atys 1286 handle _ => ty 1287 1288 fun absty ty = if is_vartype ty then prim_absty ty 1289 else 1290 let val {Tyop, Args} = dest_type ty 1291 val Args' = map absty Args 1292 in prim_absty (mk_type{Tyop=Tyop, Args=Args'}) 1293 end 1294 1295 fun repty ty = if is_vartype ty then prim_repty ty 1296 else 1297 let val {Tyop, Args} = dest_type ty 1298 val Args' = map repty Args 1299 in prim_repty (mk_type{Tyop=Tyop, Args=Args'}) 1300 end 1301 1302 fun prim_is_abs_ty ty = mem ty hatys orelse 1303 (tryfind (C match_type ty) atys; true) 1304 handle _ => false 1305 1306 fun prim_is_rep_ty ty = mem ty hrtys orelse 1307 (tryfind (C match_type ty) rtys; true) 1308 handle _ => false 1309 1310 fun is_abs_ty ty = if is_vartype ty then mem ty hatys 1311 else 1312 prim_is_abs_ty ty orelse 1313 exists is_abs_ty (#Args (dest_type ty)) 1314 1315 fun is_rep_ty ty = if is_vartype ty then mem ty hrtys 1316 else 1317 prim_is_rep_ty ty orelse 1318 exists is_rep_ty (#Args (dest_type ty)) 1319 1320 1321 fun get_abs ty = 1322 let val qth = make_hyp_quotient hyp_quot_ths quot_ths tyops ty 1323 in (rand o rator o concl o PURE_REWRITE_RULE tyop_simps) qth 1324 end 1325 1326 fun get_rep ty = 1327 let val qth = make_hyp_quotient hyp_quot_ths quot_ths tyops (repty ty) 1328 in (rand o concl o PURE_REWRITE_RULE tyop_simps) qth 1329 end 1330 1331 fun tyREL ty = 1332 let val qth = make_hyp_quotient hyp_quot_ths quot_ths tyops ty 1333 val qth' = REWRITE_RULE tyop_simps qth 1334 in (hd o snd o strip_comb o concl) qth' 1335 end 1336 1337 1338 fun mkabs tm = let val ty = type_of tm in 1339 if not (is_rep_ty ty) then tm 1340 else mk_comb{Rator=get_abs ty, Rand=tm} 1341 end 1342 1343 fun mkrep tm = let val ty = type_of tm in 1344 if not (is_abs_ty ty) then tm 1345 else mk_comb{Rator=get_rep ty, Rand=tm} 1346 end 1347 1348 in 1349 (is_abs_ty, is_rep_ty, absty, repty, get_abs, get_rep, mkabs, mkrep, tyREL) 1350 end; 1351 1352fun form_abs_rep_functions quot_ths tyops tyop_simps = 1353 form_hyp_abs_rep_functions [] quot_ths tyops tyop_simps 1354 1355 1356fun tyop_rec th = 1357 let val args = snd (strip_comb (find_base (concl th))) 1358 val R = hd args 1359 val abs = (hd o tl) args 1360 val rep = (hd o tl o tl) args 1361 val rty = (hd o #Args o dest_type o type_of) abs 1362 val Tyop = (#Tyop o dest_type) rty 1363 val Relop = (#Name o dest_const o fst o strip_comb) R 1364 val Funop = (#Name o dest_const o fst o strip_comb) abs 1365 in {Tyop=Tyop, Relop=Relop, Funop=Funop} 1366 end 1367 1368 1369fun check_quotient_ty tys_quot_ths ty = 1370 if is_vartype ty then ty 1371 else let val {Tyop, Args} = dest_type ty 1372 (* val arg_quots = check_quotient_tys Args *) 1373 fun is_ty_qth (rty,qth) = CAREFUL_INST_TYPE (match_type rty ty) qth 1374 (* (#Tyop(dest_type rty) = Tyop) *) 1375 val ty_qty = tryfind is_ty_qth tys_quot_ths 1376 handle HOL_ERR e => 1377 raise HOL_ERR { 1378 origin_structure = "quotient", 1379 origin_function = "check_quotient_ty", 1380 message = "Could not lift the type `" ^ 1381 type_to_string ty ^ "`;\n" ^ 1382 "Missing quotient extension theorem for type constructor " ^ 1383 "\"" ^ Tyop ^ "\".\n" ^ 1384 "Please prove and add to \"tyop_quotients\" inputs for quotient package.\n " (* ^ 1385 exn_to_string (HOL_ERR e) *) 1386 } 1387 in ty 1388 end 1389 1390and check_quotient_tys tys_quot_ths tys = map (check_quotient_ty tys_quot_ths) tys 1391 1392 1393fun define_quotient_lifted_function quot_ths tyops tyop_simps = 1394 let 1395 (* no refls *) 1396 val syms = map (MATCH_MP QUOTIENT_SYM) quot_ths 1397 val trans = map (MATCH_MP QUOTIENT_TRANS) quot_ths 1398 1399 val unp_quot_ths = map (PURE_REWRITE_RULE[QUOTIENT_def]) quot_ths 1400 val (ABS_REP, (REP_REFL, ABS11)) = ((I ## unzip) o unzip) 1401 (map ((I ## CONJ_PAIR) o CONJ_PAIR) unp_quot_ths) 1402 val (abss, rep_as) = unzip (map 1403 (Psyntax.dest_comb o lhs o #Body o dest_forall o concl) ABS_REP) 1404 val reps = map (#Rator o dest_comb) rep_as 1405 val RELs = map (hd o snd o strip_comb o concl) quot_ths 1406 val tys = map (hd o #Args o dest_type o type_of) RELs 1407 val ntys = map (hd o #Args o dest_type o type_of) reps 1408 1409 val tys_quot_ths = zip tys quot_ths 1410 val tyop_tys = map quotient_type tyops 1411 val tyop_ty_ths = zip tyop_tys tyops 1412 1413 1414 val (is_abs_ty, is_rep_ty, absty, repty, get_abs, get_rep, 1415 mkabs, mkrep, tyREL) = 1416 form_abs_rep_functions quot_ths tyops tyop_simps; 1417 1418 1419 fun dest_funtype ty = 1420 if (mem ty tys) 1421 then [ty] 1422 else let val {Tyop=f, Args=lr} = dest_type ty 1423 val l = hd lr 1424 val r = hd (tl lr) 1425 val _ = assert(curry op = "fun") f 1426 in [l]@(dest_funtype r) 1427 end 1428 handle _ => [ty] 1429 1430 fun eta_funtype (ty1::ty2::[]) = 1431 if not (is_rep_ty ty1) andalso not (is_rep_ty ty2) 1432 then [mk_type{Tyop="fun", Args=[ty1,ty2]}] 1433 else [ty1,ty2] 1434 | eta_funtype (ty::[]) = [ty] 1435 | eta_funtype ([]) = [] 1436 | eta_funtype (ty::tys) = 1437 let val tys' = eta_funtype tys in 1438 if (length tys' < length tys) 1439 then eta_funtype(ty::tys') 1440 else ty::tys' 1441 end 1442 1443 fun reptm ((nty,rep)::tyrs) tm = 1444 if type_of tm = nty then (���^rep ^tm���) else reptm tyrs tm 1445 | reptm [] tm = tm 1446 1447 fun abstm ((ty,abs)::tyas) tm = 1448 if type_of tm = ty then (���^abs ^tm���) else abstm tyas tm 1449 | abstm [] tm = tm 1450 1451 fun define_fun {def_name, fname, func=tm, fixity} = 1452 let val tyl = dest_funtype(type_of tm) 1453 val tyl = eta_funtype tyl 1454 val ntyl = map absty tyl 1455 val rty = end_itlist (fn t1 => fn t2 => 1456 mk_type{Tyop="fun", Args=[t1,t2]}) ntyl 1457 1458(* 1459 val _ = print "Currently loaded quotient theorems:\n" 1460 val _ = map (print_thm o snd) tys_quot_ths 1461 val _ = print "\n" 1462 1463 val _ = print "Currently loaded quotient type extension theorems:\n" 1464 val _ = map (print_thm o snd) tyop_ty_ths 1465 val _ = print "\n" 1466*) 1467 1468(* The function findtys returns a list of the types in the term 1469 which is being lifted. 1470*) 1471 fun findtys tm = 1472 if is_abs tm then 1473 let val ty = type_of tm 1474 val {Bvar, Body} = dest_abs tm 1475 val btys = findtys Body 1476 in if is_rep_ty ty then insert ty btys else btys 1477 end 1478 else if is_comb tm then 1479 let val (opr, args) = strip_comb tm in 1480 (findtys opr) @ flatten (map findtys args) 1481 end 1482 else if is_var tm then 1483 let val {Name=nm, Ty= ty} = dest_var tm 1484 in if is_rep_ty ty then [ty] else [] 1485 end 1486 else let val {Name=nm, Ty= ty} = dest_const tm 1487 in if is_rep_ty ty then [ty] else [] 1488 end 1489 1490 fun alltys ty = 1491 if is_vartype ty then [ty] 1492 else let val {Tyop,Args} = dest_type ty 1493 val atys = alltysl Args 1494 in ty :: atys 1495 end 1496 and alltysl [] = [] 1497 | alltysl (ty::tys) = alltys ty @ alltysl tys 1498 1499 val tys = mk_set (findtys tm) 1500 val tys = mk_set (filter is_rep_ty (alltysl tys)) 1501 val _ = check_quotient_tys (tys_quot_ths @ tyop_ty_ths) tys 1502 handle HOL_ERR e => Raise (HOL_ERR e) 1503 val args = wargs (Lib.butlast ntyl) 1504 val rargs = map mkrep args 1505 val l = list_mk_comb(mk_var{Name=fname, Ty=rty}, args) 1506 val r = mkabs (list_mk_comb(tm,rargs)) 1507 val def = mk_eq{lhs=l, rhs=r} 1508 fun defname t = 1509 let val head = #1 (strip_comb (lhs (#2 (strip_forall t)))) 1510 in #Name (dest_var head handle HOL_ERR _ => dest_const head) 1511 end 1512 val nam = defname def 1513 in 1514 (* new_gen_definition(def_name, def, fixity) *) 1515 1516(* The following notes are to explain the treatment of fixities: 1517 1518structure term_grammar: 1519datatype fixity = 1520 Infix of associativity * int | Closefix | Suffix of int | Prefix of int | 1521 Binder 1522 1523structure HOLgrammars : 1524datatype associativity = LEFT | RIGHT | NONASSOC 1525*) 1526 1527 case fixity of 1528 NONE => 1529 new_definition(def_name, def) 1530 | SOME Binder => 1531 new_binder_definition(def_name, def) 1532 | SOME (term_grammar.Infix (associativity, priority)) => 1533 Definition.new_definition(def_name, def) 1534 before 1535 Parse.add_infix(nam, priority, associativity) 1536 | SOME (term_grammar.Prefix priority) => 1537 Definition.new_definition(def_name, def) 1538 before 1539 Parse.add_rule{term_name=nam, 1540 fixity=Prefix priority, 1541 pp_elements=[TOK nam], 1542 paren_style=OnlyIfNecessary, 1543 block_style=(AroundEachPhrase, 1544 (PP.CONSISTENT,0))} 1545 | SOME (term_grammar.Suffix priority) => 1546 Definition.new_definition(def_name, def) 1547 before 1548 Parse.add_rule{term_name=nam, 1549 fixity=Suffix priority, 1550 pp_elements=[TOK nam], 1551 paren_style=OnlyIfNecessary, 1552 block_style=(AroundEachPhrase, 1553 (PP.CONSISTENT,0))} 1554 | SOME term_grammar.Closefix => 1555 Definition.new_definition(def_name, def) 1556 before 1557 Parse.add_rule{term_name=nam, 1558 fixity=Closefix, 1559 pp_elements=[TOK nam], 1560 paren_style=OnlyIfNecessary, 1561 block_style=(AroundEachPhrase, 1562 (PP.CONSISTENT,0))} 1563 end 1564 1565(* An example of use: 1566 val newdefs = map define_fun fnlist 1567*) 1568 1569 in 1570 define_fun 1571 end; 1572 1573 1574fun prove_quotient_equiv_rep_one_one QUOTIENT = 1575 let 1576 (* Extract the existing type, ty, and the equivalence relation, REL. *) 1577 val unp_quot_th = (PURE_REWRITE_RULE[QUOTIENT_def]) QUOTIENT 1578 val quot_parts = ((I ## CONJ_PAIR) o CONJ_PAIR) unp_quot_th 1579 val (ABS_REP, (REP_REFL, REL_ABS)) = quot_parts 1580 val Rar = (snd o strip_comb o concl) QUOTIENT 1581 val REL = hd Rar 1582 val abs = (hd o tl) Rar 1583 val rep = (hd o tl o tl) Rar 1584 val ty = (hd o #Args o dest_type o type_of) REL 1585 val nty = (hd o #Args o dest_type o type_of) rep 1586 val pty = (==`:^ty -> ^ty -> bool`==) 1587 val _ = if type_of REL = pty then () else raise Match 1588 1589(* Prove the one-to-one and onto properties of REP and ABS. *) 1590 1591 val equiv_rep_one_one = TAC_PROOF(([], 1592 (���!a a'. (^REL (^rep a) = ^REL (^rep a')) = (a = a')���)), 1593 GEN_TAC THEN GEN_TAC 1594 THEN EQ_TAC 1595 THENL 1596 [ DISCH_THEN (MP_TAC o C AP_THM ``^rep a'``) 1597 THEN REWRITE_TAC[REP_REFL] 1598 THEN ONCE_REWRITE_TAC[REL_ABS] 1599 THEN REWRITE_TAC[REP_REFL] 1600 THEN REWRITE_TAC[ABS_REP], 1601 1602 DISCH_THEN REWRITE_THM 1603 ]) 1604 1605 in 1606 equiv_rep_one_one 1607 end; 1608 1609 1610 1611 1612(* ====================================================================== *) 1613(* The following function lifts theorems which deal with values of 1614 the original types, to similarly structured theorems dealing with 1615 values of the quotient types. 1616 1617 However, note that this function is partial, and not all theorems 1618 can be lifted by this function, even if the lifted versions are true. *) 1619(* ====================================================================== *) 1620 1621 1622fun lift_theorem_by_quotients quot_ths equivs tyop_equivs 1623 tyops tyop_simps newdefs 1624 respects polydfs polywfs = 1625 let 1626 val refls = map equiv_refl equivs 1627 val syms = map (MATCH_MP QUOTIENT_SYM) quot_ths 1628 val trans = map (MATCH_MP QUOTIENT_TRANS) quot_ths 1629 1630 val _ = reset_cache() 1631 1632(* We unpack the quotient theorems into their parts, which consist of 1633 three properties: 1634 ABS_REP: !a. abs (rep a) = a 1635 REP_REFL: !a. ?r. R r r /\ (rep a = r) 1636 ABS11: !r s. R r s = R r r /\ R s s /\ (abs r = abs s) 1637*) 1638 val unp_quot_ths = map (PURE_REWRITE_RULE[QUOTIENT_def]) quot_ths 1639 val quot_parts = map ((I ## CONJ_PAIR) o CONJ_PAIR) unp_quot_ths 1640 val (ABS_REP, (REP_REFL, ABS11)) = ((I ## unzip) o unzip) quot_parts 1641 1642(* From these parts we extract the relations RELs, abstraction functions abss, 1643 representation functions reps, lower types tys and quotient types ntys. 1644*) 1645 val Rars = map (snd o strip_comb o concl) quot_ths 1646 val RELs = map hd Rars 1647 val abss = map (hd o tl) Rars 1648 val reps = map (hd o tl o tl) Rars 1649 val tys = map (hd o #Args o dest_type o type_of) RELs 1650 val ntys = map (hd o #Args o dest_type o type_of) reps 1651 val tys_quot_ths = zip tys quot_ths; 1652 1653(* Check that for each quotient theorem in "tyops", the corresponding relation *) 1654(* and map simplification theorems are present in "tyop_simps". *) 1655 1656 fun check_simp tm = exists (fn th => (Term.match_term tm (concl th); true) 1657 handle HOL_ERR _ => false 1658 ) tyop_simps 1659 orelse 1660 Raise (HOL_ERR { 1661 origin_structure = "quotient", 1662 origin_function = "check_simp", 1663 message = 1664 "Missing quotient simplification theorem:\n" ^ 1665 with_flag (show_types, true) 1666 thm_to_string (mk_oracle_thm "quotient" ([],tm)) ^ "\n" ^ 1667 "Please prove and add to \"tyop_simps\" inputs for quotient package.\n " 1668 }) 1669 1670 fun check_tyop_simps_present tyop = 1671 let val (taus,ksis,Rs,abss,reps,conseq) = strip_QUOTIENT_cond (concl tyop) 1672 val Rar = (snd o strip_comb) conseq 1673 val REL = hd Rar 1674 val abs = hd (tl Rar) 1675 val rep = hd (tl (tl Rar)) 1676 fun strip_comb_list1 [] (tm,args) = (tm,args) 1677 | strip_comb_list1 (x::xs) (tm,args) = 1678 let val (tm',a) = Term.dest_comb tm 1679 in strip_comb_list1 xs (tm', a::args) 1680 end 1681 fun strip_comb_list lst tm = strip_comb_list1 lst (tm,[]) 1682 val (R,Rargs) = strip_comb_list taus REL 1683 val eqargs = map (fn Rarg => Term.mk_const("=", type_of Rarg)) Rargs 1684 val REL' = list_mk_comb(R,eqargs) 1685 val REL_simp = mk_eq{lhs=REL', rhs=Term.mk_const("=", type_of REL')} 1686 val _ = check_simp REL_simp 1687 val theta = map (op |->) (zip ksis taus) 1688 val (amap,aargs) = strip_comb_list taus abs 1689 val Iaargs = map (fn tau => Term.mk_const("I", tau --> tau)) taus 1690 val abs' = list_mk_comb(inst theta amap, Iaargs) 1691 val abs_simp = mk_eq{lhs=abs', rhs=Term.mk_const("I", type_of abs')} 1692 val _ = check_simp abs_simp 1693 val (rmap,rargs) = strip_comb_list taus rep 1694 val Irargs = map (fn tau => Term.mk_const("I", tau --> tau)) taus 1695 val rep' = list_mk_comb(inst theta rmap,Irargs) 1696 val rep_simp = mk_eq{lhs=rep', rhs=Term.mk_const("I", type_of rep')} 1697 val _ = check_simp rep_simp 1698 in () 1699 end 1700 1701 val _ = map check_tyop_simps_present tyops 1702 1703(* The following functions are created in relation to the given quotient 1704 theorems and type operator quotient theorems: 1705 1706 is_abs_ty : hol_type -> bool 1707 true iff the given type contains a lifted, quotient type 1708 is_rep_ty : hol_type -> bool 1709 true iff the given type contains a type being lifted 1710 absty : hol_type -> hol_type 1711 lifts the given type to the quotient level 1712 repty : hol_type -> hol_type 1713 lowers the given tupe from the quotient level 1714 get_abs : hol_type -> term 1715 returns the abstraction function for the lower type 1716 get_rep : hol_type -> term 1717 returns the representation function for the lifted type 1718 mkabs : term -> term 1719 wraps the given term with an application of the 1720 abstraction function for its type 1721 mkrep : term -> term 1722 wraps the given term with an application of the 1723 representation function for its type 1724 tyREL : hol_type -> term 1725 returns the partial equivalence relation for the type 1726*) 1727 val (is_abs_ty, is_rep_ty, absty, repty, get_abs, get_rep, 1728 mkabs, mkrep, tyREL) = 1729 form_abs_rep_functions quot_ths tyops tyop_simps; 1730 1731 1732(* Determine the constants being lifted. *) 1733 1734 fun get_deffunc newdef = 1735 let val (vs,b) = (strip_forall o concl) newdef 1736 val r = rhs b 1737 val c = if is_abs_ty (type_of r) then rand r else r 1738 in funpow (length vs) rator c 1739 end 1740 1741 val funcs = map get_deffunc newdefs 1742 val newdeffuncs = funcs 1743 1744 fun match_ty_term ob pat = 1745 let val (tmtheta,tytheta) = match_term pat ob 1746 val pat' = inst tytheta pat 1747 in if pat' = ob then (tmtheta,tytheta) 1748 else raise raise HOL_ERR { 1749 origin_structure = "quotient", 1750 origin_function = "match_ty_term", 1751 message = "not a match" 1752 } 1753 end 1754 1755(* For each constant being lifted, check that its respectfulness theorem 1756 is present. If not, then if the theorem is trivial, create it. 1757 If it is missing and not trivial, fail with an error message. 1758*) 1759 fun add_trivial_respects funcs equivs tyop_equivs = 1760 let val get_func = fst o strip_comb o rand o rator 1761 o find_base o snd o strip_forall o concl 1762 val rfuncs = map get_func respects 1763 val missing = (*subtract funcs rfuncs*) 1764 filter (fn f => not (exists (can (match_ty_term f)) rfuncs)) funcs 1765 fun check_not_rep_ty margty = if is_rep_ty margty then raise Match 1766 else () 1767 1768 fun fake_respects tm = 1769 let val ty = type_of tm 1770 val (margtys,mresty) = strip_fun ty 1771 val xargs = map (fn (n,ty) => 1772 mk_var{Name="x"^Int.toString n, Ty=ty}) 1773 (enumerate 1 margtys) 1774 val yargs = map (fn (n,ty) => 1775 mk_var{Name="y"^Int.toString n, Ty=ty}) 1776 (enumerate 1 margtys) 1777 val xyargs = zip xargs yargs 1778 val xterm = list_mk_comb(tm,xargs) 1779 val yterm = list_mk_comb(tm,yargs) 1780 val conc = list_mk_comb (tyREL (type_of xterm), [xterm,yterm]) 1781 val hyps = map (fn (x,y) => list_mk_comb (tyREL (type_of x), [x,y])) 1782 xyargs 1783 val body = if length hyps > 0 1784 then mk_imp{ant=list_mk_conj hyps,conseq=conc} 1785 else conc 1786 in 1787 List.foldr (fn ((x,y),tm) => list_mk_forall([x,y],tm)) body xyargs 1788 end 1789 1790 fun make_missing_respects mfunc = 1791 let val (margtys,mresty) = strip_fun (type_of mfunc) 1792 val _ = map check_not_rep_ty margtys 1793 val margs = map (fn (n,ty) => 1794 mk_var{Name="T"^Int.toString n, Ty=ty}) 1795 (enumerate 1 margtys) 1796 val mterm = list_mk_comb(mfunc,margs) 1797 val mrefl = equiv_refl (make_equiv equivs tyop_equivs mresty) 1798 in 1799 GENL margs (SPEC mterm mrefl) 1800 end 1801 handle e => raise HOL_ERR 1802 { origin_structure = "quotient", 1803 origin_function = "make_missing_respects", 1804 message = "Missing respectfulness theorem for " ^ 1805 term_to_string mfunc ^ ".\n" ^ 1806 with_flag (show_types, true) 1807 thm_to_string (mk_oracle_thm "quotient" ([], fake_respects mfunc)) ^ "\n" ^ 1808 "Please prove and add to \"respects\" inputs for quotient package.\n " 1809 } 1810 in 1811 map make_missing_respects missing @ respects 1812 end 1813 1814 val all_respects = add_trivial_respects funcs equivs tyop_equivs 1815 1816 1817 fun dest_funtype ty = 1818 if (mem ty tys) 1819 then [ty] 1820 else let val {Tyop=f, Args=lr} = dest_type ty 1821 val l = hd lr 1822 val r = hd (tl lr) 1823 val _ = assert(curry op = "fun") f 1824 in [l]@(dest_funtype r) 1825 end 1826 handle _ => [ty] 1827 1828 fun eta_funtype (ty1::ty2::[]) = 1829 if not (is_rep_ty ty1) andalso not (is_rep_ty ty2) 1830 then [mk_type{Tyop="fun", Args=[ty1,ty2]}] 1831 else [ty1,ty2] 1832 | eta_funtype (ty::[]) = [ty] 1833 | eta_funtype ([]) = [] 1834 | eta_funtype (ty::tys) = 1835 let val tys' = eta_funtype tys in 1836 if (length tys' < length tys) 1837 then eta_funtype(ty::tys') 1838 else ty::tys' 1839 end 1840 1841(* EQ_APs holds theorems that equality implies reflexivity for those 1842 partial equivalence relations which are reflexive. 1843 This is only true now for equivalence relations, 1844 not partial equivalence relations in general: 1845*) 1846 val EQ_APs = 1847 let fun prove_EQ_AP refl = 1848 let val R = (rator o rator o #Body o dest_forall o concl) refl 1849 in prove 1850 ((���!p q. (p = q) ==> ^R p q���), 1851 REPEAT GEN_TAC THEN DISCH_THEN SUBST1_TAC THEN 1852 MATCH_ACCEPT_TAC refl) 1853 end 1854 in map prove_EQ_AP refls 1855 end 1856 1857(* 1858 val EQ_WELLDEFs = 1859 let fun prove_EQ_WELLDEF (REL,(sym,trans)) = 1860 prove 1861 ((���!x1 x2 y1 y2. ^REL x1 x2 /\ ^REL y1 y2 ==> 1862 (^REL x1 y1 = ^REL x2 y2)���), 1863 REPEAT GEN_TAC THEN STRIP_TAC THEN EQ_TAC THENL 1864 [ ALL_TAC, POP_ASSUM (ASSUME_TAC o MATCH_MP sym) ] THEN 1865 DISCH_THEN (fn th => POP_ASSUM (MP_TAC o CONJ th)) THEN 1866 DISCH_THEN (MP_TAC o MATCH_MP trans) THENL 1867 [ POP_ASSUM (ASSUME_TAC o MATCH_MP sym), ALL_TAC ] THEN 1868 POP_ASSUM (fn th => DISCH_THEN (MP_TAC o CONJ th)) THEN 1869 DISCH_THEN (ACCEPT_TAC o MATCH_MP trans)) 1870 in 1871 map prove_EQ_WELLDEF (zip RELs (zip syms trans)) 1872 end 1873*) 1874 1875 fun UNDISCH_CONJ th = 1876 CONV_RULE (REWR_CONV (GSYM AND_IMP_INTRO)) th 1877 handle _ => 1878 UNDISCH th 1879 1880 fun UNSTRIP th = 1881 UNDISCH_CONJ th 1882 handle _ => 1883 snd (SPEC_VAR th) 1884 1885(* The RAISE_ONE_RSP rule raises the order of the given wf theorem by one, 1886 by decreasing the effective arity of the constant and by increasing 1887 the order of the relation that relates the left and right sides. 1888 Fails when order cannot be raised any further, i.e., when arity is 0. *) 1889 1890 fun RAISE_ONE_RSP th = 1891 let val (left,right) = ((rand ## I) o Psyntax.dest_comb o concl) th 1892 val lx = rand left and rx = rand right 1893 val _ = assert not (lx = rx) 1894 (* Normal case where lx and rx are different variables *) 1895 val asm = first (fn asm => rand asm = rx andalso 1896 rand (rator asm) = lx) (hyp th) 1897 val th1 = GEN lx (GEN rx (DISCH asm th)) 1898 in 1899 REWRITE_RULE[FUN_REL_EQ] 1900 (CONV_RULE (REWR_CONV (GSYM FUN_REL)) th1) 1901 end 1902 handle _ => 1903 (* We repair the special case where lx and rx are the same variable 1904 and not of a type being lifted; improper but common user error *) 1905 let val (left,right) = ((rand ## I) o Psyntax.dest_comb o concl) th 1906 val lx = rand left and rx = rand right 1907 val _ = assert (curry op = lx) rx 1908 val _ = assert (not o is_rep_ty o type_of) rx 1909 val tm = concl th and asl = hyp th 1910 val free = mk_set (free_vars tm @ flatten (map free_vars asl)) 1911 val ry = Term.variant free rx 1912 val asm = mk_eq{lhs=lx, rhs=ry} 1913 val th1 = CONV_RULE (RAND_CONV (RAND_CONV 1914 (REWR_CONV (ASSUME asm)))) th 1915 val th2 = GEN lx (GEN ry (DISCH asm th1)) 1916 in 1917 REWRITE_RULE[FUN_REL_EQ] 1918 (CONV_RULE (REWR_CONV (GSYM FUN_REL)) th2) 1919 end 1920 1921 1922(* The GEN_DISCH_ONE rule expects the top assumption of the hypothesis 1923 to be a quotient condition. It discharges the top assumption from the 1924 hypotheses of the given theorem, and generalizes the three free variables 1925 of the assumption. *) 1926 1927 fun GEN_DISCH_ONE th = 1928 let val asm = last (hyp th) 1929 val vars = snd (strip_comb asm) 1930 in 1931 GENL vars (DISCH asm th) 1932 end 1933 1934(* The prove_ho_respects rule revises the given (possibly conditional) 1935 respectfulness theorem "resp" to the highest possible order, which is 1936 the same as the lowest possible arity. For most respectfulness theorems 1937 the result will be of arity 0, i.e., the constant with no arguments, 1938 related to itself by a higher-order quotient relation. *) 1939 1940 fun prove_ho_respects resp = 1941 let val th1 = repeat UNSTRIP resp 1942 val th2 = repeat RAISE_ONE_RSP th1 1943 in 1944 repeat GEN_DISCH_ONE th2 1945 end 1946 1947 val ho_respects = map prove_ho_respects all_respects 1948 val ho_polywfs = map prove_ho_respects polywfs 1949 1950 1951(* The prove_ALL_HIGHER_DEFs function takes a definition theorem def, 1952 lowers it to the least possible order (higher possible arity), and 1953 then generates all higher order versions. All versions generated 1954 are returned, from the least to the highest order. *) 1955 1956 fun prove_ALL_HIGHER_DEFs def = 1957 let 1958 1959(* The function MAKE_LOWER_DEF converts a given definition theorem to 1960 the version of one lower order, if possible, and otherwise throws 1961 an exception. *) 1962 1963 fun MAKE_LOWER_DEF def = 1964 let val (vrs,df) = (strip_forall o concl) def 1965 val {lhs=l,rhs=r} = dest_eq df 1966 val _ = assert is_rep_ty (type_of l) 1967 val {Tyop,Args} = (dest_type o type_of) l 1968 val _ = assert (curry op = "fun") Tyop 1969 val ty1 = hd Args 1970 val ty1n = (#Tyop o dest_type) ty1 1971 handle _ => 1972 String.extract(dest_vartype ty1,1,NONE) 1973 val ty1n = if String.size ty1n > 0 then ty1n else "z" 1974 val xn = String.substring(ty1n,0,1) 1975 val asl = hyp def 1976 val free = mk_set (free_vars df @ 1977 flatten (map free_vars asl)) 1978 val x = Term.variant free (mk_var{Name=xn, Ty=ty1}) 1979 val lx = mk_comb{Rator=l, Rand=x} 1980 val rb = if is_abs_ty (type_of r) then rand r else r 1981 val rx = mkabs (mk_comb{Rator=rb, Rand=mkrep x}) 1982 val vrsx = vrs @ [x] 1983 val dfx = list_mk_forall(vrsx, mk_eq{lhs=lx, rhs=rx}) 1984 in 1985 TAC_PROOF((asl,dfx), 1986 REPEAT GEN_TAC 1987 THEN CONV_TAC (LAND_CONV (ONCE_REWRITE_CONV[def])) 1988 THEN REWRITE_TAC[FUN_MAP_THM,I_THM]) 1989 end 1990 1991(* The function MAKE_LOWEST_DEF converts a given definition theorem to 1992 the version of least possible order. *) 1993 1994 fun MAKE_LOWEST_DEF def = 1995 MAKE_LOWEST_DEF (MAKE_LOWER_DEF def) handle _ => def 1996 1997(* The function prove_HIGHER_DEF proves and returns a version of a definition 1998 theorem of the next higher order, if possible, and otherwise throws 1999 an exception. *) 2000 2001 fun prove_HIGHER_DEF def = 2002 let val (vrs,df) = (strip_forall o concl) def 2003 val {lhs=lhs1, rhs=rhs1} = dest_eq df 2004 val lhs' = (#Rator o dest_comb) lhs1 2005 val cmb = if is_abs_ty (type_of rhs1) 2006 then (#Rand o dest_comb) rhs1 2007 else rhs1 2008 val rhs' = (mkabs o #Rator o dest_comb) cmb 2009 val ndf = mk_eq{lhs=lhs', rhs=rhs'} 2010 val ndef = list_mk_forall(butlast vrs, ndf) 2011 in 2012 prove 2013 (ndef, 2014 REPEAT GEN_TAC 2015 THEN CONV_TAC FUN_EQ_CONV 2016 THEN GEN_TAC 2017 THEN TRY (CONV_TAC 2018 (RAND_CONV (RATOR_CONV (RATOR_CONV 2019 (REWR_CONV FUN_MAP) 2020 THENC BETA_CONV) 2021 THENC BETA_CONV))) 2022 THEN CONV_TAC (LAND_CONV (ONCE_REWRITE_CONV[def])) 2023 THEN REWRITE_TAC([I_THM,FUN_MAP_I] @ tyop_simps)) 2024 end 2025 2026(* The function MAKE_HIGHER_DEFS proves and returns a list of all versions 2027 of a given definition theorem of equal or higher order. *) 2028 2029 fun MAKE_HIGHER_DEFS def = 2030 def :: MAKE_HIGHER_DEFS (prove_HIGHER_DEF def) 2031 handle _ => [def] 2032 in 2033 MAKE_HIGHER_DEFS (MAKE_LOWEST_DEF def) 2034 end 2035 2036 val ADD_HIGHER_DEFS = flatten o (map prove_ALL_HIGHER_DEFs) 2037 2038 val higher_newdefs = ADD_HIGHER_DEFS newdefs 2039 2040 2041(* The function strip_type takes a type and returns a pair, consisting of 2042 a list of the types of the arguments of the function type (or [] if the 2043 type is not a function type), and the result type of the function type 2044 (or the type itself if it is not a function type). 2045*) 2046 fun strip_type ty = 2047 if is_vartype ty then ([],ty) 2048 else 2049 let val {Tyop, Args} = dest_type ty in 2050 if Tyop = "fun" then 2051 (((curry op :: (hd Args)) ## I) o strip_type o hd o tl) Args 2052 else ([],ty) 2053 end 2054 2055 fun argty n ty = 2056 if n >= 1 then 2057 let val {Tyop, Args} = dest_type ty in 2058 if not(Tyop = "fun") then raise Match 2059 else if n = 1 then hd Args 2060 else argty (n-1) (hd (tl Args)) 2061 end 2062 else raise Match 2063 2064 fun resty n ty = 2065 if n = 0 then ty 2066 else if n >= 1 then 2067 let val {Tyop, Args} = dest_type ty in 2068 if not(Tyop = "fun") then raise Match 2069 else resty (n-1) (hd (tl Args)) 2070 end 2071 else raise Match 2072 2073 fun del_imps tm = snd (strip_imp tm) 2074(* 2075 if is_imp tm then (del_imps o #conseq o dest_imp) tm 2076 else tm 2077*) 2078 2079 fun polydf_name th = 2080 let val tm = (snd o strip_forall 2081 o repeat (#conseq o dest_imp o snd o strip_forall) 2082 o concl) th 2083 val {lhs,rhs} = dest_eq tm 2084 val a1 = if is_comb lhs then (hd o snd o strip_comb) lhs 2085 else lhs 2086 fun is_a1 b = (b = a1 orelse (is_comb b andalso rand b = a1)) 2087 val tm1 = if exists is_a1 ((snd o strip_comb) rhs) 2088 then rhs 2089 else (#Rand o dest_comb) rhs 2090 handle _ => (#Rand o dest_comb) rhs 2091 in (#Name o dest_const o fst o strip_comb) tm1 2092 end 2093 2094 val poly_lifted_names = 2095 map polydf_name polydfs 2096 2097 fun poly_liftedf opp = 2098 mem (#Name (dest_const opp)) poly_lifted_names 2099 handle _ => false 2100 2101(* The function findtys returns a list of the types in the term 2102 which is being lifted. 2103*) 2104 fun findtys tm = 2105 if is_abs tm then 2106 let val ty = type_of tm 2107 val {Bvar, Body} = dest_abs tm 2108 val btys = findtys Body 2109 in if is_rep_ty ty then insert ty btys else btys 2110 end 2111 else if is_comb tm then 2112 let val (opr, args) = strip_comb tm in 2113 (findtys opr) @ flatten (map findtys args) 2114 end 2115 else if is_var tm then 2116 let val {Name=nm, Ty= ty} = dest_var tm 2117 in if is_rep_ty ty then [ty] else [] 2118 end 2119 else let val {Name=nm, Ty= ty} = dest_const tm 2120 in if is_rep_ty ty then [ty] else [] 2121 end 2122 2123 fun alltys ty = 2124 if is_vartype ty then [ty] 2125 else let val {Tyop,Args} = dest_type ty 2126 val atys = alltysl Args 2127 in ty :: atys 2128 end 2129 and alltysl [] = [] 2130 | alltysl (ty::tys) = alltys ty @ alltysl tys 2131 2132 fun findalltys tm = filter is_rep_ty (alltysl (findtys tm)) 2133 2134 2135(* The function findops returns a list of the polymorphic operators in the term 2136 which have types being lifted. 2137*) 2138 val RELnms = map (#Name o dest_const) (filter is_const RELs) 2139 fun get_tyop_REL tyop = 2140 let val (taus,ksis,Rs,abss,reps,conseq) = strip_QUOTIENT_cond (concl tyop) 2141 val Rar = (snd o strip_comb) conseq 2142 val REL = hd Rar 2143 val abs = hd (tl Rar) 2144 val rep = hd (tl (tl Rar)) 2145 fun strip_comb_list1 [] (tm,args) = (tm,args) 2146 | strip_comb_list1 (x::xs) (tm,args) = 2147 let val (tm',a) = Term.dest_comb tm 2148 in strip_comb_list1 xs (tm', a::args) 2149 end 2150 fun strip_comb_list lst tm = strip_comb_list1 lst (tm,[]) 2151 val (R,Rargs) = strip_comb_list taus REL 2152 in R 2153 end 2154 val tyop_RELs = map get_tyop_REL tyops 2155 val tyop_RELnms = map (#Name o dest_const) tyop_RELs 2156 2157 fun match_higher_th tm th = (* where th ranges over ho_polywfs *) 2158 let val (taus,ksis,Rs,abss,reps,base) = strip_QUOTIENT_cond (concl th) 2159 val opr = fst (strip_comb (rand (rator base))) 2160 in #Name(dest_const tm) = #Name (dest_const opr) 2161 end 2162 2163 fun match_higher_df tm = (* where th ranges over polydfs *) 2164 mem (#Name(dest_const tm)) poly_lifted_names 2165 2166 fun orig_const c = 2167 let val {Name,Thy,...} = dest_thy_const c 2168 in prim_mk_const{Name=Name,Thy=Thy} 2169 end 2170 2171 fun orig_type_of c = type_of (orig_const c) 2172 2173 fun mk_ksi usedtvs tau = 2174 let val used = map dest_vartype usedtvs 2175 val nm = dest_vartype tau 2176 fun new_name nm = 2177 if mem nm used then new_name (nm ^ "1") else nm 2178 in trace ("Vartype Format Complaint",0) mk_vartype (new_name nm) 2179 end 2180 2181 fun mk_ksis taus = 2182 let fun mk_ksis1 usedtvs [] = [] 2183 | mk_ksis1 usedtvs (tau::taus) = 2184 let val ksi = mk_ksi usedtvs tau 2185 in ksi :: mk_ksis1 (ksi :: usedtvs) taus 2186 end 2187 in mk_ksis1 taus taus 2188 end 2189 2190 fun base_vartype tyv = 2191 let val cs = explode (dest_vartype tyv) 2192 val _ = assert not (length cs = 0) 2193 val _ = assert (curry op = #"'") (hd cs) 2194 in implode (tl cs) 2195 end 2196 2197 fun mk_R_tm tau = mk_var {Name="R" ^ base_vartype tau, 2198 Ty= tau --> tau --> bool} 2199 2200 fun mk_abs_tm (tau,ksi) = mk_var {Name="abs" ^ base_vartype tau, 2201 Ty= tau --> ksi} 2202 2203 fun mk_rep_tm (tau,ksi) = mk_var {Name="rep" ^ base_vartype tau, 2204 Ty= ksi --> tau} 2205 2206 val quotient_tm = (fst o strip_comb o lhs o snd o strip_forall o concl) QUOTIENT_def 2207 2208 fun mk_quotient_tm (tau,ksi) = inst [alpha |-> tau, beta |-> ksi] quotient_tm 2209 2210 fun mk_quotient_phrase ((tau,ksi),(R,abs,rep)) = 2211 list_mk_comb(mk_quotient_tm(tau,ksi), [R,abs,rep]) 2212 2213 fun fake_poly_respects tm = 2214 let val otm = orig_const tm 2215 val ty = type_of otm 2216 val taus = type_vars ty 2217 val ksis = mk_ksis taus 2218 val tau_ksis = zip taus ksis 2219 val Rs = map mk_R_tm taus 2220 val abss = map mk_abs_tm tau_ksis 2221 val reps = map mk_rep_tm tau_ksis 2222 val R_abs_reps = map (fn (R,(abs,rep)) => (R,abs,rep)) (zip Rs (zip abss reps)) 2223 val quot_phrases = map mk_quotient_phrase (zip tau_ksis R_abs_reps) 2224 val hyp_quot_ths = map ASSUME quot_phrases 2225 val (is_abs_ty, is_rep_ty, absty, repty, get_abs, get_rep, 2226 mkabs, mkrep, tyREL) = 2227 form_abs_rep_functions (hyp_quot_ths @ quot_ths) tyops tyop_simps 2228 2229 (* form the base of the fake polymorphic respectfulness theorem *) 2230 val (margtys,mresty) = strip_fun ty 2231 val xargs = map (fn (n,ty) => 2232 mk_var{Name="x"^Int.toString n, Ty=ty}) 2233 (enumerate 1 margtys) 2234 val yargs = map (fn (n,ty) => 2235 mk_var{Name="y"^Int.toString n, Ty=ty}) 2236 (enumerate 1 margtys) 2237 val xyargs = zip xargs yargs 2238 val xterm = list_mk_comb(otm,xargs) 2239 val yterm = list_mk_comb(otm,yargs) 2240 val conc = list_mk_comb (tyREL (type_of xterm), [xterm,yterm]) 2241 val hyps = map (fn (x,y) => list_mk_comb (tyREL (type_of x), [x,y])) 2242 xyargs 2243 val body = if length hyps > 0 2244 then mk_imp{ant=list_mk_conj hyps,conseq=conc} 2245 else conc 2246 val base = List.foldr (fn ((x,y),tm) => list_mk_forall([x,y],tm)) body xyargs 2247 in (* Add quotient theorem hypotheses *) 2248 List.foldr (fn (((R,abs,rep),qtm),tm) => 2249 list_mk_forall([R,abs,rep], mk_imp{ant=qtm, conseq=tm})) 2250 base (zip R_abs_reps quot_phrases) 2251 end 2252 2253 fun fake_poly_preserves tm = 2254 let val otm = orig_const tm 2255 val ty = type_of otm 2256 val taus = type_vars ty 2257 val ksis = mk_ksis taus 2258 val tau_ksis = zip taus ksis 2259 val Rs = map mk_R_tm taus 2260 val abss = map mk_abs_tm tau_ksis 2261 val reps = map mk_rep_tm tau_ksis 2262 val R_abs_reps = map (fn (R,(abs,rep)) => (R,abs,rep)) (zip Rs (zip abss reps)) 2263 val quot_phrases = map mk_quotient_phrase (zip tau_ksis R_abs_reps) 2264 val hyp_quot_ths = map ASSUME quot_phrases 2265 val (is_abs_ty, is_rep_ty, absty, repty, get_abs, get_rep, 2266 mkabs, mkrep, tyREL) = 2267 form_hyp_abs_rep_functions hyp_quot_ths quot_ths tyops tyop_simps 2268 2269 (* form the base of the fake polymorphic respectfulness theorem *) 2270 val (margtys,mresty) = strip_fun ty 2271 val theta = map (op |->) tau_ksis 2272 val abs_argtys = map (type_subst theta) margtys 2273 (* map absty margtys *) 2274 val xargs = map (fn (n,ty) => mk_var{Name="x"^Int.toString n, Ty=ty}) 2275 (enumerate 1 abs_argtys) 2276 val rep_args = map (fn tm => mkrep tm handle _ => tm) xargs 2277 val repterm = list_mk_comb(otm, rep_args) 2278 val absterm = mkabs repterm 2279 val absdef = list_mk_comb(inst (map (op |->) tau_ksis) otm, xargs) 2280 val body = mk_eq{lhs=absdef, rhs=absterm} 2281 val base = list_mk_forall(xargs, body) 2282 in (* Add quotient theorem hypotheses *) 2283 List.foldr (fn (((R,abs,rep),qtm),tm) => 2284 list_mk_forall([R,abs,rep], mk_imp{ant=qtm, conseq=tm})) 2285 base (zip R_abs_reps quot_phrases) 2286 end 2287 2288 fun findops tm = 2289 if is_abs tm then (findops o #Body o dest_abs) tm 2290 else if is_comb tm then 2291 let val (opr, args) = strip_comb tm in 2292 (findops opr) @ flatten (map findops args) 2293 end 2294 else if is_var tm then [] 2295 else let val {Name=nm, Ty= ty} = dest_const tm 2296 val (atys,rty) = strip_type ty 2297 fun err1 () = HOL_ERR { 2298 origin_structure = "quotient", 2299 origin_function = "findops", 2300 message = "Missing polymorphic respectfulness theorem for `" ^ 2301 term_to_string tm ^ "`.\n" ^ 2302 with_flag (show_types, true) 2303 thm_to_string (mk_oracle_thm "quotient" ([], fake_poly_respects tm)) ^ "\n" ^ 2304 "Please prove and add to \"poly_respects\" inputs for quotient package.\n " 2305 } 2306 fun err2 () = HOL_ERR { 2307 origin_structure = "quotient", 2308 origin_function = "findops", 2309 message = "Missing polymorphic preservation theorem for `" ^ 2310 term_to_string tm ^ "`.\n" ^ 2311 with_flag (show_types, true) 2312 thm_to_string (mk_oracle_thm "quotient" ([], fake_poly_preserves tm)) ^ "\n" ^ 2313 "Please prove and add to \"poly_preserves\" inputs for quotient package.\n " 2314 } 2315 in if is_rep_ty ty 2316 then if mem (#Name(dest_const tm)) ("respects" :: RELnms @ tyop_RELnms) 2317 orelse exists (can (match_ty_term tm)) newdeffuncs 2318 then [] 2319 else if not (exists (match_higher_th tm) ho_polywfs) then raise (err1()) 2320 else if not (match_higher_df tm) then raise (err2()) 2321 else if poly_liftedf tm then [tm] else [] 2322 else [] 2323 end 2324 2325 2326(* The function findaps returns a list of the types of function variables 2327 in the term which contain types being lifted. 2328*) 2329 fun findaps tm = 2330 if is_abs tm then (findaps o #Body o dest_abs) tm 2331 else if is_comb tm then 2332 let val (opr, args) = strip_comb tm in 2333 (findaps opr) @ flatten (map findaps args) 2334 end 2335 else if is_const tm then [] 2336 else let val {Name=nm, Ty= ty} = dest_var tm 2337 val (atys,rty) = strip_type ty 2338 in if not (atys = []) andalso is_rep_ty ty 2339 then [ty] 2340 else [] 2341 end 2342 2343(* The function findabs returns a list of types of abstraction terms 2344 in the given term which contain types being lifted. 2345*) 2346 fun findabs tm = 2347 if is_abs tm then 2348 let val ty = type_of tm 2349 val tys = (findabs o #Body o dest_abs) tm 2350 in if is_rep_ty ty then ty::tys else tys 2351 end 2352 else if is_comb tm then 2353 let val {Rator=opr, Rand=arg} = dest_comb tm in 2354 (findabs opr) @ (findabs arg) 2355 end 2356 else [] 2357 2358 2359 2360(* 2361So we need a function to lift polymorphic already-defined functions 2362to operate on lifted types as well, and to deal with these functions 2363appearing in definitions of theorems being lifted: 2364 2365It should take as arguments a list of specifications of each 2366polymorphic function. The specification for one polymorphic function 2367would include 2368 2369 a. the constant, with as polymorphic a type as possible, 2370 using the type variables 'a, 'b, 'c, etc. for the polymorphic types. 2371 These indicate the relevant quotient types/theorems needed 2372 in order in the antecedents of the theorem below. 2373 2374 b. a theorem, stating 2375 2376 !Ra abs_a rep_a ... Rn abs_n rep_n. 2377 2378 (* the quotient theorem for type "a": *) 2379 (!a. abs_a(rep_a a) = a) /\ 2380 (!r r'. Ra r r' ==> (abs_a r = abs_a r')) ==> 2381 . . . 2382 (* the quotient theorem for type "n": *) 2383 (!a. abs_a(rep_a a) = a) /\ 2384 (!r r'. Ra r r' ==> (abs_a r = abs_a r')) ==> 2385 2386 (* the "definition" of the higher function *) 2387 (!x1 ... xm. F x1 ... xm = abs_r (F (rep_1 x1) ... (rep_m xm))) 2388 /\ 2389 (* the "well-formedness" or "respectfulness of the equivalences" *) 2390 (!x1 x1' ... xm xm'. 2391 R1 x1 x1' /\ ... /\ Rm xm xm' ==> 2392 Rr (F x1 ... xm) (F x1' ... xm')) 2393 2394 Here abs_1, rep_1, R1 correspond to the type of the first argument 2395 of F, ... abs_m, rep_m, Rm correspond to the type of the m-th 2396 argument of F, and abs_r, rep_r, Rr correspond to the type of the 2397 result of F. If one of these types is not lifted, then use 2398 I, I, and $= for that abs, rep, and R. 2399*) 2400 2401 2402(* QUOTIENT THEOREM CREATION AND CACHING SECTION *) 2403 2404 fun prim_get_quotient ty = 2405 tryfind (fn (rty,qth) => CAREFUL_INST_TYPE (match_type rty ty) qth) 2406 tys_quot_ths 2407 2408 val tyop_tys = map quotient_type tyops 2409 2410 val tyop_ty_ths = zip tyop_tys tyops 2411 2412 fun prim_get_tyop_quotient ty = 2413 tryfind (fn (rty,qth) => CAREFUL_INST_TYPE (match_type rty ty) qth) 2414 tyop_ty_ths 2415 2416 fun insert_cache ty qth = 2417 (quotient_cache := Map.insert(!quotient_cache, ty, qth); qth) 2418 2419(* The function get_quotient produces the quotient theorem for type ty. *) 2420 2421 fun get_quotient ty = 2422 if not (is_rep_ty ty) then identity_quotient ty 2423 else 2424 prim_get_quotient ty 2425 handle _ => 2426 let val {Tyop,Args} = dest_type ty 2427 val ths = map get_quotient Args 2428 in 2429 let val tyop = prim_get_tyop_quotient ty 2430 (* this may be one of the base quotient theorems, 2431 or one of the tyop conditional quotient ths. *) 2432 (* may need to move type vars in tyop ants to genvars, 2433 to avoid clashes with type vars in "ths" *) 2434 val tyop' = GEN_QUOT_TYVARS tyop 2435 val qth = foldl (fn (arg,qth) => MATCH_MP qth arg 2436 (**) handle _ => qth (**) ) 2437 tyop' ths 2438 in qth 2439 end 2440 handle _ => identity_quotient ty 2441 end 2442 2443(* We wrap caching around the get_quotient function. *) 2444 2445 fun get_quotient1 ty = 2446 if !caching then 2447 case Map.peek(!quotient_cache, ty) of 2448 SOME th => (hits := !hits + 1; th) 2449 | NONE => (misses := !misses + 1; 2450 insert_cache ty (get_quotient ty)) 2451 else get_quotient ty 2452 2453 val get_quotient = get_quotient1 2454 2455(* 2456 val _ = print "Currently loaded quotient theorems:\n" 2457 val _ = map (print_thm o snd) tys_quot_ths 2458 val _ = print "\n" 2459 2460 val _ = print "Currently loaded quotient type extension theorems:\n" 2461 val _ = map (print_thm o snd) tyop_ty_ths 2462 val _ = print "\n" 2463*) 2464 2465(* The function resolve_quotient, given a theorem conditioned on a quotient 2466 theorem, constructs the appropriate quotient theorem for the type present, 2467 and discharges that condition from the given theorem, returning the 2468 simplified theorem. In general, this "resolution" may need to be repeated. 2469*) 2470 fun resolve_quotient th = 2471 let val qtm = (#ant o dest_imp o snd o strip_forall o concl) th 2472 val (Q,Rar) = strip_comb qtm 2473 val _ = assert (curry op = "QUOTIENT") ((#Name o dest_const) Q) 2474 val rty = (hd o #Args o dest_type o type_of o hd o tl) Rar 2475 val qth = get_quotient rty 2476 in 2477 (MATCH_MP th) qth 2478 end 2479 2480 fun dest_QUOTIENT_imp tm = 2481 let val {ant, conseq} = dest_imp tm 2482 val (Q,_) = strip_comb ant 2483 val Qname = #Name (dest_const Q) 2484 val _ = assert (curry op = "QUOTIENT") Qname 2485 in 2486 conseq 2487 end 2488 2489(* The function get_higher_wf_base strips off all quotient conditions from 2490 the given theorem, and then regarding it as a respectfulness theorem, 2491 strips off any remaining antecedent, returning the consequent as the "base". 2492*) 2493 fun get_higher_wf_base th = 2494 let val tm1 = (concl) th 2495 val tm2 = repeat (dest_QUOTIENT_imp o snd o strip_forall) tm1 2496 val tm3 = (snd o strip_forall) tm2 2497 in #conseq(dest_imp tm3) 2498 handle _ => tm3 2499 end 2500 2501(* The function match_higher_wf matches the base of a given conditional 2502 respectfulness theorem to a goal, and then uses that match to instantiate 2503 the types of the respectfulness theorem, which is then "resolved" by 2504 "resolve_quotient" until all the conditions are gone. This resolved 2505 version of the respectfulness theorem is the result returned. 2506 This function intentionally fails if the rand of the goal does not 2507 contain a type being lifted. 2508*) 2509 fun match_higher_wf th gl = 2510 let val _ = assert is_rep_ty (type_of (rand gl)) 2511 val th' = (*GEN_QUOT_TYVARS*) th 2512 val base = get_higher_wf_base th' 2513 val types = snd (match_term base gl) 2514 val ith = CAREFUL_INST_TYPE types th' 2515 val wf = repeat resolve_quotient ith 2516 in REWRITE_RULE tyop_simps wf 2517 end 2518 2519 fun match_higher_half_wf th gl = 2520 let val th' = GEN_QUOT_TYVARS th 2521 val base = get_higher_wf_base th' 2522 val types = snd (match_term (rand base) (rand gl)) 2523 val ith = (*CAREFUL_*)INST_TYPE types th' 2524 val wf = repeat resolve_quotient ith 2525 in REWRITE_RULE tyop_simps wf 2526 end 2527 2528 2529(* The function get_higher_eq_base strips off all quotient conditions from 2530 the given theorem, and then regarding it as a preservation theorem, 2531 strips off the right hand side if it is an equality, and returns the 2532 remaining term as the "base". 2533*) 2534 fun get_higher_eq_base tm = 2535 let val tm1 = repeat (dest_QUOTIENT_imp o snd o strip_forall) tm 2536 val tm2 = (snd o strip_forall) tm1 2537 in #lhs(dest_eq tm2) 2538 handle _ => tm2 2539 end 2540 2541(* The function match_higher_eq matches the base of a given conditional 2542 preservation theorem to a goal, and then uses that match to instantiate 2543 the types of the preservation theorem, which is then "resolved" by 2544 "resolve_quotient" until all the conditions are gone. This resolved 2545 version of the preservation theorem is the result returned. 2546*) 2547 fun match_higher_eq th gl = 2548 let val th' = (*GEN_QUOT_TYVARS*) th 2549 val base = get_higher_eq_base (concl th') 2550 val types = snd (match_term base gl) 2551 val ith = CAREFUL_INST_TYPE types th' 2552 val eq = repeat resolve_quotient ith 2553 in eq 2554 end 2555 2556(* When applied to a (conditional) respectfulness theorem of the form 2557 2558 |- !R1 abs1 rep1. QUOTIENT R1 abs1 rep1 ==> ... 2559 !Rn absn repn. QUOTIENT Rn absn repn ==> 2560 !x1 y1 ... xn yn. R_i_1 x1 y1 /\ ... /\ R_i_n xn yn ==> 2561 R (C x1 ... xn) (C y1 ... yn) 2562 2563HIGHER_RSP_TAC produces a tactic that reduces a goal whose conclusion 2564is a substitution and/or type instance of R (C x1 ... xn) (C y1 ... yn) 2565to a set of n subgoals which are the corresponding instances of 2566R_i_1 x1 y1 through R_i_n xn yn, IF for that substitution/type instance the 2567corresponding quotient theorem antecedents are resolvable. 2568*) 2569 fun cname tm = #Name (dest_const (fst (strip_comb (rand (rator tm))))) 2570 2571 fun HIGHER_RSP_TAC th (asl,gl) = 2572 let val base = get_higher_wf_base th 2573 val _ = assert (curry op = (cname gl)) (cname base) 2574 (* for fast elimination of inapplicable th's *) 2575 val wf = match_higher_half_wf th gl 2576 in ((MATCH_ACCEPT_TAC wf handle _ => MATCH_MP_TAC wf) 2577 THEN REPEAT CONJ_TAC) (asl,gl) 2578 end 2579 2580(* The function get_higher_df_op takes a term which is a polymorphic operator, 2581 and a conditional preservation theorem for that operator, and attempts to 2582 instantiate the theorem according to the type of the term, and then 2583 resolve the preservation theorem by proving and discharging the quotient 2584 antecedents. The resulting simplified preservation theorem is returned. 2585 2586 In the special case where some of the quotient theorem resolvents may 2587 have been identity quotients, the result may have to be simplified by 2588 rewriting with theorems FUN_MAP_I and/or I_THM. Of course, rewriting 2589 with I_THM is not helpful if the operator being preserved is I itself. 2590*) 2591 2592 fun get_higher_df_op tm th = 2593 let val th' = (*GEN_QUOT_TYVARS*) th 2594 val tm1 = (concl) th' 2595 val tm2 = repeat (#conseq o dest_imp o snd o strip_forall) tm1 2596 val {lhs=lhs2,rhs=rhs2} = (dest_eq o snd o strip_forall) tm2 2597 val a1 = if is_comb lhs2 then (hd o snd o strip_comb) lhs2 2598 else lhs2 2599 fun is_a1 b = (b = a1 orelse (is_comb b andalso rand b = a1)) 2600 val tm3 = if exists is_a1 ((snd o strip_comb) rhs2) 2601 then rhs2 2602 else (#Rand o dest_comb) rhs2 2603 handle _ => (#Rand o dest_comb) rhs2 2604 val opr = (fst o strip_comb) tm3 2605 val types = snd (match_term opr tm) 2606 val ith = CAREFUL_INST_TYPE types th' 2607 val df = repeat resolve_quotient ith 2608 val df' = REWRITE_RULE[FUN_MAP_I] df 2609 in if #Name (dest_const opr) = "I" then df' 2610 else REWRITE_RULE (I_THM::tyop_simps) df' 2611 end 2612 2613(* The function MK_DEF_OP takes a term which is a polymorphic operator, 2614 and searches the list of polymorphic conditional preservation theorems 2615 for one corresponding to that operator. If found, the theorem is 2616 instantiated for the particular type of that term and its quotient 2617 antecedents are resolved and discharged, leaving a simplified preservation 2618 theorem which is returned. If not found, an exception is raised. 2619*) 2620 fun MK_DEF_OP tm = 2621 let val {Name=nm, Ty=ty} = dest_const tm 2622 in 2623 tryfind (get_higher_df_op tm) polydfs 2624 end 2625 handle e => raise HOL_ERR { 2626 origin_structure = "quotient", 2627 origin_function = "MK_DEF_OP", 2628 message = "Missing polymorphic preservation theorem for " ^ 2629 term_to_string tm ^ ".\n" 2630 } 2631 2632(* The tactic LAMBDA_RSP_TAC: 2633 2634 A |- (R1 ===> R2) (\x. f[x]) (\y. g[y]) 2635 ======================================= 2636 A U {R1 x' y'} |- R2 (f[x']) (g[y']) 2637 2638This tactic simplifies a goal which is a partial equivalence between 2639two abstractions into a goal where a new hypothesis is added, being 2640the R1 relation between two new variables x' and y', and the goal is 2641now the R2 relation between the bodies of the two abstractions, with 2642x' and y' substituted for their bound variables, respectively. 2643 2644The variables x' and y' are chosen to be new, but will often be the same 2645as the abstraction variables x and y, if there are no other conflicts. 2646 2647The new hypothesis R1 x' y' may be used later to prove subgoals of 2648R2 (f[x']) (g[y']). 2649*) 2650 fun LAMBDA_RSP_TAC (asl,gl) = 2651 let val {Rator=Rf, Rand=g} = dest_comb gl 2652 val {Rator=R, Rand=f} = dest_comb Rf 2653 val _ = assert is_abs f 2654 val _ = assert is_abs g 2655 val free = mk_set (free_vars f @ flatten (map free_vars asl)) 2656 val x = Term.variant free (#Bvar (dest_abs f)) 2657 val y = Term.variant (x::free) (#Bvar (dest_abs g)) 2658 val (Rop, Rargs) = strip_comb R 2659 (*val _ = assert (curry op = "===>") (#Name (dest_const Rop))*) 2660 in 2661 (CONV_TAC (REWR_CONV FUN_REL) 2662 THEN X_GEN_TAC x THEN X_GEN_TAC y THEN DISCH_TAC 2663 THEN CONV_TAC (LAND_CONV BETA_CONV 2664 THENC RAND_CONV BETA_CONV)) (asl,gl) 2665 end; 2666 2667 2668(* The following set of tactics create a facility to use respectfulness 2669 and preservation theorems which are conditioned by quotient antecedents 2670 almost as easily as if they were simple implications or equations. 2671*) 2672 2673 fun QUOT_MATCH_ACCEPT_TAC th = 2674 W(MATCH_ACCEPT_TAC o (match_higher_wf th) o snd) 2675 2676 fun QUOT_MATCH_MP_TAC th = 2677 W(MATCH_MP_TAC o (match_higher_wf th) o snd) 2678 2679 fun QUOT_REWR_CONV th = 2680 W(REWR_CONV o (match_higher_eq th)) 2681 2682 fun QUOT_REWRITE_CONV thl = 2683 EVERY_CONV (map (TOP_DEPTH_CONV o QUOT_REWR_CONV) thl) 2684 2685 fun QUOT_REWRITE_RULE thl = CONV_RULE (QUOT_REWRITE_CONV thl) 2686 2687 fun QUOT_REWRITE_TAC thl = CONV_TAC (QUOT_REWRITE_CONV thl) 2688 2689(* Here are some possible extensions to higher order rewriting, 2690 which are currently not needed: 2691 2692 fun SPEC_UNDISCH_ALL th = 2693 let val th' = UNDISCH_ALL (SPEC_ALL th) 2694 in if concl th = concl th' then th 2695 else SPEC_UNDISCH_ALL th' 2696 end 2697 2698 fun QUOT_HO_REWR_CONV th = 2699 W(Conv.HO_REWR_CONV o pthm o REWRITE_RULE[I_THM] o pthm 2700 o repeat resolve_quotient o pthm o UNDISCH_ALL 2701 o HO_PART_MATCH I (SPEC_UNDISCH_ALL th) 2702 (* o ptm "part_match " *) ) 2703 2704 fun QUOT_HO_REWRITE_CONV thl = 2705 EVERY_CONV (map (TOP_DEPTH_CONV o QUOT_HO_REWR_CONV) thl) 2706 2707 fun QUOT_HO_REWRITE_RULE thl = CONV_RULE (QUOT_HO_REWRITE_CONV thl) 2708*) 2709 2710(* The EQUALS_RSP_TAC tactic: 2711 2712 ?- R x1 x2 /\ R x2 y2 2713 ==================================== 2714 ?- R x1 y1 = R x2 y2 2715 2716 R must be the partial equivalence relation of some quotient. 2717*) 2718 2719 fun EQUALS_RSP_TAC (asl,gl) = 2720 let val tms1 = rand (rator gl) 2721 val _ = assert is_rep_ty (type_of (rand tms1)) 2722 val wf = match_higher_half_wf EQUALS_RSP gl 2723 in ((MATCH_MP_TAC wf handle _ => MATCH_ACCEPT_TAC wf) 2724 THEN REPEAT STRIP_TAC) (asl,gl) 2725 end 2726 2727(* The APPLY_RSP_TAC tactic: 2728 2729 ?- (R1 ===> R2) f g /\ R1 x y 2730 ==================================== 2731 ?- R2 (f x) (g y) 2732 2733 The type of f must contain a type being lifted. Furthermore, 2734 f must be of the form (v a1 ... an) with 0 <= n, where v is a variable. 2735 2736 This is intended to apply where the "head"s of f and g are variables, 2737 not constants. In this case the two variables should be related in the 2738 assumption list. 2739*) 2740 2741 fun APPLY_RSP_TAC (asl,gl) = 2742 let val tms1 = rand (rator gl) 2743 val opp = rator tms1 2744 val _ = assert is_rep_ty (type_of opp) 2745 val wf = match_higher_half_wf APPLY_RSP gl 2746 in ((MATCH_MP_TAC wf handle _ => MATCH_ACCEPT_TAC wf) 2747 THEN REPEAT STRIP_TAC) (asl,gl) 2748 end 2749 2750(* The ABSTRACT_RES_ABSTRACT_TAC tactic implements two complimentary rules 2751 for dealing with RES_ABSTRACT: 2752 2753 ?- (R1 ===> R2) f g 2754 ================================================= 2755 ?- (R1 ===> R2) (RES_ABSTRACT (respects R1) f) g 2756 2757 ?- (R1 ===> R2) f g 2758 ================================================= 2759 ?- (R1 ===> R2) f (RES_ABSTRACT (respects R1) g) 2760 2761 This will get rid of the RES_ABSTRACT on either the left or right, 2762 and when repeated on both, so that the other tactics can apply to 2763 the (perhaps) abstractions f and g. 2764*) 2765 val ABSTRACT_RES_ABSTRACT_TAC = 2766 QUOT_MATCH_MP_TAC ABSTRACT_RES_ABSTRACT ORELSE 2767 QUOT_MATCH_MP_TAC RES_ABSTRACT_ABSTRACT 2768 2769 val ABS_REP_RSP_TAC : tactic = 2770 QUOT_MATCH_MP_TAC REP_ABS_RSP 2771 2772 2773(* The LAMBDA_PRS function creates a preservation theorem for an abstraction. 2774 It takes a function type fty = ty1 -> ty2 and returns a theorem of the form 2775 2776 !f. (\x. f x) = (rep1 --> abs2) (\x. rep2 (f (abs1 x))) 2777 2778 for the appropriate abs and rep functions for ty1 and ty2. 2779*) 2780 fun LAMBDA_PRS fty = 2781 let val {Tyop=nm, Args=args} = dest_type fty 2782 val _ = assert (curry op = "fun") nm 2783 val aty = hd args 2784 val bty = hd (tl args) 2785 val cldf = CAREFUL_INST_TYPE[alpha |-> aty, beta |-> bty] 2786 quotientTheory.LAMBDA_PRS 2787 val ldf = repeat resolve_quotient cldf 2788 val ldf' = PURE_REWRITE_RULE[I_THM] ldf 2789 in 2790 ldf' (* (\x. f x) = ^(\x. v(f ^x)) *) 2791 end; 2792 2793 2794(* The APPLIC_PRS function creates a preservation theorem for an application. 2795 It takes a function type fty = ty1 -> ty2 and returns a theorem of the form 2796 2797 !f. f x = abs2 ((abs1 --> rep2) f (rep1 x)) 2798 2799 for the appropriate abs and rep functions for ty1 and ty2. 2800*) 2801 fun APPLIC_PRS fty = 2802 let val tyl = dest_funtype fty 2803 val tyl = eta_funtype tyl 2804 val ntyl = map absty tyl 2805 val rty = end_itlist (fn t1 => fn t2 => 2806 mk_type{Tyop="fun", Args=[t1,t2]}) ntyl 2807 val args = wargs (Lib.butlast ntyl) 2808 val rargs = map mkrep args 2809 val f = mk_var{Name="f", Ty=absty fty} 2810 val l = list_mk_comb(mk_var{Name="f", Ty=rty}, args) 2811 val r = mkabs (list_mk_comb(mkrep f,rargs)) 2812 val def = mk_eq{lhs=l, rhs=r} 2813 val gl = list_mk_forall(f::args, def) 2814 in 2815 (* (f x) = ^(v(f) v(x)) *) 2816 prove (gl, 2817 REPEAT GEN_TAC 2818 THEN REWRITE_TAC[FUN_MAP,FUN_MAP_I,(*SET_MAP_def,*)I_THM,PAIR_MAP] 2819 THEN REPEAT (CHANGED_TAC 2820 (CONV_TAC (DEPTH_CONV BETA_CONV) 2821 THEN REWRITE_TAC[])) 2822 THEN QUOT_REWRITE_TAC[QUOTIENT_ABS_REP] 2823 THEN REWRITE_TAC [ETA_AX] 2824 ) 2825 end; 2826 2827 fun MATCH_MP0_TAC th = (MATCH_MP_TAC th 2828 handle _ => MATCH_ACCEPT_TAC th) 2829 2830 2831(* ------------------------------------------------------------------------- *) 2832(* *) 2833(* R_MK_COMB_TAC tactic: *) 2834(* *) 2835(* The R_MK_COMB_TAC tactic is key to the correct processing of theorems *) 2836(* being lifted up according to the equivalence relations. It repeatedly *) 2837(* breaks down a goal to be proved into subgoals, and then analyzes each *) 2838(* subgoal, until all are resolved. Each goal must be of the form *) 2839(* *) 2840(* RELATION term1 term2 *) 2841(* *) 2842(* where term1 and term2 are terms in the HOL OL of some type, say 'a, *) 2843(* and where RELATION is a partial equivalence relation relating values *) 2844(* of 'a. *) 2845(* If 'a is not a type being lifted, then RELATION will be normal equality. *) 2846(* *) 2847(* Currently R_MK_COMB_TAC consists of 12 tactics, tried in order until *) 2848(* one works. The order of these tactics is very important. For some *) 2849(* goals, several of the tactics may apply, but they should be tried in *) 2850(* order until the first one is found that works. *) 2851(* *) 2852(* This tactic is called from two places: the most important of these is *) 2853(* the call from TRANSFORM_CONV, which proves the expansion of the given, *) 2854(* lower version of the theorem into a version with "rep o abs" "oil" *) 2855(* injected between operator results and their uses. This oil will be used *) 2856(* in the collapse of the lower operators into their higher versions in *) 2857(* subsequent rewriting. This is part of the actual lifting of the theorem. *) 2858(* *) 2859(* The other place which calls this tactic is from REGULARIZE_TAC, where *) 2860(* this is used to solve subgoals of the form RELATION term1 term2. *) 2861(* To work in this context, the tactic ABSTRACT_RES_ABSTRACT_TAC is present, *) 2862(* which would not be needed otherwise. This is part of the attempt to *) 2863(* reshape the given theorem into a regular form which can be lifted, which *) 2864(* may or may not succeed. *) 2865(* *) 2866(* We now list the 12 Individual tactics of R_MK_COMB_TAC: *) 2867(* *) 2868(* *) 2869(* 1. W(C (curry op THEN) (GEN_TAC THEN CONV_TAC *) 2870(* (RAND_CONV BETA_CONV THENC LAND_CONV BETA_CONV)) o *) 2871(* CONV_TAC o X_FUN_EQ_CONV o #Bvar o dest_abs o lhs o snd) *) 2872(* *) 2873(* This takes a goal of the form (\x. F(x)) = (\y. G(y)) *) 2874(* and transforms it into the form F(x) = G(x). I'll represent this as *) 2875(* *) 2876(* ?- F(x) = G(x) *) 2877(* =========================== *) 2878(* ?- (\x. F(x)) = (\y. G(y)) *) 2879(* *) 2880(* The free variable "x" in the new goal is taken from the bound variable *) 2881(* in the left-hand-side of the original goal. This obviously only works *) 2882(* if the type of the function (\x. F(x)) is not a type being lifted. *) 2883(* *) 2884(* *) 2885(* 2. ABSTRACT_RES_ABSTRACT_TAC *) 2886(* *) 2887(* This implements two complimentary rules for dealing with RES_ABSTRACT: *) 2888(* *) 2889(* ?- (R1 ===> R2) f g *) 2890(* ================================================= *) 2891(* ?- (R1 ===> R2) (RES_ABSTRACT (respects R1) f) g *) 2892(* *) 2893(* ?- (R1 ===> R2) f g *) 2894(* ================================================= *) 2895(* ?- (R1 ===> R2) f (RES_ABSTRACT (respects R1) g) *) 2896(* *) 2897(* This will get rid of the RES_ABSTRACT on either the left or right, *) 2898(* and when repeated on both, so that the other tactics can apply to *) 2899(* the (perhaps) abstractions f and g. *) 2900(* *) 2901(* *) 2902(* 3. LAMBDA_RES_TAC *) 2903(* *) 2904(* A U {R1 x y} ?- R2 (F(x)) (G(y)) *) 2905(* ========================================= *) 2906(* A ?- (R1 ===> R2) (\x. F(x)) (\y. G(y)) *) 2907(* *) 2908(* The free variable "x" is chosen to be not in the free variables of *) 2909(* (\x. F(x)), and "y" is chosen to be not "x" or free in (\y. G(y)). *) 2910(* If possible, they are chosed to be a close as possible to the bound *) 2911(* variables. *) 2912(* *) 2913(* The new assumption R1 x y is propogated for possible use later in *) 2914(* solving subgoals of R2 (F(x)) (G(y)), where it may well be necessary *) 2915(* to know that R1 x y. This use of the assumption is accomplished by *) 2916(* FIRST_ASSUM MATCH_ACCEPT_TAC mentioned below. *) 2917(* *) 2918(* *) 2919(* 4. EQUALS_RSP_TAC *) 2920(* *) 2921(* ?- R x1 x2 /\ R x2 y2 *) 2922(* ==================================== *) 2923(* ?- R x1 y1 = R x2 y2 *) 2924(* *) 2925(* R must be the partial equivalence relation of some quotient. *) 2926(* *) 2927(* *) 2928(* 5. FIRST (map HIGHER_RSP_TAC ho_polywfs) *) 2929(* *) 2930(* This tries the given generic constant respectfulness theorems until *) 2931(* one fits (if any). Then the goal is replaced by the corresponding *) 2932(* antecedents, as by MATCH_MP_TAC. The LET constant is a good example: *) 2933(* *) 2934(* ?- (R1 ===> R2) f g /\ R1 x y *) 2935(* ================================== *) 2936(* ?- R2 (LET f x) (LET g y) *) 2937(* *) 2938(* The respectfulness theorems in ho_polywfs will have been converted to *) 2939(* the highest order possible, e.g., for the LET respectfulness theorem, *) 2940(* *) 2941(* ================================== *) 2942(* ?- ((R1 ===> R2) ===> R1 ===> R2) LET LET *) 2943(* *) 2944(* *) 2945(* 6. FIRST(map MATCH_ACCEPT_TAC ho_respects) *) 2946(* *) 2947(* The "ho_respects" are the respectfulness theorems generated for *) 2948(* all newly defined functions, converted to the highest order, such as: *) 2949(* *) 2950(* |- ($= ===> ALPHA) Con1 Con1 *) 2951(* |- ($= ===> ALPHA) Var1 Var1 *) 2952(* |- ($= ===> $= ===> LIST_REL ($= ### ALPHA)) $// $// *) 2953(* |- (ALPHA ===> ALPHA ===> ALPHA) App1 App1 *) 2954(* |- ($= ===> ALPHA ===> ALPHA) Lam1 Lam1 *) 2955(* |- (($= ===> ALPHA) ===> ALPHA) Abs1 Abs1 *) 2956(* |- (ALPHA ===> $=) HEIGHT1 HEIGHT1 *) 2957(* |- (ALPHA ===> $=) FV1 FV1 *) 2958(* |- (LIST_REL ($= ### ALPHA) ===> $= ===> ALPHA) SUB1 SUB1 *) 2959(* |- (LIST_REL ($= ### ALPHA) ===> $=) FV_subst1 FV_subst1 *) 2960(* |- (ALPHA ===> LIST_REL ($= ### ALPHA) ===> ALPHA) $<[ $<[ *) 2961(* |- ($= ===> LIST_REL ($= ### ALPHA) ===> LIST_REL ($= ### ALPHA) *) 2962(* ===> $=) ALPHA_subst ALPHA_subst *) 2963(* *) 2964(* *) 2965(* 7. ABS_REP_RSP_TAC *) 2966(* *) 2967(* ?- R f g *) 2968(* ======================================================= *) 2969(* ?- R f (rep (abs g) *) 2970(* *) 2971(* *) 2972(* 9. APPLY_RSP_TAC *) 2973(* *) 2974(* ?- (R1 ===> R2) f g /\ R1 x y *) 2975(* ==================================== *) 2976(* ?- R2 (f x) (g y) *) 2977(* *) 2978(* The type of f must contain a type being lifted. Furthermore, *) 2979(* f must be of the form (v a1 ... an) with 0 <= n, where v is a variable. *) 2980(* *) 2981(* This is intended to apply where the "head"s of f and g are variables *) 2982(* or constants. In the variables case, the two variables should be related *) 2983(* in the assumption list. *) 2984(* *) 2985(* *) 2986(* 9. REFL_TAC *) 2987(* *) 2988(* ==================================== *) 2989(* ?- x = x *) 2990(* *) 2991(* 10. MK_COMB_TAC *) 2992(* *) 2993(* ?- (f = g) /\ (x = y) *) 2994(* ==================================== *) 2995(* ?- f x = g y *) 2996(* *) 2997(* *) 2998(* 11. FIRST_ASSUM MATCH_ACCEPT_TAC *) 2999(* *) 3000(* Finds the first assumption which matches the goal (if any). *) 3001(* *) 3002(* *) 3003(* ==================== *) 3004(* A ?- A *) 3005(* *) 3006(* This makes use of the assumptions created by the tactic LAMBDA_RES_TAC *) 3007(* mentioned above. *) 3008(* *) 3009(* *) 3010(* 12. FIRST (map MATCH_MP_TAC EQ_APs) (* for REGULARIZE later *) *) 3011(* *) 3012(* Reduces equivalence relations to equality relations. An equality always *) 3013(* implies equivalence, but not the reverse; so these may not be the right *) 3014(* thing to do. Nevertheless, sometimes it is easier to prove the equality. *) 3015(* Note that this ONLY works for relations which are full equivalence *) 3016(* relations; partial equivalence relations are not in general reflexive. *) 3017(* *) 3018(* [|- !p q. (p = q) ==> ALPHA p q, *) 3019(* |- !p q. (p = q) ==> ($= ### ALPHA) p q, *) 3020(* |- !p q. (p = q) ==> LIST_REL ($= ### ALPHA) p q, *) 3021(* |- !p q. (p = q) ==> (ALPHA +++ LIST_REL ($= ### ALPHA)) p q] *) 3022(* *) 3023(* *) 3024(* ------------------------------------------------------------------------- *) 3025 3026 val R_MK_COMB_TAC = FIRST 3027 [W(C (curry op THEN) (GEN_TAC THEN CONV_TAC 3028 (RAND_CONV BETA_CONV THENC LAND_CONV BETA_CONV)) o 3029 CONV_TAC o X_FUN_EQ_CONV o #Bvar o dest_abs o lhs o snd) 3030 , 3031 ABSTRACT_RES_ABSTRACT_TAC, (* slow to die? *) 3032 LAMBDA_RSP_TAC, 3033 EQUALS_RSP_TAC, 3034 FIRST (map HIGHER_RSP_TAC ho_polywfs) (* slow *) 3035 , 3036 FIRST (map MATCH_ACCEPT_TAC ho_respects), 3037 ABS_REP_RSP_TAC, (* before MATCH_MP_RSP_TAC APPLY_RSP *) 3038 APPLY_RSP_TAC (* after MATCH_ACCEPT_TAC ho_respects, 3039 before MK_COMB_TAC *) (* slow *) 3040 , 3041 REFL_TAC, 3042 MK_COMB_TAC 3043 , 3044 FIRST_ASSUM MATCH_ACCEPT_TAC 3045 , 3046 FIRST (map MATCH_MP_TAC EQ_APs) (* for REGULARIZE later *) 3047 ] 3048 3049(* For testing purposes: *) 3050(* REPEAT R_MK_COMB_TAC *) 3051 3052 fun prim_liftedf opp = 3053 exists (fn func => (match_term func opp; true) handle _ => false) 3054 funcs 3055 3056 fun liftedf opp = 3057 prim_liftedf opp orelse poly_liftedf opp 3058 3059(* ------------------------------------------------------------------------- *) 3060(* The transconv function takes a term which is a statement to be lifted, *) 3061(* and "inflates" the term by injecting "rep (abs _)" oil around every *) 3062(* operator that yields a value being lifted. *) 3063(* *) 3064(* The particular abs and rep functions used depend, of course, on the *) 3065(* particular type of the value returned by the operator. *) 3066(* *) 3067(* The new term is not necessarily equal to the old one; this equality is *) 3068(* proven by the conversion TRANSCONV, using transconv and R_MK_COMB_TAC. *) 3069(* ------------------------------------------------------------------------- *) 3070 3071 fun transconv tm = 3072 if is_abs tm then 3073 let val {Bvar=v, Body=t} = dest_abs tm 3074 val vty = type_of v 3075 val t' = mk_abs{Bvar=v, Body=transconv t} 3076 in 3077 if not (is_rep_ty (type_of tm)) then t' 3078 else 3079 mkrep(mkabs( 3080 if not (is_rep_ty vty) then t' 3081 else 3082 let val v' = mkrep(mkabs(v)) 3083 val t1 = beta_conv (mk_comb{Rator=t', Rand=v'}) 3084 in 3085 mk_abs{Bvar=v, Body=t1} 3086 end)) 3087 end 3088 else 3089 let val (opp,tms0) = strip_comb tm 3090 val tms = map transconv tms0 3091 val ty = type_of tm 3092 in 3093 if (((#Name o dest_const) opp = "respects") handle _ => false) 3094 then list_mk_comb(opp, (hd tms0)::(tl tms)) 3095 else if (liftedf opp andalso is_rep_ty ty) then 3096 mkrep(mkabs(list_mk_comb(opp,tms))) 3097 else if (is_var opp andalso length tms > 0 3098 andalso is_rep_ty ty) then 3099 mkrep(mkabs(list_mk_comb(opp,tms))) 3100 else if tms = [] then opp 3101 else list_mk_comb(opp, tms) 3102 end 3103 3104(* ------------------------------------------------------------------------- *) 3105(* The TRANSCONV conversion takes a term which is a statement to be lifted, *) 3106(* "inflates" the term by injecting "rep (abs _)" oil around every operator *) 3107(* that yields a value being lifted, and proves that the original term is *) 3108(* equal to the inflated term, using transconv and R_MK_COMB_TAC. *) 3109(* ------------------------------------------------------------------------- *) 3110 3111 fun TRANSFORM_CONV tm = 3112 let 3113 val teq = mk_eq{lhs=tm, rhs=transconv tm} 3114 val th = TAC_PROOF (([],teq), REPEAT R_MK_COMB_TAC) 3115 in 3116 th 3117 end 3118 handle _ => 3119 raise HOL_ERR { 3120 origin_structure = "quotient", 3121 origin_function = "TRANSFORM_CONV", 3122 message = "Could not convert to higher types the term\n" ^ 3123 term_to_string tm ^ "\n" ^ 3124 "May be missing a respects or a poly_respects theorem" 3125 ^ " for some constant in it." 3126 } 3127 3128 3129(* ------------------------------------------------------------------------- *) 3130(* The regularize function takes a term which is a statement to be lifted, *) 3131(* and converts it to a similar term which is "regular", as defined in the *) 3132(* documentation for the quotient package. *) 3133(* *) 3134(* Instances of equality between two types being lifted are converted to *) 3135(* instances of the appropriate partial equivalence relation. *) 3136(* Instances of universal and existstential quantification for types being *) 3137(* lifted are converted to "RES_FORALL R" or "RES_EXISTS R" for the *) 3138(* appropriate partial equivalence relation R. *) 3139(* Several other more specialized conversions are performed as well. *) 3140(* *) 3141(* That the original theorem implies the regularized version is proved *) 3142(* by the REGULARIZE function, using regularize and REGULARIZE_TAC. *) 3143(* ------------------------------------------------------------------------- *) 3144 3145 val domain = fst o dom_rng 3146 3147 fun regularize tm = 3148 let val ty = type_of tm 3149 val regularize_abs = (pairLib.mk_pabs o (I ## regularize) 3150 o pairLib.dest_pabs) 3151 in 3152 (* abstraction *) 3153 if is_abs tm then 3154 let val tm1 = regularize_abs tm 3155 val dom = domain ty 3156 in 3157 if is_rep_ty dom then 3158 (���RES_ABSTRACT (respects (^(tyREL dom))) ^tm1���) 3159 handle _ => tm1 3160 else tm1 3161 end 3162 (* respects(R): *) 3163 else if (#Name (dest_const (rator tm)) = "respects") 3164 handle _ => false 3165 then tm 3166 (* combination *) 3167 else if is_comb tm orelse is_const tm then 3168 let val (opp,args) = strip_comb tm 3169 in 3170 if is_const opp andalso is_rep_ty (type_of opp) then 3171 let val name = #Name (dest_const opp) in 3172 if name = "=" then 3173 list_mk_comb(tyREL (type_of (hd args)), map regularize args) 3174 else if mem name ["!","?","?!"] then 3175 let val ty1 = (domain o type_of) opp 3176 val tm1 = hd args 3177 val tm1r = regularize_abs tm1 3178 val dom = (fst o dom_rng) ty1 3179 val domREL = tyREL dom 3180 val res = (���respects(^domREL)���) 3181 in 3182 if name = "!" then 3183 (���RES_FORALL ^res ^tm1r���) 3184 else if name = "?" then 3185 (���RES_EXISTS ^res ^tm1r���) 3186 else if name = "?!" then 3187 (���RES_EXISTS_EQUIV ^domREL ^tm1r���) 3188 else 3189 list_mk_comb(opp, map regularize args) 3190 end 3191 handle _ => list_mk_comb(opp, map regularize args) 3192 else if mem name ["SUBSET","PSUBSET"] then 3193 let val ty1 = (domain o domain o type_of) opp 3194 val elemREL = tyREL ty1 3195 in 3196 if name = "SUBSET" then 3197 list_mk_comb(���SUBSETR ^elemREL���, map regularize args) 3198 else if name = "PSUBSET" then 3199 list_mk_comb(���PSUBSETR ^elemREL���, map regularize args) 3200 else 3201 list_mk_comb(opp, map regularize args) 3202 end 3203 handle _ => list_mk_comb(opp, map regularize args) 3204 else if mem name ["INSERT"] then 3205 let val ty1 = (domain o type_of) opp 3206 val elemREL = tyREL ty1 3207 in 3208 list_mk_comb(���INSERTR ^elemREL���, map regularize args) 3209 end 3210 handle _ => list_mk_comb(opp, map regularize args) 3211 else if mem name ["DELETE","DISJOINT"] then 3212 let val ty1 = (domain o domain o type_of) opp 3213 val elemREL = tyREL ty1 3214 in 3215 if name = "DELETE" then 3216 list_mk_comb(���DELETER ^elemREL���, map regularize args) 3217 else if name = "DISJOINT" then 3218 list_mk_comb(���DISJOINTR ^elemREL���, map regularize args) 3219 else 3220 list_mk_comb(opp, map regularize args) 3221 end 3222 handle _ => list_mk_comb(opp, map regularize args) 3223 else if mem name ["FINITE"] then 3224 let val ty1 = (domain o domain o type_of) opp 3225 val elemREL = tyREL ty1 3226 in 3227 list_mk_comb(���FINITER ^elemREL���, map regularize args) 3228 end 3229 handle _ => list_mk_comb(opp, map regularize args) 3230 else if mem name ["GSPEC"] then 3231 let val ty1 = (domain o type_of) opp 3232 val (dom,rng) = dom_rng ty1 3233 val tya = hd (#Args (dest_type rng)) 3234 val bREL = tyREL tya 3235 val aREL = tyREL dom 3236 in 3237 list_mk_comb(���GSPECR ^aREL ^bREL���, map regularize args) 3238 end 3239 handle _ => list_mk_comb(opp, map regularize args) 3240 else if mem name ["IMAGE"] then 3241 let val ty1 = (domain o type_of) opp 3242 val (dom,rng) = dom_rng ty1 3243 val domREL = tyREL dom 3244 val rngREL = tyREL rng 3245 in 3246 if name = "IMAGE" then 3247 list_mk_comb(���IMAGER ^domREL ^rngREL���, map regularize args) 3248 else 3249 list_mk_comb(opp, map regularize args) 3250 end 3251 handle _ => list_mk_comb(opp, map regularize args) 3252 else if mem name ["RES_FORALL","RES_EXISTS", 3253 "RES_EXISTS_UNIQUE","RES_ABSTRACT"] then 3254 if is_comb (hd args) andalso 3255 is_const ((rator o hd) args) andalso 3256 not (name = "RES_EXISTS_UNIQUE") andalso 3257 ((#Name o dest_const o rator o hd) args) = "respects" 3258 then 3259 list_mk_comb(opp, [hd args, 3260 regularize_abs (hd (tl args)) ]) 3261 else 3262 let val restr = hd args 3263 val ropp = (#Name o dest_const o fst o strip_comb) 3264 restr 3265 val tm1 = hd (tl args) 3266 val tm1r = regularize_abs tm1 3267 val ty1 = type_of tm1 3268 val dom = (fst o dom_rng) ty1 3269 val res = if ropp = "respects" then restr else 3270 (���\z. respects(^(tyREL dom)) z /\ ^restr z���) 3271 in 3272 if name = "RES_FORALL" then 3273 (���RES_FORALL ^res ^tm1r���) 3274 else if name = "RES_EXISTS" then 3275 (���RES_EXISTS ^res ^tm1r���) 3276 else if name = "RES_EXISTS_UNIQUE" then 3277 (���RES_EXISTS_EQUIV ^(tyREL dom) ^tm1r���) 3278 else if name = "RES_ABSTRACT" then 3279 (���RES_ABSTRACT ^res ^tm1r���) 3280 else 3281 list_mk_comb(opp, map regularize args) 3282 end 3283 handle _ => list_mk_comb(opp, map regularize args) 3284 else if mem name ["RES_EXISTS_EQUIV"] then 3285 list_mk_comb(opp, [hd args, 3286 regularize_abs (hd (tl args)) ]) 3287 handle _ => list_mk_comb(opp, map regularize args) 3288 else 3289 list_mk_comb(opp, map regularize args) 3290 end 3291 else 3292 list_mk_comb(opp, map regularize args) 3293 end 3294 (* var *) 3295 else 3296 tm 3297 end 3298 3299 3300 local 3301 val erfs = map (MATCH_MP EQUIV_RES_FORALL) equivs 3302 val eres = map (MATCH_MP EQUIV_RES_EXISTS) equivs 3303 val ereus = map (MATCH_MP EQUIV_RES_EXISTS_UNIQUE) equivs 3304 in 3305 val er_rws = erfs @ eres @ ereus 3306 end 3307 3308 3309 fun MATCH_EQUIV_TAC equiv = 3310 MATCH_MP_TAC (MATCH_MP EQUALS_EQUIV_IMPLIES equiv) 3311 THEN CONJ_TAC 3312 THEN REPEAT R_MK_COMB_TAC 3313 THEN NO_TAC 3314 3315 3316(* ------------------------------------------------------------------------- *) 3317(* The REGULARIZE_TAC tactic attempts to prove the equality of a term with *) 3318(* its "regularized" version. Similar to R_MK_COMB_TAC, it consists of a *) 3319(* list of 18 tactics which are tried successively and repeatedly to find *) 3320(* the first one that succeeds. Unlike R_MK_COMB_TAC, success is not always *) 3321(* expected. *) 3322(* *) 3323(* The first seven tactics deal with various versions of quantification. *) 3324(* *) 3325(* This tactic is used by the REGULARIZE function to prove the regularized *) 3326(* version of a given theorem. *) 3327(* ------------------------------------------------------------------------- *) 3328 3329 val REGULARIZE_TAC = FIRST 3330 [ 3331 W(curry op THEN 3332 (FIRST (map MATCH_MP_TAC 3333 [FORALL_REGULAR,EXISTS_REGULAR])) o 3334 X_GEN_TAC o #Bvar o dest_abs o rand o rand o rator o snd), 3335 3336 W(curry op THEN 3337 (FIRST (map MATCH_MP_TAC 3338 [RES_FORALL_REGULAR,RES_EXISTS_REGULAR])) o 3339 X_GEN_TAC o #Bvar o dest_abs o rand o rand o rator o snd) 3340 THEN DISCH_THEN (ASSUME_TAC o REWRITE_RULE[RESPECTS]), 3341 3342 W(curry op THEN 3343 (MATCH_MP_TAC LEFT_RES_FORALL_REGULAR) o 3344 X_GEN_TAC o #Bvar o dest_abs o rand o rand o rator o snd) 3345 THEN CONJ_TAC 3346 THENL [ REWRITE_TAC[RESPECTS] 3347 THEN REPEAT GEN_TAC 3348 THEN ASM_REWRITE_TAC[] 3349 THEN FIRST (map MATCH_MP_TAC EQ_APs) 3350 THEN ASM_REWRITE_TAC[] 3351 THEN NO_TAC, 3352 3353 CONV_TAC (LAND_CONV BETA_CONV) 3354 THEN CONV_TAC (RAND_CONV BETA_CONV) 3355 ], 3356 3357 W(curry op THEN 3358 (MATCH_MP_TAC RIGHT_RES_FORALL_REGULAR) o 3359 X_GEN_TAC o #Bvar o dest_abs o rand o rand o rator o snd) 3360 THEN DISCH_THEN (ASSUME_TAC o CONV_RULE (REWR_CONV RESPECTS)), 3361 3362 W(curry op THEN 3363 (MATCH_MP_TAC LEFT_RES_EXISTS_REGULAR) o 3364 X_GEN_TAC o #Bvar o dest_abs o rand o rand o rator o snd) 3365 THEN DISCH_THEN (ASSUME_TAC o CONV_RULE (REWR_CONV RESPECTS)), 3366 3367 W(curry op THEN 3368 (MATCH_MP_TAC RIGHT_RES_EXISTS_REGULAR) o 3369 X_GEN_TAC o #Bvar o dest_abs o rand o rand o rator o snd) 3370 THEN CONJ_TAC 3371 THENL [ REWRITE_TAC[RESPECTS] 3372 THEN REPEAT GEN_TAC 3373 THEN ASM_REWRITE_TAC[] 3374 THEN FIRST (map MATCH_MP_TAC EQ_APs) 3375 THEN ASM_REWRITE_TAC[] 3376 THEN NO_TAC, 3377 3378 CONV_TAC (LAND_CONV BETA_CONV) 3379 THEN CONV_TAC (RAND_CONV BETA_CONV) 3380 ], 3381 3382 MATCH_MP_TAC RES_EXISTS_UNIQUE_REGULAR_SAME 3383 THEN REWRITE_TAC (map GSYM er_rws) 3384 THEN REPEAT R_MK_COMB_TAC, 3385 3386 CONV_TAC (RAND_CONV BETA_CONV THENC LAND_CONV BETA_CONV), 3387 3388 DISCH_THEN REWRITE_THM THEN REPEAT R_MK_COMB_TAC THEN NO_TAC, 3389 3390 FIRST (map MATCH_ACCEPT_TAC EQ_APs), 3391 3392 FIRST (map MATCH_MP_TAC 3393 [EQUALS_IMPLIES,CONJ_IMPLIES,DISJ_IMPLIES,IMP_IMPLIES, 3394 NOT_IMPLIES]) 3395 THEN REPEAT CONJ_TAC, 3396 3397 MATCH_ACCEPT_TAC EQ_IMPLIES, 3398 3399 FIRST (map MATCH_EQUIV_TAC equivs), 3400 3401 W(C (curry op THEN) (GEN_TAC THEN CONV_TAC 3402 (RAND_CONV BETA_CONV THENC LAND_CONV BETA_CONV)) o 3403 CONV_TAC o X_FUN_EQ_CONV o #Bvar o dest_abs o lhs o snd) 3404 , 3405 CONV_TAC FUN_EQ_CONV THEN GEN_TAC, 3406 REFL_TAC, 3407 EQ_TAC, 3408 MK_COMB_TAC 3409 ] 3410 3411 3412(* ------------------------------------------------------------------------- *) 3413(* The REGULARIZE_RULE function attempts to prove the regularized version of *) 3414(* a given theorem. It does this by calling "regularize" to generate the *) 3415(* regularized version of the theorem's conclusion, and then by using *) 3416(* REGULARIZE_TAC to prove that the regular version is implied by the *) 3417(* original version. *) 3418(* ------------------------------------------------------------------------- *) 3419 3420 fun REGULARIZE_RULE th = 3421 let val tm = concl th 3422 val tm' = regularize tm 3423 in 3424 if tm = tm' then th 3425 else 3426 (* REGULARIZE th *) 3427 let 3428 val rmp = mk_imp{ant=tm, conseq=tm'} 3429 val rth = prove(rmp, REWRITE_TAC er_rws 3430 THEN REPEAT REGULARIZE_TAC) 3431 in 3432 MP rth th 3433 end 3434 handle _ => raise HOL_ERR { 3435 origin_structure = "quotient", 3436 origin_function = "REGULARIZE", 3437 message = "Could not lift the irregular theorem\n" ^ 3438 thm_to_string th ^ "\n" ^ 3439 "May try proving and then lifting\n" ^ 3440 term_to_string tm' 3441 } 3442 end 3443 3444 3445(* ------------------------------------------------------------------------- *) 3446(* The check_high function verifies if the given term is completely formed *) 3447(* of quotient-level constants and types, without any remaining elements *) 3448(* from the lower, representational level. Such elements might persist if *) 3449(* for some reason the preservation theorem for some constant in the theorem *) 3450(* being lifted was not available to be used in the lifting process. *) 3451(* ------------------------------------------------------------------------- *) 3452 3453 fun check_high tm = 3454 (if is_comb tm andalso is_const (rator tm) 3455 andalso #Name (dest_const (rator tm)) = "respects" 3456 then () 3457 else if is_abs tm then check_high (#Body (dest_abs tm)) 3458 else if is_comb tm then 3459 let val (opp,args) = strip_comb tm 3460 val _ = map check_high args 3461 (* val _ = check_high opp *) 3462 in () end 3463 else (); 3464 if is_rep_ty (type_of tm) then 3465 raise HOL_ERR { 3466 origin_structure = "quotient", 3467 origin_function = "check_high", 3468 message = "Could not lift the term " ^ 3469 term_to_string tm ^ "\n" ^ 3470 "May be missing a constant to be lifted, " ^ 3471 "or a poly_preserves theorem." 3472 } 3473 else () 3474 ) 3475 3476 fun CHECK_HIGH th = (check_high (concl th); th) 3477 3478 3479(* ------------------------------------------------------------------------- *) 3480(* In HOL4, version Kananaskis-3, it was discovered that higher order *) 3481(* rewriting was damaged from before. Previously a rewrite of the form *) 3482(* (\x. F x) = (\x. G x) would maintain the bound variable name. *) 3483(* But the current version does not, changing the \x. to a gensym variable. *) 3484(* *) 3485(* REPAIRED_HO_PURE_REWRITE_RULE repairs this, and keeps the original *) 3486(* variable name. *) 3487(* ------------------------------------------------------------------------- *) 3488(* 3489 fun RENAME_ABS_CONV name tm = 3490 let val ty = (#Ty o dest_var o #Bvar o dest_abs) tm 3491 val x = mk_var{Name=name, Ty=ty} 3492 in ALPHA_CONV x tm 3493 end 3494 3495 fun HO_PURE_REWRITE_CONV ths tm = 3496 (CHANGED_CONV (Ho_Rewrite.GEN_REWRITE_CONV I ths) THENC 3497 (if is_abs (rand tm) then 3498 let val name = (#Name o dest_var o #Bvar o dest_abs o rand) tm 3499 in 3500 RENAME_ABS_CONV name 3501 end 3502 else ALL_CONV)) tm 3503 3504 val REPAIRED_HO_PURE_REWRITE_RULE = 3505 CONV_RULE o TOP_DEPTH_CONV o HO_PURE_REWRITE_CONV 3506*) 3507(* 3508 fun HO_REWR_CONV th tm = 3509 (Ho_Rewrite.GEN_REWRITE_CONV TOP_DEPTH_CONV ths THENC 3510 (if is_abs (rand tm) then 3511 let val name = (#Name o dest_var o #Bvar o dest_abs o rand) tm 3512 in 3513 RENAME_ABS_CONV name 3514 end 3515 else ALL_CONV)) tm 3516 3517 fun HO_PURE_REWRITE_CONV1 ths tm = 3518 (Ho_Rewrite.GEN_REWRITE_CONV TOP_DEPTH_CONV ths THENC 3519 (if is_abs (rand tm) then 3520 let val name = (#Name o dest_var o #Bvar o dest_abs o rand) tm 3521 in 3522 RENAME_ABS_CONV name 3523 end 3524 else ALL_CONV)) tm 3525 3526 val REPAIRED_HO_PURE_REWRITE_RULE1 = 3527 CONV_RULE o HO_PURE_REWRITE_CONV1 3528*) 3529 3530 3531(* ------------------------------------------------------------------------- *) 3532(* Here we define LIFT_RULE, which is the function that lifts theorems from *) 3533(* the original, lower level to the higher, quotient level. *) 3534(* *) 3535(* LIFT_RULE has several phases: *) 3536(* 1. Preliminary cleaning by GEN_ALL and tyop_simps; *) 3537(* 2. Conversion to regularized form by REGULARIZE_RULE; *) 3538(* 3. Check that all types within the theorem are supported by the *) 3539(* available quotient type extension theorems, and that all *) 3540(* operators within the theorem are supported by the available *) 3541(* respectfulness and preservation theorems. *) 3542(* 4. Extraction of the operators, abstractions, and applications *) 3543(* contained within the theorem to be lifted; *) 3544(* 5. Creation of the preservation theorems for the operators, *) 3545(* abstractions, and applications; *) 3546(* 6. Transformation of the regular theorem to its "inflated" form; *) 3547(* ( This is the phase with the highest failure rate. ) *) 3548(* 7. Conversion of R (rep x) (rep y) to (x = y); *) 3549(* 8. Rewriting by all preservation theorems to collapse inflated forms; *) 3550(* 9. Checking that the result has no remaining lower-level terms. *) 3551(* *) 3552(* If anything fails, LIFT_RULE wraps the exception with an error message *) 3553(* containing the actual original theorem which was given to be lifted. *) 3554(* ------------------------------------------------------------------------- *) 3555 3556 val LIFT_RULE = 3557 (fn th => let val thr = (REGULARIZE_RULE o 3558 REWRITE_RULE (FUN_REL_EQ :: tyop_simps) 3559 o GEN_ALL) th 3560 val tm = concl thr 3561 val tys = mk_set (findalltys tm) 3562 val _ = check_quotient_tys (tys_quot_ths @ tyop_ty_ths) tys 3563 val ops = mk_set (findops tm) 3564 val abs = mk_set (findabs tm) 3565 val aps = mk_set (findaps tm) 3566 val DEF_OPs = ADD_HIGHER_DEFS (map MK_DEF_OP ops) 3567 val DEF_LAMs = map LAMBDA_PRS abs 3568 val DEF_APPs = ADD_HIGHER_DEFS (map APPLIC_PRS aps) 3569 val LAM_APP_DEFS = map GSYM (DEF_LAMs @ DEF_APPs) 3570 val DEFs = DEF_OPs @ higher_newdefs 3571 in 3572 (CHECK_HIGH o 3573 PURE_REWRITE_RULE (map GSYM DEFs) o 3574 Ho_Rewrite.PURE_REWRITE_RULE LAM_APP_DEFS o 3575 QUOT_REWRITE_RULE [GSYM EQUALS_PRS] o 3576 CONV_RULE TRANSFORM_CONV) thr 3577 handle e => raise HOL_ERR { 3578 origin_structure = "quotient", 3579 origin_function = "LIFT_RULE", 3580 message = "Could not lift the theorem\n" ^ 3581 thm_to_string th ^ "\n" ^ 3582 exn_to_string e 3583 } 3584 end) 3585 3586 in 3587 3588 LIFT_RULE 3589 end; 3590(* end of lift_theorem_by_quotients *) 3591 3592 3593 3594(* --------------------------------------------------------------- *) 3595(* Check to see if a purported respectfulness theorem is actually *) 3596(* of the right form. *) 3597(* --------------------------------------------------------------- *) 3598 3599fun check_respects_tm tm = 3600 let val (vrs,body) = strip_forall tm 3601 val (ants, base) = if is_imp body then 3602 let val {ant, conseq} = Rsyntax.dest_imp body 3603 in (strip_conj ant, conseq) end 3604 else ([],body) 3605 val ant_args = map (fn ant => (rand (rator ant), rand ant)) ants 3606 val _ = assert distinct (uncurry append (unzip ant_args)) 3607 val ((Rc,t1),t2) = ((Psyntax.dest_comb ## I) o Psyntax.dest_comb) base 3608 val (c1,args1) = strip_comb t1 3609 val (c2,args2) = strip_comb t2 3610 val _ = assert (curry op = c1) c2 3611 val _ = assert distinct args1 3612 val _ = assert distinct args2 3613 val argpairs = zip args1 args2 3614 fun check_arg (a12 as (a1,a2)) = 3615 ((mem a12 ant_args andalso mem a1 vrs andalso mem a2 vrs 3616 orelse (a1 = a2)) 3617 andalso type_of a1 = type_of a2) 3618 fun check_ant (ant12 as (ant1,ant2)) = 3619 (mem ant12 argpairs 3620 andalso mem ant1 vrs andalso mem ant2 vrs 3621 andalso type_of ant1 = type_of ant2) 3622 fun check_var vr = mem vr args1 orelse mem vr args2 3623 in 3624 all check_arg argpairs andalso all check_ant ant_args 3625 andalso all check_var vrs 3626 orelse raise Match 3627 end; 3628 3629fun check_respects th = 3630 Term.free_vars (concl th) = [] andalso 3631 check_respects_tm (concl th) 3632 handle e => raise HOL_ERR { 3633 origin_structure = "quotient", 3634 origin_function = "check_respects", 3635 message = "The following theorem is not of the right form for a respectfulness theorem:\n" ^ 3636 thm_to_string th ^ "\n" 3637 }; 3638 3639 3640(* --------------------------------------------------------------- *) 3641(* Check to see if a purported polymorphic respectfulness theorem *) 3642(* is actually of the right form. *) 3643(* --------------------------------------------------------------- *) 3644 3645fun check_poly_respects th = 3646 let val (taus, ksis, Rs, abss, reps, uncond_tm) = 3647 strip_QUOTIENT_cond (concl th) 3648 val _ = assert (all is_vartype) (append taus ksis) 3649 val _ = assert distinct (append taus ksis) 3650 val _ = assert distinct (append (append Rs abss) reps) 3651 in 3652 Term.free_vars (concl th) = [] andalso 3653 check_respects_tm uncond_tm 3654 end 3655 handle e => raise HOL_ERR { 3656 origin_structure = "quotient", 3657 origin_function = "check_poly_respects", 3658 message = "The following theorem is not of the right form for a polymorphic respectfulness\ntheorem:\n" ^ 3659 thm_to_string th ^ "\n" 3660 }; 3661 3662local 3663 fun any_type_var_in tyl ty = exists (C type_var_in ty) tyl 3664 fun un_abs_rep tyl tm = if any_type_var_in tyl (type_of tm) 3665 then rand tm else tm 3666 fun check_strip_comb [] tm = (tm,[]) 3667 | check_strip_comb (x::xs) tm = 3668 let val (tm', y) = Psyntax.dest_comb tm 3669 val (c,ys) = check_strip_comb xs tm' 3670 in (c, y::ys) end 3671 fun dest_psv_rhs args tm = 3672 let val (c, ys) = check_strip_comb (rev args) tm 3673 in (c, rev ys) end 3674 3675in 3676fun check_poly_preserves th = 3677 let val (taus, ksis, Rs, abss, reps, uncond_tm) = 3678 strip_QUOTIENT_cond (concl th) 3679 val _ = assert (all is_vartype) (append taus ksis) 3680 val _ = assert distinct (append taus ksis) 3681 val _ = assert distinct (append (append Rs abss) reps) 3682 val (vrs,body) = strip_forall uncond_tm 3683 val (tm1,tm2) = Psyntax.dest_eq body 3684 val (c1,args1) = strip_comb tm1 3685 (* Next line is for ABSTRACT_PRS, but not for APPLY_PRS: *) 3686 val args1' = if is_var c1 then c1::args1 else args1 3687 val _ = assert (all (C mem args1')) vrs 3688 val _ = assert (all (C mem vrs)) args1' 3689 val tm2' = un_abs_rep ksis tm2 3690 val (c2,args2) = dest_psv_rhs args1' tm2' 3691 val tysubst = map (op |->) (zip taus ksis) 3692 val _ = assert (curry op = (type_of tm1)) 3693 (type_subst tysubst (type_of tm2')) 3694 val args2' = map (un_abs_rep taus) args2 3695 val _ = assert (all (op =)) (zip args1' args2') 3696 val _ = assert (all (op =)) 3697 (zip (map type_of args1') 3698 (map (type_subst tysubst o type_of) args2)) 3699 in 3700 true 3701 end 3702 handle e => raise HOL_ERR { 3703 origin_structure = "quotient", 3704 origin_function = "check_poly_preserves", 3705 message = "The following theorem is not of the right form for a polymorphic preservation\ntheorem:\n" ^ 3706 thm_to_string th ^ "\n" 3707 } 3708end; 3709 3710 3711 3712 3713(* --------------------------------------------------------------- *) 3714(* Returns a list of types present in the "respects" theorems but *) 3715(* not directly mentioned in the "quot_ths" list, but for which *) 3716(* quotient theorems can be built from the existing ones. *) 3717(* --------------------------------------------------------------- *) 3718 3719fun enrich_types quot_ths tyops respects = 3720 (* qtys holds the base types of the new quotients formed. *) 3721 let val qtys = map (hd o #Args o dest_type o type_of o hd o tl 3722 o snd o strip_comb o concl) quot_ths 3723 fun resp_ty rth = 3724 let val body = (snd o strip_forall o concl) rth 3725 val base = (#conseq o dest_imp) body handle _ => body 3726 in (#Ty o dest_const o fst o strip_comb o #Rand o dest_comb) base 3727 end 3728 (* test checks there is a substitution theta s.t. ty2 theta = ty1: *) 3729 fun test ty1 ty2 = (match_type ty2 ty1; true) handle _ => false 3730 fun tintersect [] tys2 = [] 3731 | tintersect (ty::tys) tys2 = 3732 if exists (test ty) tys2 then ty::tintersect tys tys2 3733 else tintersect tys tys2 3734 fun tsubtract [] tys2 = [] 3735 | tsubtract (ty::tys) tys2 = 3736 if exists (test ty) tys2 then tsubtract tys tys2 3737 else ty::tsubtract tys tys2 3738 3739 (* being_lifted ty is true iff ty contains a subtype being lifted *) 3740 fun being_lifted ty = not (null (tintersect (sub_tys ty) qtys)) 3741 3742 (* atys holds the types of arguments and results of the operators 3743 described in the "respects" theorems. 3744 These are used as suggestions for types of new quotient theorems 3745 that may be frequently needed in the later phase of lifting old 3746 theorems to the quotient level. *) 3747 val atys = mk_set (flatten (map (fun_tys o resp_ty) respects)) 3748 3749 (* ltys holds those types from atys which contain a type being lifted *) 3750 val ltys = filter being_lifted atys 3751 3752 (* natys holds those types from ltys which are new, not in qtys *) 3753 val natys = tsubtract ltys qtys 3754 3755 (* nstys holds all subtypes of the types in natys which contain a type 3756 being lifted *) 3757 val nstys = filter being_lifted (flatten (map sub_tys natys)) 3758 3759 (* ntys holds all types from nstys which are new, not in qtys *) 3760 val ntys = mk_set (tsubtract nstys qtys) 3761 3762(* val quot_ths' = quot_ths @ map (make_quotient quot_ths tyops) ntys *) 3763 in 3764 ntys 3765 end; 3766 3767 3768 3769 3770(* ------------------------ *) 3771(* ALTERNATIVE ENTRY POINT. *) 3772(* ------------------------ *) 3773 3774fun define_quotient_types_rule {types, defs, 3775 tyop_equivs, tyop_quotients, tyop_simps, 3776 respects, poly_preserves, poly_respects} = 3777 let 3778 val equivs = map (PURE_REWRITE_RULE (map GSYM [EQUIV_def,PARTIAL_EQUIV_def]) 3779 o #equiv) types 3780 val _ = map check_equiv equivs 3781 val _ = map check_tyop_equiv tyop_equivs 3782 val _ = map check_tyop_quotient tyop_quotients 3783 val _ = map check_tyop_simp tyop_simps 3784 3785 val equivs = filter is_equiv equivs 3786 val all_equivs = equivs @ tyop_equivs 3787 3788 fun print_thm' th = if !chatting then (print_thm th; print "\n"; th) 3789 else th 3790 val quotients = map (fn {name, equiv} => 3791 define_quotient_type name (name^"_ABS") (name^"_REP") equiv) 3792 types 3793 val _ = if !chatting then print "Quotients:\n" else () 3794 val _ = if !chatting then map print_thm' quotients else [] 3795 3796 val fn_defns = 3797 map (define_quotient_lifted_function 3798 quotients tyop_quotients tyop_simps) defs 3799 val _ = if !chatting then print "\nDefinitions:\n" else () 3800 val _ = if !chatting then map print_thm' fn_defns else [] 3801 3802 val _ = map check_respects respects 3803 val _ = map check_poly_preserves poly_preserves 3804 val _ = map check_poly_respects poly_respects 3805 3806 val ntys = enrich_types quotients tyop_quotients respects 3807 val nequivs = map (make_equiv equivs tyop_equivs) ntys 3808 fun is_ident_equiv th = 3809 (curry op = "=" o #Name o dest_const o rand o concl 3810 o PURE_REWRITE_RULE[GSYM EQUIV_def]) th 3811 handle _ => false 3812 val pequivs = equivs @ filter (not o is_ident_equiv) nequivs 3813 fun is_ident_quot th = 3814 (curry op = "=" o #Name o dest_const o rand o rator o rator o concl) th 3815 handle _ => false 3816 val quotients = 3817 quotients @ filter (not o is_ident_quot) (map (make_quotient quotients tyop_quotients) ntys) 3818 3819 val LIFT_RULE = 3820 lift_theorem_by_quotients quotients pequivs tyop_equivs 3821 tyop_quotients tyop_simps fn_defns 3822 respects poly_preserves poly_respects 3823 handle e => Raise e 3824 in 3825 LIFT_RULE 3826 end; 3827 3828 3829 3830(* ----------------- *) 3831(* MAIN ENTRY POINT. *) 3832(* ----------------- *) 3833 3834fun define_quotient_types {types, defs, tyop_equivs, tyop_quotients,tyop_simps, 3835 respects, poly_preserves, poly_respects, old_thms} = 3836 let fun print_thm' th = if !chatting then (print_thm th; print "\n"; th) 3837 else th 3838 3839 val LIFT_RULE = 3840 define_quotient_types_rule 3841 {types=types, 3842 defs=defs, 3843 tyop_equivs=tyop_equivs, 3844 tyop_quotients=tyop_quotients, 3845 tyop_simps=tyop_simps, 3846 respects=respects, 3847 poly_preserves=poly_preserves, poly_respects=poly_respects} 3848 3849 val _ = if !chatting then print "\nLifted theorems:\n" else () 3850 val new_thms = map (print_thm' o LIFT_RULE) 3851 old_thms handle e => Raise e 3852 in 3853 new_thms 3854 end; 3855 3856 3857fun define_quotient_types_full_rule {types, defs, tyop_equivs, tyop_quotients, 3858 tyop_simps, respects, poly_preserves, poly_respects} = 3859 let 3860 val tyop_equivs = tyop_equivs @ 3861 [LIST_EQUIV, PAIR_EQUIV, SUM_EQUIV, OPTION_EQUIV] 3862 val tyop_quotients = tyop_quotients @ 3863 [LIST_QUOTIENT, PAIR_QUOTIENT, 3864 SUM_QUOTIENT, OPTION_QUOTIENT, FUN_QUOTIENT] 3865 val tyop_simps = tyop_simps @ 3866 [LIST_MAP_I, LIST_REL_EQ, PAIR_MAP_I, PAIR_REL_EQ, 3867 SUM_MAP_I, SUM_REL_EQ, OPTION_MAP_I, OPTION_REL_EQ, 3868 FUN_MAP_I, FUN_REL_EQ] 3869 val poly_preserves = poly_preserves @ 3870 [CONS_PRS, NIL_PRS, MAP_PRS, LENGTH_PRS, APPEND_PRS, 3871 FLAT_PRS, REVERSE_PRS, FILTER_PRS, NULL_PRS, 3872 SOME_EL_PRS, ALL_EL_PRS, FOLDL_PRS, FOLDR_PRS, 3873 FST_PRS, SND_PRS, COMMA_PRS, CURRY_PRS, 3874 UNCURRY_PRS, PAIR_MAP_PRS, 3875 INL_PRS, INR_PRS, ISL_PRS, ISR_PRS, SUM_MAP_PRS, 3876 NONE_PRS, SOME_PRS, IS_SOME_PRS, IS_NONE_PRS, 3877 OPTION_MAP_PRS, 3878 FORALL_PRS, EXISTS_PRS, 3879 EXISTS_UNIQUE_PRS, ABSTRACT_PRS, 3880 COND_PRS, LET_PRS, literal_case_PRS, 3881 I_PRS, K_PRS, o_PRS, C_PRS, W_PRS] 3882 val poly_respects = poly_respects @ 3883 [CONS_RSP, NIL_RSP, MAP_RSP, LENGTH_RSP, APPEND_RSP, 3884 FLAT_RSP, REVERSE_RSP, FILTER_RSP, NULL_RSP, 3885 SOME_EL_RSP, ALL_EL_RSP, FOLDL_RSP, FOLDR_RSP, 3886 FST_RSP, SND_RSP, COMMA_RSP, CURRY_RSP, 3887 UNCURRY_RSP, PAIR_MAP_RSP, 3888 INL_RSP, INR_RSP, ISL_RSP, ISR_RSP, SUM_MAP_RSP, 3889 NONE_RSP, SOME_RSP, IS_SOME_RSP, IS_NONE_RSP, 3890 OPTION_MAP_RSP, 3891 RES_FORALL_RSP, RES_EXISTS_RSP, 3892 RES_EXISTS_EQUIV_RSP, RES_ABSTRACT_RSP, 3893 COND_RSP, LET_RSP, literal_case_RSP, 3894 I_RSP, K_RSP, o_RSP, C_RSP, W_RSP] 3895(* ?? EQUALS, LAMBDA, RES_FORALL, RES_EXISTS, APPLY ?? *) 3896 in 3897 define_quotient_types_rule 3898 {types=types, defs=defs, 3899 tyop_equivs=tyop_equivs, tyop_quotients=tyop_quotients, 3900 tyop_simps=tyop_simps, 3901 respects=respects, 3902 poly_preserves=poly_preserves, poly_respects=poly_respects} 3903 end; 3904 3905 3906 3907fun define_quotient_types_full {types, defs, tyop_equivs, tyop_quotients, 3908 tyop_simps, respects, poly_preserves, poly_respects, old_thms} = 3909 let fun print_thm' th = if !chatting then (print_thm th; print "\n"; th) 3910 else th 3911 3912 val LIFT_RULE = 3913 define_quotient_types_full_rule 3914 {types=types, defs=defs, 3915 tyop_equivs=tyop_equivs, tyop_quotients=tyop_quotients, 3916 tyop_simps=tyop_simps, 3917 respects=respects, 3918 poly_preserves=poly_preserves, poly_respects=poly_respects} 3919 3920 val _ = if !chatting then print "\nLifted theorems:\n" else () 3921 val new_thms = map (print_thm' o LIFT_RULE) 3922 old_thms handle e => Raise e 3923 in 3924 new_thms 3925 end; 3926 3927 3928fun define_quotient_types_std_rule {types, defs, respects} = 3929 define_quotient_types_full_rule 3930 {types=types, defs=defs, 3931 tyop_equivs=[], tyop_quotients=[], 3932 tyop_simps=[], 3933 respects=respects, 3934 poly_preserves=[], poly_respects=[]}; 3935 3936 3937 3938fun define_quotient_types_std {types, defs, respects, old_thms} = 3939 define_quotient_types_full 3940 {types=types, defs=defs, 3941 tyop_equivs=[], tyop_quotients=[], 3942 tyop_simps=[], 3943 respects=respects, 3944 poly_preserves=[], poly_respects=[], 3945 old_thms=old_thms}; 3946 3947 3948 3949fun define_equivalence_type {name, equiv, defs, welldefs, old_thms} = 3950 define_quotient_types {types=[{name=name, equiv=equiv}], 3951 defs=defs, 3952 tyop_equivs=[], 3953 tyop_quotients=[FUN_QUOTIENT], 3954 tyop_simps=[FUN_REL_EQ,FUN_MAP_I], 3955 respects=welldefs, 3956 poly_preserves=[FORALL_PRS,EXISTS_PRS], 3957 poly_respects=[RES_FORALL_RSP,RES_EXISTS_RSP], 3958 old_thms=old_thms}; 3959 3960(* Subset types: *) 3961 3962(* expects inhab = |- ?x. P[x] *) 3963 3964fun is_ho_match_term tm1 tm2 = 3965 (ho_match_term [] Term.empty_tmset tm1 tm2; true) handle _ => false; 3966 3967val inhab_tm = 3968 ���?(x:'a). P x���; 3969 3970fun is_inhab th = is_ho_match_term inhab_tm (concl th); 3971 3972fun check_inhab th = 3973 is_inhab th orelse 3974 raise HOL_ERR { 3975 origin_structure = "quotient", 3976 origin_function = "check_inhab", 3977 message = "The following is not a predicate inhabitation theorem:\n" ^ 3978 thm_to_string th ^ "\n" 3979 } 3980 3981fun dest_con_inhab c = 3982 let open Psyntax 3983 val (vs,body) = strip_forall c 3984 val (ant,conseq) = if is_imp body andalso not (is_neg body) 3985 then dest_imp body else (T,body) 3986 val ants = if ant=T then [] else strip_conj ant 3987 in 3988 (vs, ants, conseq) 3989 end 3990 3991fun check_con_inhab th = 3992 let val (vs, ants, conseq) = dest_con_inhab (concl th) 3993 val _ = assert (all is_var) vs 3994 val _ = assert distinct vs 3995 val _ = assert distinct ants 3996 in 3997 Term.free_vars (concl th) = [] orelse raise Match 3998 end 3999 handle e => raise HOL_ERR { 4000 origin_structure = "quotient", 4001 origin_function = "check_con_inhab", 4002 message = "The following does not have the form of a constant inhabitation theorem:\n" ^ 4003 thm_to_string th ^ "\n" 4004 } 4005 4006 4007fun tryconv f (x:'a) = f x handle HOL_ERR _ => x 4008 4009(* 4010val name = "vect0"; 4011val inhab = TAC_PROOF (([],``?x:bool list. ~(x = [])``), 4012 EXISTS_TAC ``[T]`` THEN REWRITE_TAC[listTheory.NOT_CONS_NIL]); 4013*) 4014 4015fun define_subset_reln {name:string, inhab:thm} = 4016 let open Psyntax bossLib 4017 val _ = check_inhab inhab 4018 val P = tryconv eta_conv (snd (dest_comb (concl inhab))) 4019 val ty = fst (dom_rng (type_of P)) (* P : ty -> bool *) 4020 val fvs = free_vars P 4021 val x = variant fvs (mk_var("x",ty)) 4022 val y = variant (x::fvs) (mk_var("y",ty)) 4023 val Px = tryconv beta_conv (mk_comb(P,x)) 4024 val Py = tryconv beta_conv (mk_comb(P,y)) 4025 val eq = mk_eq(x,y) 4026 val Rbody = list_mk_conj[Px,Py,eq] 4027 val Rabs = list_mk_abs([x,y], Rbody) 4028 val Rname = name ^ "_R" 4029 val Rvar = mk_var(Rname, ty --> ty --> bool) 4030 val Rargs = list_mk_comb(Rvar,fvs) 4031 val Rdef = new_definition (Rname^"_def", mk_eq(Rargs,Rabs)) 4032 val Rexp = lhs (concl Rdef) 4033 val Rcon = fst (strip_comb Rexp) 4034 val Rdef = TAC_PROOF (([], ``^Rexp ^x ^y = ^Rbody``), 4035 REWRITE_TAC [Rdef] 4036 THEN BETA_TAC 4037 THEN REFL_TAC) 4038 val PEQUIV_R = TAC_PROOF (([], ``PARTIAL_EQUIV ^Rexp``), 4039 REWRITE_TAC [quotientTheory.PARTIAL_EQUIV_def,FUN_EQ_THM] 4040 THEN CONJ_TAC 4041 THENL 4042 [ SIMP_TAC bool_ss [Rdef,inhab], 4043 4044 REPEAT GEN_TAC 4045 THEN EQ_TAC 4046 THENL 4047 [ SIMP_TAC bool_ss [Rdef], 4048 4049 STRIP_TAC 4050 THEN POP_ASSUM (fn th => REWRITE_TAC[th]) 4051 THEN POP_ASSUM (fn th => REWRITE_TAC[th]) 4052 ] 4053 ]) 4054 in 4055 (Rdef, {name=name, equiv=PEQUIV_R}) 4056 end; 4057 4058fun dest_Rdef Rdef = 4059 let open Psyntax 4060 val (qvrs,body) = strip_forall (concl Rdef) 4061 val (al,ar) = dest_eq body 4062 val (Rcon,vars) = strip_comb al 4063 val x = hd vars 4064 val y = hd(tl vars) 4065 val _ = assert null (tl(tl vars)) 4066 val (Px,(Py,eqtm)) = ((I ## dest_conj) o dest_conj) ar 4067 val P = mk_abs(x,Px) 4068 val _ = assert (aconv (tryconv eta_conv P)) (tryconv eta_conv (mk_abs(y,Py))) 4069 in 4070 (P,Rcon) 4071 end 4072 4073fun variants avoids [] = [] 4074 | variants avoids (v::vs) = 4075 let val v' = variant avoids v 4076 in v' :: variants (v'::avoids) vs 4077 end 4078 4079fun LIST_MK_COMB_TAC g = 4080 TRY (MK_COMB_TAC THENL [LIST_MK_COMB_TAC, ALL_TAC]) g 4081 4082fun prove_subset_respects Rdefs = 4083 let open Psyntax 4084 val Rdefs2 = map GSYM Rdefs 4085 val PRs = map dest_Rdef Rdefs 4086 val (Ps,Rcons) = unzip PRs 4087 fun find_R [] tm = 4088 raise HOL_ERR { 4089 origin_structure = "quotient", 4090 origin_function = "prove_subset_respects", 4091 message = "Term does not match expected predicates: " ^ 4092 term_to_string tm 4093 } 4094 | find_R ((P,R)::rest) tm = 4095 let val (x,body) = dest_abs P 4096 val (tmS,tyS) = match_term body tm 4097 in (inst tyS R, subst tmS (inst tyS x)) 4098 end handle HOL_ERR _ => (* if it doesn't match *) 4099 find_R rest tm 4100 in 4101 fn th => 4102 let val c = concl th 4103 val (vs, ants, conseq) = dest_con_inhab c 4104 val vs' = variants vs vs 4105 val (REL,Parg) = find_R PRs conseq 4106 val (copr,cargs) = strip_comb Parg 4107 val theta = map op |-> (zip vs vs') 4108 val conseq2 = list_mk_comb(REL,[Parg,subst theta Parg]) 4109 fun mk_ant2 ant = 4110 let val (Rant,Parg) = find_R PRs ant 4111 in list_mk_comb(Rant,[Parg,subst theta Parg]) 4112 end 4113 val ants2 = map mk_ant2 ants 4114 val body2 = if null ants then conseq2 4115 else mk_imp (list_mk_conj ants2, conseq2) 4116 val c2 = list_mk_forall(vs @ vs', body2) 4117 in 4118 TAC_PROOF(([],c2), 4119 REPEAT GEN_TAC 4120 THEN PURE_REWRITE_TAC Rdefs 4121 THEN TRY (DISCH_TAC THEN POP_ASSUM MP_TAC THEN STRIP_TAC) 4122 THEN CONJ_TAC 4123 THENL 4124 [ MATCH_ACCEPT_TAC th 4125 ORELSE (MATCH_MP_TAC th 4126 THEN REPEAT CONJ_TAC 4127 THEN FIRST_ASSUM MATCH_ACCEPT_TAC), 4128 4129 CONJ_TAC 4130 THENL 4131 [ MATCH_ACCEPT_TAC th 4132 ORELSE (MATCH_MP_TAC th 4133 THEN REPEAT CONJ_TAC 4134 THEN FIRST_ASSUM MATCH_ACCEPT_TAC), 4135 4136 LIST_MK_COMB_TAC 4137 THEN (* n subgoals *) 4138 ( REFL_TAC ORELSE 4139 FIRST_ASSUM MATCH_ACCEPT_TAC ) 4140 ] 4141 ]) 4142 end 4143 end; 4144 4145 4146 4147fun define_subset_types_rule {types, defs, tyop_equivs, tyop_quotients,tyop_simps, 4148 inhabs, poly_preserves, poly_respects} = 4149 let val (Rdefs,types') = unzip (map define_subset_reln types) 4150 val respects' = map (prove_subset_respects Rdefs) inhabs 4151 4152 val LIFT_RULE = 4153 define_quotient_types_rule 4154 {types=types', 4155 defs=defs, 4156 respects=respects', 4157 tyop_equivs=tyop_equivs, 4158 tyop_quotients=tyop_quotients, 4159 tyop_simps=tyop_simps, 4160 poly_preserves=poly_preserves, poly_respects=poly_respects} 4161 in LIFT_RULE 4162 end; 4163 4164(* ---------------------------------- *) 4165(* MAIN ENTRY POINT FOR SUBSET TYPES. *) 4166(* ---------------------------------- *) 4167 4168fun define_subset_types {types, defs, tyop_equivs, tyop_quotients,tyop_simps, 4169 inhabs, poly_preserves, poly_respects, old_thms} = 4170 let fun print_thm' th = if !chatting then (print_thm th; print "\n"; th) 4171 else th 4172 4173 val LIFT_RULE = 4174 define_subset_types_rule 4175 {types=types, 4176 defs=defs, 4177 inhabs=inhabs, 4178 tyop_equivs=tyop_equivs, 4179 tyop_quotients=tyop_quotients, 4180 tyop_simps=tyop_simps, 4181 poly_preserves=poly_preserves, poly_respects=poly_respects} 4182 4183 val _ = if !chatting then print "\nLifted theorems:\n" else () 4184 val new_thms = map (print_thm' o LIFT_RULE) 4185 old_thms handle e => Raise e 4186 in 4187 new_thms 4188 end; 4189 4190 4191 4192end; (* of structure quotient *) 4193