QuotMain.thy
changeset 99 19e5aceb8c2d
parent 98 aeb4fc74984f
child 100 09f4d69f7b66
equal deleted inserted replaced
98:aeb4fc74984f 99:19e5aceb8c2d
   297   get_fun absF @{typ t} @{typ qt} @{context} @{typ "t * nat"}
   297   get_fun absF @{typ t} @{typ qt} @{context} @{typ "t * nat"}
   298   |> fst
   298   |> fst
   299   |> Syntax.string_of_term @{context}
   299   |> Syntax.string_of_term @{context}
   300   |> writeln
   300   |> writeln
   301 *}
   301 *}
       
   302 
       
   303 text {* produces the definition for a lifted constant *}
       
   304 
       
   305 ML {*
       
   306 fun get_const_def nconst oconst rty qty lthy =
       
   307 let
       
   308   val ty = fastype_of nconst
       
   309   val (arg_tys, res_ty) = strip_type ty
       
   310 
       
   311   val fresh_args = arg_tys |> map (pair "x")
       
   312                            |> Variable.variant_frees lthy [nconst, oconst]
       
   313                            |> map Free
       
   314 
       
   315   val rep_fns = map (fst o get_fun repF rty qty lthy) arg_tys
       
   316   val abs_fn  = (fst o get_fun absF rty qty lthy) res_ty
       
   317 
       
   318 in
       
   319   map (op $) (rep_fns ~~ fresh_args)
       
   320   |> curry list_comb oconst
       
   321   |> curry (op $) abs_fn
       
   322   |> fold_rev lambda fresh_args
       
   323 end
       
   324 *}
       
   325 
       
   326 ML {*
       
   327 fun exchange_ty rty qty ty =
       
   328   if ty = rty
       
   329   then qty
       
   330   else
       
   331     (case ty of
       
   332        Type (s, tys) => Type (s, map (exchange_ty rty qty) tys)
       
   333       | _ => ty
       
   334     )
       
   335 *}
       
   336 
       
   337 ML {*
       
   338 fun make_const_def nconst_bname oconst mx rty qty lthy =
       
   339 let
       
   340   val oconst_ty = fastype_of oconst
       
   341   val nconst_ty = exchange_ty rty qty oconst_ty
       
   342   val nconst = Const (Binding.name_of nconst_bname, nconst_ty)
       
   343   val def_trm = get_const_def nconst oconst rty qty lthy
       
   344 in
       
   345   define (nconst_bname, mx, def_trm) lthy
       
   346 end
       
   347 *}
       
   348 
       
   349 local_setup {*
       
   350   make_const_def @{binding VR} @{term "vr"} NoSyn @{typ "t"} @{typ "qt"} #> snd #>
       
   351   make_const_def @{binding AP} @{term "ap"} NoSyn @{typ "t"} @{typ "qt"} #> snd #>
       
   352   make_const_def @{binding LM} @{term "lm"} NoSyn @{typ "t"} @{typ "qt"} #> snd
       
   353 *}
       
   354 
       
   355 term vr
       
   356 term ap
       
   357 term lm
       
   358 thm VR_def AP_def LM_def
       
   359 term LM
       
   360 term VR
       
   361 term AP
       
   362 
       
   363 text {* a test with functions *}
       
   364 datatype 'a t' =
       
   365   vr' "string"
       
   366 | ap' "('a t') * ('a t')"
       
   367 | lm' "'a" "string \<Rightarrow> ('a t')"
       
   368 
       
   369 consts Rt' :: "('a t') \<Rightarrow> ('a t') \<Rightarrow> bool"
       
   370 axioms t_eq': "EQUIV Rt'"
       
   371 
       
   372 quotient qt' = "'a t'" / "Rt'"
       
   373   apply(rule t_eq')
       
   374   done
       
   375 
       
   376 print_theorems
       
   377 
       
   378 local_setup {*
       
   379   make_const_def @{binding VR'} @{term "vr'"} NoSyn @{typ "'a t'"} @{typ "'a qt'"} #> snd #>
       
   380   make_const_def @{binding AP'} @{term "ap'"} NoSyn @{typ "'a t'"} @{typ "'a qt'"} #> snd #>
       
   381   make_const_def @{binding LM'} @{term "lm'"} NoSyn @{typ "'a t'"} @{typ "'a qt'"} #> snd
       
   382 *}
       
   383 
       
   384 term vr'
       
   385 term ap'
       
   386 term ap'
       
   387 thm VR'_def AP'_def LM'_def
       
   388 term LM'
       
   389 term VR'
       
   390 term AP'
       
   391 
       
   392 
       
   393 text {* finite set example *}
       
   394 print_syntax
       
   395 inductive
       
   396   list_eq (infix "\<approx>" 50)
       
   397 where
       
   398   "a#b#xs \<approx> b#a#xs"
       
   399 | "[] \<approx> []"
       
   400 | "xs \<approx> ys \<Longrightarrow> ys \<approx> xs"
       
   401 | "a#a#xs \<approx> a#xs"
       
   402 | "xs \<approx> ys \<Longrightarrow> a#xs \<approx> a#ys"
       
   403 | "\<lbrakk>xs1 \<approx> xs2; xs2 \<approx> xs3\<rbrakk> \<Longrightarrow> xs1 \<approx> xs3"
       
   404 
       
   405 lemma list_eq_refl:
       
   406   shows "xs \<approx> xs"
       
   407   apply (induct xs)
       
   408    apply (auto intro: list_eq.intros)
       
   409   done
       
   410 
       
   411 lemma equiv_list_eq:
       
   412   shows "EQUIV list_eq"
       
   413   unfolding EQUIV_REFL_SYM_TRANS REFL_def SYM_def TRANS_def
       
   414   apply(auto intro: list_eq.intros list_eq_refl)
       
   415   done
       
   416 
       
   417 quotient fset = "'a list" / "list_eq"
       
   418   apply(rule equiv_list_eq)
       
   419   done
       
   420 
       
   421 print_theorems
       
   422 
       
   423 typ "'a fset"
       
   424 thm "Rep_fset"
       
   425 
       
   426 local_setup {*
       
   427   make_const_def @{binding EMPTY} @{term "[]"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   428 *}
       
   429 
       
   430 term Nil
       
   431 term EMPTY
       
   432 thm EMPTY_def
       
   433 
       
   434 
       
   435 local_setup {*
       
   436   make_const_def @{binding INSERT} @{term "op #"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   437 *}
       
   438 
       
   439 term Cons
       
   440 term INSERT
       
   441 thm INSERT_def
       
   442 
       
   443 local_setup {*
       
   444   make_const_def @{binding UNION} @{term "op @"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   445 *}
       
   446 
       
   447 term append
       
   448 term UNION
       
   449 thm UNION_def
       
   450 
       
   451 
       
   452 thm QUOTIENT_fset
       
   453 
       
   454 thm QUOT_TYPE_I_fset.thm11
       
   455 
       
   456 
       
   457 fun
       
   458   membship :: "'a \<Rightarrow> 'a list \<Rightarrow> bool" (infix "memb" 100)
       
   459 where
       
   460   m1: "(x memb []) = False"
       
   461 | m2: "(x memb (y#xs)) = ((x=y) \<or> (x memb xs))"
       
   462 
       
   463 lemma mem_respects:
       
   464   fixes z
       
   465   assumes a: "list_eq x y"
       
   466   shows "(z memb x) = (z memb y)"
       
   467   using a by induct auto
       
   468 
       
   469 
       
   470 fun
       
   471   card1 :: "'a list \<Rightarrow> nat"
       
   472 where
       
   473   card1_nil: "(card1 []) = 0"
       
   474 | card1_cons: "(card1 (x # xs)) = (if (x memb xs) then (card1 xs) else (Suc (card1 xs)))"
       
   475 
       
   476 local_setup {*
       
   477   make_const_def @{binding card} @{term "card1"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   478 *}
       
   479 
       
   480 term card1
       
   481 term card
       
   482 thm card_def
       
   483 
       
   484 (* text {*
       
   485  Maybe make_const_def should require a theorem that says that the particular lifted function
       
   486  respects the relation. With it such a definition would be impossible:
       
   487  make_const_def @{binding CARD} @{term "length"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   488 *}*)
       
   489 
       
   490 lemma card1_rsp:
       
   491   fixes a b :: "'a list"
       
   492   assumes e: "a \<approx> b"
       
   493   shows "card1 a = card1 b"
       
   494   using e apply induct
       
   495   apply (simp_all add:mem_respects)
       
   496   done
       
   497 
       
   498 lemma card1_0:
       
   499   fixes a :: "'a list"
       
   500   shows "(card1 a = 0) = (a = [])"
       
   501   apply (induct a)
       
   502    apply (simp)
       
   503   apply (simp_all)
       
   504    apply meson
       
   505   apply (simp_all)
       
   506   done
       
   507 
       
   508 lemma not_mem_card1:
       
   509   fixes x :: "'a"
       
   510   fixes xs :: "'a list"
       
   511   shows "~(x memb xs) \<Longrightarrow> card1 (x # xs) = Suc (card1 xs)"
       
   512   by simp
       
   513 
       
   514 
       
   515 lemma mem_cons:
       
   516   fixes x :: "'a"
       
   517   fixes xs :: "'a list"
       
   518   assumes a : "x memb xs"
       
   519   shows "x # xs \<approx> xs"
       
   520   using a
       
   521   apply (induct xs)
       
   522   apply (auto intro: list_eq.intros)
       
   523   done
       
   524 
       
   525 lemma card1_suc:
       
   526   fixes xs :: "'a list"
       
   527   fixes n :: "nat"
       
   528   assumes c: "card1 xs = Suc n"
       
   529   shows "\<exists>a ys. ~(a memb ys) \<and> xs \<approx> (a # ys)"
       
   530   using c
       
   531 apply(induct xs)
       
   532 apply (metis Suc_neq_Zero card1_0)
       
   533 apply (metis QUOT_TYPE_I_fset.R_trans QuotMain.card1_cons list_eq_refl mem_cons)
       
   534 done
       
   535 
       
   536 primrec
       
   537   fold1
       
   538 where
       
   539   "fold1 f (g :: 'a \<Rightarrow> 'b) (z :: 'b) [] = z"
       
   540 | "fold1 f g z (a # A) =
       
   541      (if ((!u v. (f u v = f v u))
       
   542       \<and> (!u v w. ((f u (f v w) = f (f u v) w))))
       
   543      then (
       
   544        if (a memb A) then (fold1 f g z A) else (f (g a) (fold1 f g z A))
       
   545      ) else z)"
       
   546 
       
   547 thm fold1.simps
       
   548 
       
   549 lemma cons_preserves:
       
   550   fixes z
       
   551   assumes a: "xs \<approx> ys"
       
   552   shows "(z # xs) \<approx> (z # ys)"
       
   553   using a by (rule QuotMain.list_eq.intros(5))
       
   554 
       
   555 lemma fs1_strong_cases:
       
   556   fixes X :: "'a list"
       
   557   shows "(X = []) \<or> (\<exists>a. \<exists> Y. (~(a memb Y) \<and> (X \<approx> a # Y)))"
       
   558   apply (induct X)
       
   559   apply (simp)
       
   560   apply (metis QUOT_TYPE_I_fset.thm11 list_eq_refl mem_cons QuotMain.m1)
       
   561   done
       
   562 
       
   563 
       
   564 text {*
       
   565   Unabs_def converts a definition given as
       
   566 
       
   567     c \<equiv> %x. %y. f x y
       
   568 
       
   569   to a theorem of the form
       
   570 
       
   571     c x y \<equiv> f x y
       
   572 
       
   573   This function is needed to rewrite the right-hand
       
   574   side to the left-hand side.
       
   575 *}
       
   576 
       
   577 ML {*
       
   578 fun unabs_def ctxt def =
       
   579 let
       
   580   val (lhs, rhs) = Thm.dest_equals (cprop_of def)
       
   581   val xs = strip_abs_vars (term_of rhs)
       
   582   val (_, ctxt') = Variable.add_fixes (map fst xs) ctxt
       
   583   
       
   584   val thy = ProofContext.theory_of ctxt'
       
   585   val cxs = map (cterm_of thy o Free) xs
       
   586   val new_lhs = Drule.list_comb (lhs, cxs)
       
   587 
       
   588   fun get_conv [] = Conv.rewr_conv def
       
   589     | get_conv (x::xs) = Conv.fun_conv (get_conv xs)
       
   590 in
       
   591   get_conv xs new_lhs |>  
       
   592   singleton (ProofContext.export ctxt' ctxt)
       
   593 end
       
   594 *}
       
   595 
       
   596 local_setup {*
       
   597   make_const_def @{binding IN} @{term "membship"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   598 *}
       
   599 
       
   600 term membship
       
   601 term IN
       
   602 thm IN_def
       
   603 
       
   604 (* unabs_def tests *)
       
   605 ML {* (Conv.fun_conv (Conv.fun_conv (Conv.rewr_conv @{thm IN_def}))) @{cterm "IN x y"} *}
       
   606 ML {* MetaSimplifier.rewrite_rule @{thms IN_def} @{thm IN_def}*}
       
   607 ML {* @{thm IN_def}; unabs_def @{context} @{thm IN_def} *}
       
   608 
       
   609 lemmas a = QUOT_TYPE.ABS_def[OF QUOT_TYPE_fset]
       
   610 thm QUOT_TYPE.thm11[OF QUOT_TYPE_fset, THEN iffD1, simplified a]
       
   611 
       
   612 lemma yy:
       
   613   shows "(False = x memb []) = (False = IN (x::nat) EMPTY)"
       
   614 unfolding IN_def EMPTY_def
       
   615 apply(rule_tac f="(op =) False" in arg_cong)
       
   616 apply(rule mem_respects)
       
   617 apply(simp only: QUOT_TYPE_I_fset.REP_ABS_rsp)
       
   618 apply(rule list_eq.intros)
       
   619 done
       
   620 
       
   621 lemma
       
   622   shows "IN (x::nat) EMPTY = False"
       
   623 using m1
       
   624 apply -
       
   625 apply(rule yy[THEN iffD1, symmetric])
       
   626 apply(simp)
       
   627 done
       
   628 
       
   629 lemma
       
   630   shows "((x=y) \<or> (IN x xs) = (IN (x::nat) (INSERT y xs))) =
       
   631          ((x=y) \<or> x memb REP_fset xs = x memb (y # REP_fset xs))"
       
   632 unfolding IN_def INSERT_def
       
   633 apply(rule_tac f="(op \<or>) (x=y)" in arg_cong)
       
   634 apply(rule_tac f="(op =) (x memb REP_fset xs)" in arg_cong)
       
   635 apply(rule mem_respects)
       
   636 apply(rule list_eq.intros(3))
       
   637 apply(unfold REP_fset_def ABS_fset_def)
       
   638 apply(simp only: QUOT_TYPE.REP_ABS_rsp[OF QUOT_TYPE_fset])
       
   639 apply(rule list_eq_refl)
       
   640 done
       
   641 
       
   642 lemma append_respects_fst:
       
   643   assumes a : "list_eq l1 l2"
       
   644   shows "list_eq (l1 @ s) (l2 @ s)"
       
   645   using a
       
   646   apply(induct)
       
   647   apply(auto intro: list_eq.intros)
       
   648   apply(simp add: list_eq_refl)
       
   649 done
       
   650 
       
   651 lemma yyy:
       
   652   shows "
       
   653     (
       
   654      (UNION EMPTY s = s) &
       
   655      ((UNION (INSERT e s1) s2) = (INSERT e (UNION s1 s2)))
       
   656     ) = (
       
   657      ((ABS_fset ([] @ REP_fset s)) = s) &
       
   658      ((ABS_fset ((e # (REP_fset s1)) @ REP_fset s2)) = ABS_fset (e # (REP_fset s1 @ REP_fset s2)))
       
   659     )"
       
   660   unfolding UNION_def EMPTY_def INSERT_def
       
   661   apply(rule_tac f="(op &)" in arg_cong2)
       
   662   apply(rule_tac f="(op =)" in arg_cong2)
       
   663   apply(simp only: QUOT_TYPE_I_fset.thm11[symmetric])
       
   664   apply(rule append_respects_fst)
       
   665   apply(simp only: QUOT_TYPE_I_fset.REP_ABS_rsp)
       
   666   apply(rule list_eq_refl)
       
   667   apply(simp)
       
   668   apply(rule_tac f="(op =)" in arg_cong2)
       
   669   apply(simp only: QUOT_TYPE_I_fset.thm11[symmetric])
       
   670   apply(rule append_respects_fst)
       
   671   apply(simp only: QUOT_TYPE_I_fset.REP_ABS_rsp)
       
   672   apply(rule list_eq_refl)
       
   673   apply(simp only: QUOT_TYPE_I_fset.thm11[symmetric])
       
   674   apply(rule list_eq.intros(5))
       
   675   apply(simp only: QUOT_TYPE_I_fset.REP_ABS_rsp)
       
   676   apply(rule list_eq_refl)
       
   677 done
       
   678 
       
   679 lemma
       
   680   shows "
       
   681      (UNION EMPTY s = s) &
       
   682      ((UNION (INSERT e s1) s2) = (INSERT e (UNION s1 s2)))"
       
   683   apply (simp add: yyy)
       
   684   apply (simp add: QUOT_TYPE_I_fset.thm10)
       
   685   done
       
   686 
       
   687 ML {*
       
   688   fun mk_rep x = @{term REP_fset} $ x;
       
   689   fun mk_abs x = @{term ABS_fset} $ x;
       
   690   val consts = [@{const_name "Nil"}, @{const_name "append"},
       
   691                 @{const_name "Cons"}, @{const_name "membship"},
       
   692                 @{const_name "card1"}]
       
   693 *}
       
   694 
       
   695 ML {* val qty = @{typ "'a fset"} *}
       
   696 ML {* val tt = Type ("fun", [Type ("fun", [qty, @{typ "prop"}]), @{typ "prop"}]) *}
       
   697 ML {* val fall = Const(@{const_name all}, dummyT) *}
       
   698 
       
   699 ML {*
       
   700 fun build_goal_term ctxt thm constructors rty qty mk_rep mk_abs =
       
   701   let
       
   702     fun mk_rep_abs x = mk_rep (mk_abs x);
       
   703 
       
   704     fun is_constructor (Const (x, _)) = member (op =) constructors x
       
   705       | is_constructor _ = false;
       
   706 
       
   707     fun maybe_mk_rep_abs t =
       
   708       let
       
   709         val _ = writeln ("Maybe: " ^ Syntax.string_of_term ctxt t)
       
   710       in
       
   711         if fastype_of t = rty then mk_rep_abs t else t
       
   712       end;
       
   713 
       
   714     fun is_all (Const ("all", Type("fun", [Type("fun", [ty, _]), _]))) = ty = rty
       
   715       | is_all _ = false;
       
   716 
       
   717     fun is_ex (Const ("Ex", Type("fun", [Type("fun", [ty, _]), _]))) = ty = rty
       
   718       | is_ex _ = false;
       
   719 
       
   720     fun build_aux ctxt1 tm =
       
   721       let
       
   722         val (head, args) = Term.strip_comb tm;
       
   723         val args' = map (build_aux ctxt1) args;
       
   724       in
       
   725         (case head of
       
   726           Abs (x, T, t) =>
       
   727             if T = rty then let
       
   728               val ([x'], ctxt2) = Variable.variant_fixes [x] ctxt1;
       
   729               val v = Free (x', qty);
       
   730               val t' = subst_bound (mk_rep v, t);
       
   731               val rec_term = build_aux ctxt2 t';
       
   732               val _ = tracing (Syntax.string_of_term ctxt2 t')
       
   733               val _ = tracing (Syntax.string_of_term ctxt2 (Term.lambda_name (x, v) rec_term))
       
   734             in
       
   735               Term.lambda_name (x, v) rec_term
       
   736             end else let
       
   737               val ([x'], ctxt2) = Variable.variant_fixes [x] ctxt1;
       
   738               val v = Free (x', T);
       
   739               val t' = subst_bound (v, t);
       
   740               val rec_term = build_aux ctxt2 t';
       
   741             in Term.lambda_name (x, v) rec_term end
       
   742         | _ =>  (* I assume that we never lift 'prop' since it is not of sort type *)
       
   743             if is_all head then
       
   744               list_comb (Const(@{const_name all}, dummyT), args') |> Syntax.check_term ctxt1
       
   745             else if is_ex head then
       
   746               list_comb (Const(@{const_name Ex}, dummyT), args') |> Syntax.check_term ctxt1
       
   747             else if is_constructor head then
       
   748               maybe_mk_rep_abs (list_comb (head, map maybe_mk_rep_abs args'))
       
   749             else
       
   750               maybe_mk_rep_abs (list_comb (head, args'))
       
   751         )
       
   752       end;
       
   753   in
       
   754     build_aux ctxt (Thm.prop_of thm)
       
   755   end
       
   756 *}
       
   757 
       
   758 ML {*
       
   759 fun build_goal ctxt thm cons rty qty mk_rep mk_abs =
       
   760   Logic.mk_equals ((build_goal_term ctxt thm cons rty qty mk_rep mk_abs), (Thm.prop_of thm))
       
   761 *}
       
   762 
       
   763 ML {*
       
   764   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm m1}))
       
   765 *}
       
   766   
       
   767 ML {*
       
   768 m1_novars |> prop_of
       
   769 |> Syntax.string_of_term @{context}
       
   770 |> writeln; 
       
   771 build_goal_term @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
   772 |> Syntax.string_of_term @{context}
       
   773 |> writeln
       
   774 *}
       
   775 
       
   776 
       
   777 ML {* val fset_defs = @{thms EMPTY_def IN_def UNION_def card_def INSERT_def} *}
       
   778 ML {* val fset_defs_sym = map (fn t => symmetric (unabs_def @{context} t)) fset_defs *}
       
   779 
       
   780 ML {*
       
   781   fun dest_cbinop t =
       
   782     let
       
   783       val (t2, rhs) = Thm.dest_comb t;
       
   784       val (bop, lhs) = Thm.dest_comb t2;
       
   785     in
       
   786       (bop, (lhs, rhs))
       
   787     end
       
   788 *}
       
   789 
       
   790 ML {*
       
   791   fun dest_ceq t =
       
   792     let
       
   793       val (bop, pair) = dest_cbinop t;
       
   794       val (bop_s, _) = Term.dest_Const (Thm.term_of bop);
       
   795     in
       
   796       if bop_s = "op =" then pair else (raise CTERM ("Not an equality", [t]))
       
   797     end
       
   798 *}
       
   799 
       
   800 ML Thm.instantiate
       
   801 ML {*@{thm arg_cong2}*}
       
   802 ML {*@{thm arg_cong2[of _ _ _ _ "op ="]} *}
       
   803 ML {* val cT = @{cpat "op ="} |> Thm.ctyp_of_term |> Thm.dest_ctyp |> hd *}
       
   804 ML {*
       
   805   Toplevel.program (fn () =>
       
   806     Drule.instantiate' [SOME cT, SOME cT, SOME @{ctyp bool}] [NONE, NONE, NONE, NONE, SOME (@{cpat "op ="})] @{thm arg_cong2}
       
   807   )
       
   808 *}
       
   809 
       
   810 ML {*
       
   811   fun split_binop_conv t =
       
   812     let
       
   813       val (lhs, rhs) = dest_ceq t;
       
   814       val (bop, _) = dest_cbinop lhs;
       
   815       val [clT, cr2] = bop |> Thm.ctyp_of_term |> Thm.dest_ctyp;
       
   816       val [cmT, crT] = Thm.dest_ctyp cr2;
       
   817     in
       
   818       Drule.instantiate' [SOME clT, SOME cmT, SOME crT] [NONE, NONE, NONE, NONE, SOME bop] @{thm arg_cong2}
       
   819     end
       
   820 *}
       
   821 
       
   822 ML {*
       
   823   fun split_arg_conv t =
       
   824     let
       
   825       val (lhs, rhs) = dest_ceq t;
       
   826       val (lop, larg) = Thm.dest_comb lhs;
       
   827       val [caT, crT] = lop |> Thm.ctyp_of_term |> Thm.dest_ctyp;
       
   828     in
       
   829       Drule.instantiate' [SOME caT, SOME crT] [NONE, NONE, SOME lop] @{thm arg_cong}
       
   830     end
       
   831 *}
       
   832 
       
   833 ML {*
       
   834   fun split_binop_tac n thm =
       
   835     let
       
   836       val concl = Thm.cprem_of thm n;
       
   837       val (_, cconcl) = Thm.dest_comb concl;
       
   838       val rewr = split_binop_conv cconcl;
       
   839     in
       
   840       rtac rewr n thm
       
   841     end
       
   842       handle CTERM _ => Seq.empty
       
   843 *}
       
   844 
       
   845 ML {*
       
   846   fun split_arg_tac n thm =
       
   847     let
       
   848       val concl = Thm.cprem_of thm n;
       
   849       val (_, cconcl) = Thm.dest_comb concl;
       
   850       val rewr = split_arg_conv cconcl;
       
   851     in
       
   852       rtac rewr n thm
       
   853     end
       
   854       handle CTERM _ => Seq.empty
       
   855 *}
       
   856 
       
   857 (* Has all the theorems about fset plugged in. These should be parameters to the tactic *)
       
   858 
       
   859 lemma trueprop_cong:
       
   860   shows "(a \<equiv> b) \<Longrightarrow> (Trueprop a \<equiv> Trueprop b)"
       
   861   by auto
       
   862 
       
   863 ML {*
       
   864   Cong_Tac.cong_tac
       
   865 *}
       
   866 
       
   867 thm QUOT_TYPE_I_fset.R_trans2
       
   868 ML {*
       
   869   fun foo_tac' ctxt =
       
   870     REPEAT_ALL_NEW (FIRST' [
       
   871 (*      rtac @{thm trueprop_cong},*)
       
   872       rtac @{thm list_eq_refl},
       
   873       rtac @{thm cons_preserves},
       
   874       rtac @{thm mem_respects},
       
   875       rtac @{thm card1_rsp},
       
   876       rtac @{thm QUOT_TYPE_I_fset.R_trans2},
       
   877       CHANGED o (simp_tac ((Simplifier.context ctxt HOL_ss) addsimps @{thms QUOT_TYPE_I_fset.REP_ABS_rsp})),
       
   878       Cong_Tac.cong_tac @{thm cong},
       
   879       rtac @{thm ext}
       
   880 (*      rtac @{thm eq_reflection},*)
       
   881 (*      CHANGED o (ObjectLogic.full_atomize_tac)*)
       
   882     ])
       
   883 *}
       
   884 
       
   885 ML {*
       
   886   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm m1}))
       
   887   val goal = build_goal @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
   888   val cgoal = cterm_of @{theory} goal
       
   889   val cgoal2 = Thm.rhs_of (MetaSimplifier.rewrite false fset_defs_sym cgoal)
       
   890 *}
       
   891 
       
   892 (*notation ( output) "prop" ("#_" [1000] 1000) *)
       
   893 notation ( output) "Trueprop" ("#_" [1000] 1000)
       
   894 
       
   895 lemma atomize_eqv[atomize]: 
       
   896   shows "(Trueprop A \<equiv> Trueprop B) \<equiv> (A \<equiv> B)" 
       
   897 proof
       
   898   assume "A \<equiv> B" 
       
   899   then show "Trueprop A \<equiv> Trueprop B" by unfold
       
   900 next
       
   901   assume *: "Trueprop A \<equiv> Trueprop B"
       
   902   have "A = B"
       
   903   proof (cases A)
       
   904     case True
       
   905     have "A" by fact
       
   906     then show "A = B" using * by simp
       
   907   next
       
   908     case False
       
   909     have "\<not>A" by fact
       
   910     then show "A = B" using * by auto
       
   911   qed
       
   912   then show "A \<equiv> B" by (rule eq_reflection)
       
   913 qed
       
   914 
       
   915 prove {* (Thm.term_of cgoal2) *}
       
   916   apply (tactic {* LocalDefs.unfold_tac @{context} fset_defs *} )
       
   917   apply (atomize(full))
       
   918   apply (tactic {* foo_tac' @{context} 1 *})
       
   919   done
       
   920 
       
   921 thm length_append (* Not true but worth checking that the goal is correct *)
       
   922 ML {*
       
   923   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm length_append}))
       
   924   val goal = build_goal @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
   925   val cgoal = cterm_of @{theory} goal
       
   926   val cgoal2 = Thm.rhs_of (MetaSimplifier.rewrite false fset_defs_sym cgoal)
       
   927 *}
       
   928 prove {* Thm.term_of cgoal2 *}
       
   929   apply (tactic {* LocalDefs.unfold_tac @{context} fset_defs *} )
       
   930   apply (atomize(full))
       
   931   apply (tactic {* foo_tac' @{context} 1 *})
       
   932   sorry
       
   933 
       
   934 thm m2
       
   935 ML {*
       
   936   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm m2}))
       
   937   val goal = build_goal @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
   938   val cgoal = cterm_of @{theory} goal
       
   939   val cgoal2 = Thm.rhs_of (MetaSimplifier.rewrite false fset_defs_sym cgoal)
       
   940 *}
       
   941 prove {* Thm.term_of cgoal2 *}
       
   942   apply (tactic {* LocalDefs.unfold_tac @{context} fset_defs *} )
       
   943   apply (atomize(full))
       
   944   apply (tactic {* foo_tac' @{context} 1 *})
       
   945   done
       
   946 
       
   947 thm list_eq.intros(4)
       
   948 ML {*
       
   949   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm list_eq.intros(4)}))
       
   950   val goal = build_goal @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
   951   val cgoal = cterm_of @{theory} goal
       
   952   val cgoal2 = Thm.rhs_of (MetaSimplifier.rewrite false fset_defs_sym cgoal)
       
   953   val cgoal3 = Thm.rhs_of (MetaSimplifier.rewrite true @{thms QUOT_TYPE_I_fset.thm10} cgoal2)
       
   954 *}
       
   955 
       
   956 (* It is the same, but we need a name for it. *)
       
   957 prove zzz : {* Thm.term_of cgoal3 *}
       
   958   apply (tactic {* LocalDefs.unfold_tac @{context} fset_defs *} )
       
   959   apply (atomize(full))
       
   960   apply (tactic {* foo_tac' @{context} 1 *})
       
   961   done
       
   962 
       
   963 lemma zzz' :
       
   964   "(REP_fset (INSERT a (INSERT a (ABS_fset xs))) \<approx> REP_fset (INSERT a (ABS_fset xs)))"
       
   965   using list_eq.intros(4) by (simp only: zzz)
       
   966 
       
   967 thm QUOT_TYPE_I_fset.REPS_same
       
   968 ML {* val zzz'' = MetaSimplifier.rewrite_rule @{thms QUOT_TYPE_I_fset.REPS_same} @{thm zzz'} *}
       
   969 
       
   970 
       
   971 thm list_eq.intros(5)
       
   972 ML {*
       
   973   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm list_eq.intros(5)}))
       
   974   val goal = build_goal @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
   975 *}
       
   976 ML {*
       
   977   val cgoal =
       
   978     Toplevel.program (fn () =>
       
   979       cterm_of @{theory} goal
       
   980     )
       
   981 *}
       
   982 ML {*
       
   983   val cgoal2 = Thm.rhs_of (MetaSimplifier.rewrite true fset_defs_sym cgoal)
       
   984 *}
       
   985 prove {* Thm.term_of cgoal2 *}
       
   986   apply (tactic {* LocalDefs.unfold_tac @{context} fset_defs *} )
       
   987   apply (atomize(full))
       
   988   apply (tactic {* foo_tac' @{context} 1 *})
       
   989   done
       
   990 
       
   991 section {* handling quantifiers - regularize *}
   302 
   992 
   303 text {* tyRel takes a type and builds a relation that a quantifier over this
   993 text {* tyRel takes a type and builds a relation that a quantifier over this
   304   type needs to respect. *}
   994   type needs to respect. *}
   305 ML {*
   995 ML {*
   306 fun tyRel ty rty rel lthy =
   996 fun tyRel ty rty rel lthy =
   463 (*fun prove_reg trm \<Rightarrow> thm (we might need some facts to do this)
  1153 (*fun prove_reg trm \<Rightarrow> thm (we might need some facts to do this)
   464   trm == new_trm
  1154   trm == new_trm
   465 *)
  1155 *)
   466 
  1156 
   467 
  1157 
   468 text {* produces the definition for a lifted constant *}
  1158 
   469 
       
   470 ML {*
       
   471 fun get_const_def nconst oconst rty qty lthy =
       
   472 let
       
   473   val ty = fastype_of nconst
       
   474   val (arg_tys, res_ty) = strip_type ty
       
   475 
       
   476   val fresh_args = arg_tys |> map (pair "x")
       
   477                            |> Variable.variant_frees lthy [nconst, oconst]
       
   478                            |> map Free
       
   479 
       
   480   val rep_fns = map (fst o get_fun repF rty qty lthy) arg_tys
       
   481   val abs_fn  = (fst o get_fun absF rty qty lthy) res_ty
       
   482 
       
   483 in
       
   484   map (op $) (rep_fns ~~ fresh_args)
       
   485   |> curry list_comb oconst
       
   486   |> curry (op $) abs_fn
       
   487   |> fold_rev lambda fresh_args
       
   488 end
       
   489 *}
       
   490 
       
   491 ML {*
       
   492 fun exchange_ty rty qty ty =
       
   493   if ty = rty
       
   494   then qty
       
   495   else
       
   496     (case ty of
       
   497        Type (s, tys) => Type (s, map (exchange_ty rty qty) tys)
       
   498       | _ => ty
       
   499     )
       
   500 *}
       
   501 
       
   502 ML {*
       
   503 fun make_const_def nconst_bname oconst mx rty qty lthy =
       
   504 let
       
   505   val oconst_ty = fastype_of oconst
       
   506   val nconst_ty = exchange_ty rty qty oconst_ty
       
   507   val nconst = Const (Binding.name_of nconst_bname, nconst_ty)
       
   508   val def_trm = get_const_def nconst oconst rty qty lthy
       
   509 in
       
   510   define (nconst_bname, mx, def_trm) lthy
       
   511 end
       
   512 *}
       
   513 
       
   514 local_setup {*
       
   515   make_const_def @{binding VR} @{term "vr"} NoSyn @{typ "t"} @{typ "qt"} #> snd #>
       
   516   make_const_def @{binding AP} @{term "ap"} NoSyn @{typ "t"} @{typ "qt"} #> snd #>
       
   517   make_const_def @{binding LM} @{term "lm"} NoSyn @{typ "t"} @{typ "qt"} #> snd
       
   518 *}
       
   519 
       
   520 term vr
       
   521 term ap
       
   522 term lm
       
   523 thm VR_def AP_def LM_def
       
   524 term LM
       
   525 term VR
       
   526 term AP
       
   527 
       
   528 text {* a test with functions *}
       
   529 datatype 'a t' =
       
   530   vr' "string"
       
   531 | ap' "('a t') * ('a t')"
       
   532 | lm' "'a" "string \<Rightarrow> ('a t')"
       
   533 
       
   534 consts Rt' :: "('a t') \<Rightarrow> ('a t') \<Rightarrow> bool"
       
   535 axioms t_eq': "EQUIV Rt'"
       
   536 
       
   537 quotient qt' = "'a t'" / "Rt'"
       
   538   apply(rule t_eq')
       
   539   done
       
   540 
       
   541 print_theorems
       
   542 
       
   543 local_setup {*
       
   544   make_const_def @{binding VR'} @{term "vr'"} NoSyn @{typ "'a t'"} @{typ "'a qt'"} #> snd #>
       
   545   make_const_def @{binding AP'} @{term "ap'"} NoSyn @{typ "'a t'"} @{typ "'a qt'"} #> snd #>
       
   546   make_const_def @{binding LM'} @{term "lm'"} NoSyn @{typ "'a t'"} @{typ "'a qt'"} #> snd
       
   547 *}
       
   548 
       
   549 term vr'
       
   550 term ap'
       
   551 term ap'
       
   552 thm VR'_def AP'_def LM'_def
       
   553 term LM'
       
   554 term VR'
       
   555 term AP'
       
   556 
       
   557 
       
   558 text {* finite set example *}
       
   559 print_syntax
       
   560 inductive
       
   561   list_eq (infix "\<approx>" 50)
       
   562 where
       
   563   "a#b#xs \<approx> b#a#xs"
       
   564 | "[] \<approx> []"
       
   565 | "xs \<approx> ys \<Longrightarrow> ys \<approx> xs"
       
   566 | "a#a#xs \<approx> a#xs"
       
   567 | "xs \<approx> ys \<Longrightarrow> a#xs \<approx> a#ys"
       
   568 | "\<lbrakk>xs1 \<approx> xs2; xs2 \<approx> xs3\<rbrakk> \<Longrightarrow> xs1 \<approx> xs3"
       
   569 
       
   570 lemma list_eq_refl:
       
   571   shows "xs \<approx> xs"
       
   572   apply (induct xs)
       
   573    apply (auto intro: list_eq.intros)
       
   574   done
       
   575 
       
   576 lemma equiv_list_eq:
       
   577   shows "EQUIV list_eq"
       
   578   unfolding EQUIV_REFL_SYM_TRANS REFL_def SYM_def TRANS_def
       
   579   apply(auto intro: list_eq.intros list_eq_refl)
       
   580   done
       
   581 
       
   582 quotient fset = "'a list" / "list_eq"
       
   583   apply(rule equiv_list_eq)
       
   584   done
       
   585 
       
   586 print_theorems
       
   587 
       
   588 typ "'a fset"
       
   589 thm "Rep_fset"
       
   590 
       
   591 local_setup {*
       
   592   make_const_def @{binding EMPTY} @{term "[]"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   593 *}
       
   594 
       
   595 term Nil
       
   596 term EMPTY
       
   597 thm EMPTY_def
       
   598 
       
   599 
       
   600 local_setup {*
       
   601   make_const_def @{binding INSERT} @{term "op #"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   602 *}
       
   603 
       
   604 term Cons
       
   605 term INSERT
       
   606 thm INSERT_def
       
   607 
       
   608 local_setup {*
       
   609   make_const_def @{binding UNION} @{term "op @"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   610 *}
       
   611 
       
   612 term append
       
   613 term UNION
       
   614 thm UNION_def
       
   615 
       
   616 
       
   617 thm QUOTIENT_fset
       
   618 
       
   619 thm QUOT_TYPE_I_fset.thm11
       
   620 
       
   621 
       
   622 fun
       
   623   membship :: "'a \<Rightarrow> 'a list \<Rightarrow> bool" (infix "memb" 100)
       
   624 where
       
   625   m1: "(x memb []) = False"
       
   626 | m2: "(x memb (y#xs)) = ((x=y) \<or> (x memb xs))"
       
   627 
       
   628 lemma mem_respects:
       
   629   fixes z
       
   630   assumes a: "list_eq x y"
       
   631   shows "(z memb x) = (z memb y)"
       
   632   using a by induct auto
       
   633 
       
   634 
       
   635 fun
       
   636   card1 :: "'a list \<Rightarrow> nat"
       
   637 where
       
   638   card1_nil: "(card1 []) = 0"
       
   639 | card1_cons: "(card1 (x # xs)) = (if (x memb xs) then (card1 xs) else (Suc (card1 xs)))"
       
   640 
       
   641 local_setup {*
       
   642   make_const_def @{binding card} @{term "card1"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   643 *}
       
   644 
       
   645 term card1
       
   646 term card
       
   647 thm card_def
       
   648 
       
   649 (* text {*
       
   650  Maybe make_const_def should require a theorem that says that the particular lifted function
       
   651  respects the relation. With it such a definition would be impossible:
       
   652  make_const_def @{binding CARD} @{term "length"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   653 *}*)
       
   654 
       
   655 lemma card1_rsp:
       
   656   fixes a b :: "'a list"
       
   657   assumes e: "a \<approx> b"
       
   658   shows "card1 a = card1 b"
       
   659   using e apply induct
       
   660   apply (simp_all add:mem_respects)
       
   661   done
       
   662 
       
   663 lemma card1_0:
       
   664   fixes a :: "'a list"
       
   665   shows "(card1 a = 0) = (a = [])"
       
   666   apply (induct a)
       
   667    apply (simp)
       
   668   apply (simp_all)
       
   669    apply meson
       
   670   apply (simp_all)
       
   671   done
       
   672 
       
   673 lemma not_mem_card1:
       
   674   fixes x :: "'a"
       
   675   fixes xs :: "'a list"
       
   676   shows "~(x memb xs) \<Longrightarrow> card1 (x # xs) = Suc (card1 xs)"
       
   677   by simp
       
   678 
       
   679 
       
   680 lemma mem_cons:
       
   681   fixes x :: "'a"
       
   682   fixes xs :: "'a list"
       
   683   assumes a : "x memb xs"
       
   684   shows "x # xs \<approx> xs"
       
   685   using a
       
   686   apply (induct xs)
       
   687   apply (auto intro: list_eq.intros)
       
   688   done
       
   689 
       
   690 lemma card1_suc:
       
   691   fixes xs :: "'a list"
       
   692   fixes n :: "nat"
       
   693   assumes c: "card1 xs = Suc n"
       
   694   shows "\<exists>a ys. ~(a memb ys) \<and> xs \<approx> (a # ys)"
       
   695   using c
       
   696 apply(induct xs)
       
   697 apply (metis Suc_neq_Zero card1_0)
       
   698 apply (metis QUOT_TYPE_I_fset.R_trans QuotMain.card1_cons list_eq_refl mem_cons)
       
   699 done
       
   700 
       
   701 primrec
       
   702   fold1
       
   703 where
       
   704   "fold1 f (g :: 'a \<Rightarrow> 'b) (z :: 'b) [] = z"
       
   705 | "fold1 f g z (a # A) =
       
   706      (if ((!u v. (f u v = f v u))
       
   707       \<and> (!u v w. ((f u (f v w) = f (f u v) w))))
       
   708      then (
       
   709        if (a memb A) then (fold1 f g z A) else (f (g a) (fold1 f g z A))
       
   710      ) else z)"
       
   711 
       
   712 thm fold1.simps
       
   713 
       
   714 lemma cons_preserves:
       
   715   fixes z
       
   716   assumes a: "xs \<approx> ys"
       
   717   shows "(z # xs) \<approx> (z # ys)"
       
   718   using a by (rule QuotMain.list_eq.intros(5))
       
   719 
       
   720 lemma fs1_strong_cases:
       
   721   fixes X :: "'a list"
       
   722   shows "(X = []) \<or> (\<exists>a. \<exists> Y. (~(a memb Y) \<and> (X \<approx> a # Y)))"
       
   723   apply (induct X)
       
   724   apply (simp)
       
   725   apply (metis QUOT_TYPE_I_fset.thm11 list_eq_refl mem_cons QuotMain.m1)
       
   726   done
       
   727 
       
   728 
       
   729 text {*
       
   730   Unabs_def converts a definition given as
       
   731 
       
   732     c \<equiv> %x. %y. f x y
       
   733 
       
   734   to a theorem of the form
       
   735 
       
   736     c x y \<equiv> f x y
       
   737 
       
   738   This function is needed to rewrite the right-hand
       
   739   side to the left-hand side.
       
   740 *}
       
   741 
       
   742 ML {*
       
   743 fun unabs_def ctxt def =
       
   744 let
       
   745   val (lhs, rhs) = Thm.dest_equals (cprop_of def)
       
   746   val xs = strip_abs_vars (term_of rhs)
       
   747   val (_, ctxt') = Variable.add_fixes (map fst xs) ctxt
       
   748   
       
   749   val thy = ProofContext.theory_of ctxt'
       
   750   val cxs = map (cterm_of thy o Free) xs
       
   751   val new_lhs = Drule.list_comb (lhs, cxs)
       
   752 
       
   753   fun get_conv [] = Conv.rewr_conv def
       
   754     | get_conv (x::xs) = Conv.fun_conv (get_conv xs)
       
   755 in
       
   756   get_conv xs new_lhs |>  
       
   757   singleton (ProofContext.export ctxt' ctxt)
       
   758 end
       
   759 *}
       
   760 
       
   761 local_setup {*
       
   762   make_const_def @{binding IN} @{term "membship"} NoSyn @{typ "'a list"} @{typ "'a fset"} #> snd
       
   763 *}
       
   764 
       
   765 term membship
       
   766 term IN
       
   767 thm IN_def
       
   768 
       
   769 (* unabs_def tests *)
       
   770 ML {* (Conv.fun_conv (Conv.fun_conv (Conv.rewr_conv @{thm IN_def}))) @{cterm "IN x y"} *}
       
   771 ML {* MetaSimplifier.rewrite_rule @{thms IN_def} @{thm IN_def}*}
       
   772 ML {* @{thm IN_def}; unabs_def @{context} @{thm IN_def} *}
       
   773 
       
   774 lemmas a = QUOT_TYPE.ABS_def[OF QUOT_TYPE_fset]
       
   775 thm QUOT_TYPE.thm11[OF QUOT_TYPE_fset, THEN iffD1, simplified a]
       
   776 
       
   777 lemma yy:
       
   778   shows "(False = x memb []) = (False = IN (x::nat) EMPTY)"
       
   779 unfolding IN_def EMPTY_def
       
   780 apply(rule_tac f="(op =) False" in arg_cong)
       
   781 apply(rule mem_respects)
       
   782 apply(simp only: QUOT_TYPE_I_fset.REP_ABS_rsp)
       
   783 apply(rule list_eq.intros)
       
   784 done
       
   785 
       
   786 lemma
       
   787   shows "IN (x::nat) EMPTY = False"
       
   788 using m1
       
   789 apply -
       
   790 apply(rule yy[THEN iffD1, symmetric])
       
   791 apply(simp)
       
   792 done
       
   793 
       
   794 lemma
       
   795   shows "((x=y) \<or> (IN x xs) = (IN (x::nat) (INSERT y xs))) =
       
   796          ((x=y) \<or> x memb REP_fset xs = x memb (y # REP_fset xs))"
       
   797 unfolding IN_def INSERT_def
       
   798 apply(rule_tac f="(op \<or>) (x=y)" in arg_cong)
       
   799 apply(rule_tac f="(op =) (x memb REP_fset xs)" in arg_cong)
       
   800 apply(rule mem_respects)
       
   801 apply(rule list_eq.intros(3))
       
   802 apply(unfold REP_fset_def ABS_fset_def)
       
   803 apply(simp only: QUOT_TYPE.REP_ABS_rsp[OF QUOT_TYPE_fset])
       
   804 apply(rule list_eq_refl)
       
   805 done
       
   806 
       
   807 lemma append_respects_fst:
       
   808   assumes a : "list_eq l1 l2"
       
   809   shows "list_eq (l1 @ s) (l2 @ s)"
       
   810   using a
       
   811   apply(induct)
       
   812   apply(auto intro: list_eq.intros)
       
   813   apply(simp add: list_eq_refl)
       
   814 done
       
   815 
       
   816 lemma yyy:
       
   817   shows "
       
   818     (
       
   819      (UNION EMPTY s = s) &
       
   820      ((UNION (INSERT e s1) s2) = (INSERT e (UNION s1 s2)))
       
   821     ) = (
       
   822      ((ABS_fset ([] @ REP_fset s)) = s) &
       
   823      ((ABS_fset ((e # (REP_fset s1)) @ REP_fset s2)) = ABS_fset (e # (REP_fset s1 @ REP_fset s2)))
       
   824     )"
       
   825   unfolding UNION_def EMPTY_def INSERT_def
       
   826   apply(rule_tac f="(op &)" in arg_cong2)
       
   827   apply(rule_tac f="(op =)" in arg_cong2)
       
   828   apply(simp only: QUOT_TYPE_I_fset.thm11[symmetric])
       
   829   apply(rule append_respects_fst)
       
   830   apply(simp only: QUOT_TYPE_I_fset.REP_ABS_rsp)
       
   831   apply(rule list_eq_refl)
       
   832   apply(simp)
       
   833   apply(rule_tac f="(op =)" in arg_cong2)
       
   834   apply(simp only: QUOT_TYPE_I_fset.thm11[symmetric])
       
   835   apply(rule append_respects_fst)
       
   836   apply(simp only: QUOT_TYPE_I_fset.REP_ABS_rsp)
       
   837   apply(rule list_eq_refl)
       
   838   apply(simp only: QUOT_TYPE_I_fset.thm11[symmetric])
       
   839   apply(rule list_eq.intros(5))
       
   840   apply(simp only: QUOT_TYPE_I_fset.REP_ABS_rsp)
       
   841   apply(rule list_eq_refl)
       
   842 done
       
   843 
       
   844 lemma
       
   845   shows "
       
   846      (UNION EMPTY s = s) &
       
   847      ((UNION (INSERT e s1) s2) = (INSERT e (UNION s1 s2)))"
       
   848   apply (simp add: yyy)
       
   849   apply (simp add: QUOT_TYPE_I_fset.thm10)
       
   850   done
       
   851 
       
   852 ML {*
       
   853   fun mk_rep x = @{term REP_fset} $ x;
       
   854   fun mk_abs x = @{term ABS_fset} $ x;
       
   855   val consts = [@{const_name "Nil"}, @{const_name "append"},
       
   856                 @{const_name "Cons"}, @{const_name "membship"},
       
   857                 @{const_name "card1"}]
       
   858 *}
       
   859 
       
   860 ML {* val qty = @{typ "'a fset"} *}
       
   861 ML {* val tt = Type ("fun", [Type ("fun", [qty, @{typ "prop"}]), @{typ "prop"}]) *}
       
   862 ML {* val fall = Const(@{const_name all}, dummyT) *}
       
   863 
       
   864 ML {*
       
   865 fun build_goal_term ctxt thm constructors rty qty mk_rep mk_abs =
       
   866   let
       
   867     fun mk_rep_abs x = mk_rep (mk_abs x);
       
   868 
       
   869     fun is_constructor (Const (x, _)) = member (op =) constructors x
       
   870       | is_constructor _ = false;
       
   871 
       
   872     fun maybe_mk_rep_abs t =
       
   873       let
       
   874         val _ = writeln ("Maybe: " ^ Syntax.string_of_term ctxt t)
       
   875       in
       
   876         if fastype_of t = rty then mk_rep_abs t else t
       
   877       end;
       
   878 
       
   879     fun is_all (Const ("all", Type("fun", [Type("fun", [ty, _]), _]))) = ty = rty
       
   880       | is_all _ = false;
       
   881 
       
   882     fun is_ex (Const ("Ex", Type("fun", [Type("fun", [ty, _]), _]))) = ty = rty
       
   883       | is_ex _ = false;
       
   884 
       
   885     fun build_aux ctxt1 tm =
       
   886       let
       
   887         val (head, args) = Term.strip_comb tm;
       
   888         val args' = map (build_aux ctxt1) args;
       
   889       in
       
   890         (case head of
       
   891           Abs (x, T, t) =>
       
   892             if T = rty then let
       
   893               val ([x'], ctxt2) = Variable.variant_fixes [x] ctxt1;
       
   894               val v = Free (x', qty);
       
   895               val t' = subst_bound (mk_rep v, t);
       
   896               val rec_term = build_aux ctxt2 t';
       
   897               val _ = tracing (Syntax.string_of_term ctxt2 t')
       
   898               val _ = tracing (Syntax.string_of_term ctxt2 (Term.lambda_name (x, v) rec_term))
       
   899             in
       
   900               Term.lambda_name (x, v) rec_term
       
   901             end else let
       
   902               val ([x'], ctxt2) = Variable.variant_fixes [x] ctxt1;
       
   903               val v = Free (x', T);
       
   904               val t' = subst_bound (v, t);
       
   905               val rec_term = build_aux ctxt2 t';
       
   906             in Term.lambda_name (x, v) rec_term end
       
   907         | _ =>  (* I assume that we never lift 'prop' since it is not of sort type *)
       
   908             if is_all head then
       
   909               list_comb (Const(@{const_name all}, dummyT), args') |> Syntax.check_term ctxt1
       
   910             else if is_ex head then
       
   911               list_comb (Const(@{const_name Ex}, dummyT), args') |> Syntax.check_term ctxt1
       
   912             else if is_constructor head then
       
   913               maybe_mk_rep_abs (list_comb (head, map maybe_mk_rep_abs args'))
       
   914             else
       
   915               maybe_mk_rep_abs (list_comb (head, args'))
       
   916         )
       
   917       end;
       
   918   in
       
   919     build_aux ctxt (Thm.prop_of thm)
       
   920   end
       
   921 *}
       
   922 
       
   923 ML {*
       
   924 fun build_goal ctxt thm cons rty qty mk_rep mk_abs =
       
   925   Logic.mk_equals ((build_goal_term ctxt thm cons rty qty mk_rep mk_abs), (Thm.prop_of thm))
       
   926 *}
       
   927 
       
   928 ML {*
       
   929   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm m1}))
       
   930 *}
       
   931   
       
   932 ML {*
       
   933 m1_novars |> prop_of
       
   934 |> Syntax.string_of_term @{context}
       
   935 |> writeln; 
       
   936 build_goal_term @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
   937 |> Syntax.string_of_term @{context}
       
   938 |> writeln
       
   939 *}
       
   940 
       
   941 
       
   942 ML {* val fset_defs = @{thms EMPTY_def IN_def UNION_def card_def INSERT_def} *}
       
   943 ML {* val fset_defs_sym = map (fn t => symmetric (unabs_def @{context} t)) fset_defs *}
       
   944 
       
   945 ML {*
       
   946   fun dest_cbinop t =
       
   947     let
       
   948       val (t2, rhs) = Thm.dest_comb t;
       
   949       val (bop, lhs) = Thm.dest_comb t2;
       
   950     in
       
   951       (bop, (lhs, rhs))
       
   952     end
       
   953 *}
       
   954 
       
   955 ML {*
       
   956   fun dest_ceq t =
       
   957     let
       
   958       val (bop, pair) = dest_cbinop t;
       
   959       val (bop_s, _) = Term.dest_Const (Thm.term_of bop);
       
   960     in
       
   961       if bop_s = "op =" then pair else (raise CTERM ("Not an equality", [t]))
       
   962     end
       
   963 *}
       
   964 
       
   965 ML Thm.instantiate
       
   966 ML {*@{thm arg_cong2}*}
       
   967 ML {*@{thm arg_cong2[of _ _ _ _ "op ="]} *}
       
   968 ML {* val cT = @{cpat "op ="} |> Thm.ctyp_of_term |> Thm.dest_ctyp |> hd *}
       
   969 ML {*
       
   970   Toplevel.program (fn () =>
       
   971     Drule.instantiate' [SOME cT, SOME cT, SOME @{ctyp bool}] [NONE, NONE, NONE, NONE, SOME (@{cpat "op ="})] @{thm arg_cong2}
       
   972   )
       
   973 *}
       
   974 
       
   975 ML {*
       
   976   fun split_binop_conv t =
       
   977     let
       
   978       val (lhs, rhs) = dest_ceq t;
       
   979       val (bop, _) = dest_cbinop lhs;
       
   980       val [clT, cr2] = bop |> Thm.ctyp_of_term |> Thm.dest_ctyp;
       
   981       val [cmT, crT] = Thm.dest_ctyp cr2;
       
   982     in
       
   983       Drule.instantiate' [SOME clT, SOME cmT, SOME crT] [NONE, NONE, NONE, NONE, SOME bop] @{thm arg_cong2}
       
   984     end
       
   985 *}
       
   986 
       
   987 ML {*
       
   988   fun split_arg_conv t =
       
   989     let
       
   990       val (lhs, rhs) = dest_ceq t;
       
   991       val (lop, larg) = Thm.dest_comb lhs;
       
   992       val [caT, crT] = lop |> Thm.ctyp_of_term |> Thm.dest_ctyp;
       
   993     in
       
   994       Drule.instantiate' [SOME caT, SOME crT] [NONE, NONE, SOME lop] @{thm arg_cong}
       
   995     end
       
   996 *}
       
   997 
       
   998 ML {*
       
   999   fun split_binop_tac n thm =
       
  1000     let
       
  1001       val concl = Thm.cprem_of thm n;
       
  1002       val (_, cconcl) = Thm.dest_comb concl;
       
  1003       val rewr = split_binop_conv cconcl;
       
  1004     in
       
  1005       rtac rewr n thm
       
  1006     end
       
  1007       handle CTERM _ => Seq.empty
       
  1008 *}
       
  1009 
       
  1010 ML {*
       
  1011   fun split_arg_tac n thm =
       
  1012     let
       
  1013       val concl = Thm.cprem_of thm n;
       
  1014       val (_, cconcl) = Thm.dest_comb concl;
       
  1015       val rewr = split_arg_conv cconcl;
       
  1016     in
       
  1017       rtac rewr n thm
       
  1018     end
       
  1019       handle CTERM _ => Seq.empty
       
  1020 *}
       
  1021 
       
  1022 (* Has all the theorems about fset plugged in. These should be parameters to the tactic *)
       
  1023 
       
  1024 lemma trueprop_cong:
       
  1025   shows "(a \<equiv> b) \<Longrightarrow> (Trueprop a \<equiv> Trueprop b)"
       
  1026   by auto
       
  1027 
       
  1028 ML {*
       
  1029   Cong_Tac.cong_tac
       
  1030 *}
       
  1031 
       
  1032 thm QUOT_TYPE_I_fset.R_trans2
       
  1033 ML {*
       
  1034   fun foo_tac' ctxt =
       
  1035     REPEAT_ALL_NEW (FIRST' [
       
  1036 (*      rtac @{thm trueprop_cong},*)
       
  1037       rtac @{thm list_eq_refl},
       
  1038       rtac @{thm cons_preserves},
       
  1039       rtac @{thm mem_respects},
       
  1040       rtac @{thm card1_rsp},
       
  1041       rtac @{thm QUOT_TYPE_I_fset.R_trans2},
       
  1042       CHANGED o (simp_tac ((Simplifier.context ctxt HOL_ss) addsimps @{thms QUOT_TYPE_I_fset.REP_ABS_rsp})),
       
  1043       Cong_Tac.cong_tac @{thm cong},
       
  1044       rtac @{thm ext}
       
  1045 (*      rtac @{thm eq_reflection},*)
       
  1046 (*      CHANGED o (ObjectLogic.full_atomize_tac)*)
       
  1047     ])
       
  1048 *}
       
  1049 
       
  1050 ML {*
       
  1051   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm m1}))
       
  1052   val goal = build_goal @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
  1053   val cgoal = cterm_of @{theory} goal
       
  1054   val cgoal2 = Thm.rhs_of (MetaSimplifier.rewrite false fset_defs_sym cgoal)
       
  1055 *}
       
  1056 
       
  1057 (*notation ( output) "prop" ("#_" [1000] 1000) *)
       
  1058 notation ( output) "Trueprop" ("#_" [1000] 1000)
       
  1059 
       
  1060 lemma atomize_eqv[atomize]: 
       
  1061   shows "(Trueprop A \<equiv> Trueprop B) \<equiv> (A \<equiv> B)" 
       
  1062 proof
       
  1063   assume "A \<equiv> B" 
       
  1064   then show "Trueprop A \<equiv> Trueprop B" by unfold
       
  1065 next
       
  1066   assume *: "Trueprop A \<equiv> Trueprop B"
       
  1067   have "A = B"
       
  1068   proof (cases A)
       
  1069     case True
       
  1070     have "A" by fact
       
  1071     then show "A = B" using * by simp
       
  1072   next
       
  1073     case False
       
  1074     have "\<not>A" by fact
       
  1075     then show "A = B" using * by auto
       
  1076   qed
       
  1077   then show "A \<equiv> B" by (rule eq_reflection)
       
  1078 qed
       
  1079 
       
  1080 prove {* (Thm.term_of cgoal2) *}
       
  1081   apply (tactic {* LocalDefs.unfold_tac @{context} fset_defs *} )
       
  1082   apply (atomize(full))
       
  1083   apply (tactic {* foo_tac' @{context} 1 *})
       
  1084   done
       
  1085 
       
  1086 thm length_append (* Not true but worth checking that the goal is correct *)
       
  1087 ML {*
       
  1088   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm length_append}))
       
  1089   val goal = build_goal @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
  1090   val cgoal = cterm_of @{theory} goal
       
  1091   val cgoal2 = Thm.rhs_of (MetaSimplifier.rewrite false fset_defs_sym cgoal)
       
  1092 *}
       
  1093 prove {* Thm.term_of cgoal2 *}
       
  1094   apply (tactic {* LocalDefs.unfold_tac @{context} fset_defs *} )
       
  1095   apply (atomize(full))
       
  1096   apply (tactic {* foo_tac' @{context} 1 *})
       
  1097   sorry
       
  1098 
       
  1099 thm m2
       
  1100 ML {*
       
  1101   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm m2}))
       
  1102   val goal = build_goal @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
  1103   val cgoal = cterm_of @{theory} goal
       
  1104   val cgoal2 = Thm.rhs_of (MetaSimplifier.rewrite false fset_defs_sym cgoal)
       
  1105 *}
       
  1106 prove {* Thm.term_of cgoal2 *}
       
  1107   apply (tactic {* LocalDefs.unfold_tac @{context} fset_defs *} )
       
  1108   apply (atomize(full))
       
  1109   apply (tactic {* foo_tac' @{context} 1 *})
       
  1110   done
       
  1111 
       
  1112 thm list_eq.intros(4)
       
  1113 ML {*
       
  1114   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm list_eq.intros(4)}))
       
  1115   val goal = build_goal @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
  1116   val cgoal = cterm_of @{theory} goal
       
  1117   val cgoal2 = Thm.rhs_of (MetaSimplifier.rewrite false fset_defs_sym cgoal)
       
  1118   val cgoal3 = Thm.rhs_of (MetaSimplifier.rewrite true @{thms QUOT_TYPE_I_fset.thm10} cgoal2)
       
  1119 *}
       
  1120 
       
  1121 (* It is the same, but we need a name for it. *)
       
  1122 prove zzz : {* Thm.term_of cgoal3 *}
       
  1123   apply (tactic {* LocalDefs.unfold_tac @{context} fset_defs *} )
       
  1124   apply (atomize(full))
       
  1125   apply (tactic {* foo_tac' @{context} 1 *})
       
  1126   done
       
  1127 
       
  1128 lemma zzz' :
       
  1129   "(REP_fset (INSERT a (INSERT a (ABS_fset xs))) \<approx> REP_fset (INSERT a (ABS_fset xs)))"
       
  1130   using list_eq.intros(4) by (simp only: zzz)
       
  1131 
       
  1132 thm QUOT_TYPE_I_fset.REPS_same
       
  1133 ML {* val zzz'' = MetaSimplifier.rewrite_rule @{thms QUOT_TYPE_I_fset.REPS_same} @{thm zzz'} *}
       
  1134 
       
  1135 
       
  1136 thm list_eq.intros(5)
       
  1137 ML {*
       
  1138   val m1_novars = snd(no_vars ((Context.Theory @{theory}), @{thm list_eq.intros(5)}))
       
  1139   val goal = build_goal @{context} m1_novars consts @{typ "'a list"} @{typ "'a fset"} mk_rep mk_abs
       
  1140 *}
       
  1141 ML {*
       
  1142   val cgoal =
       
  1143     Toplevel.program (fn () =>
       
  1144       cterm_of @{theory} goal
       
  1145     )
       
  1146 *}
       
  1147 ML {*
       
  1148   val cgoal2 = Thm.rhs_of (MetaSimplifier.rewrite true fset_defs_sym cgoal)
       
  1149 *}
       
  1150 prove {* Thm.term_of cgoal2 *}
       
  1151   apply (tactic {* LocalDefs.unfold_tac @{context} fset_defs *} )
       
  1152   apply (atomize(full))
       
  1153   apply (tactic {* foo_tac' @{context} 1 *})
       
  1154   done
       
  1155 
  1159 
  1156 ML {* val li = Thm.freezeT (atomize_thm @{thm list.induct}) *}
  1160 ML {* val li = Thm.freezeT (atomize_thm @{thm list.induct}) *}
  1157 
  1161 
  1158 prove {*
  1162 prove {*
  1159  Logic.mk_implies
  1163  Logic.mk_implies
  1249 local_setup {* lift_theorem_fset @{binding "m1_lift"} @{thm m1} *}
  1253 local_setup {* lift_theorem_fset @{binding "m1_lift"} @{thm m1} *}
  1250 local_setup {* lift_theorem_fset @{binding "leqi4_lift"} @{thm list_eq.intros(4)} *}
  1254 local_setup {* lift_theorem_fset @{binding "leqi4_lift"} @{thm list_eq.intros(4)} *}
  1251 local_setup {* lift_theorem_fset @{binding "leqi5_lift"} @{thm list_eq.intros(5)} *}
  1255 local_setup {* lift_theorem_fset @{binding "leqi5_lift"} @{thm list_eq.intros(5)} *}
  1252 local_setup {* lift_theorem_fset @{binding "m2_lift"} @{thm m2} *}
  1256 local_setup {* lift_theorem_fset @{binding "m2_lift"} @{thm m2} *}
  1253 thm card1_suc_r
  1257 thm card1_suc_r
  1254 ML {* Toplevel.program (fn () => lift_theorem_fset @{binding "card_suc"} @{thm card1_suc_r} @{context}) *}
  1258 (* ML {* Toplevel.program (fn () => lift_theorem_fset @{binding "card_suc"} @{thm card1_suc_r} @{context}) *}*)
  1255 (*local_setup {* lift_theorem_fset @{binding "card_suc"} @{thm card1_suc} *}*)
  1259 (*local_setup {* lift_theorem_fset @{binding "card_suc"} @{thm card1_suc} *}*)
  1256 
  1260 
  1257 thm m1_lift
  1261 thm m1_lift
  1258 thm leqi4_lift
  1262 thm leqi4_lift
  1259 thm leqi5_lift
  1263 thm leqi5_lift