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