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 |