590 |
590 |
591 (*** specification of (co)inductive sets ****) |
591 (*** specification of (co)inductive sets ****) |
592 |
592 |
593 (** definitional introduction of (co)inductive sets **) |
593 (** definitional introduction of (co)inductive sets **) |
594 |
594 |
595 fun add_ind_def verbose declare_consts alt_name coind no_elim no_ind cs |
595 fun mk_ind_def declare_consts alt_name coind cs intr_ts monos con_defs thy |
596 atts intros monos con_defs thy params paramTs cTs cnames induct_cases = |
596 params paramTs cTs cnames = |
597 let |
597 let |
598 val _ = if verbose then message ("Proofs for " ^ coind_prefix coind ^ "inductive set(s) " ^ |
|
599 commas_quote cnames) else (); |
|
600 |
|
601 val sumT = fold_bal (fn (T, U) => Type ("+", [T, U])) cTs; |
598 val sumT = fold_bal (fn (T, U) => Type ("+", [T, U])) cTs; |
602 val setT = HOLogic.mk_setT sumT; |
599 val setT = HOLogic.mk_setT sumT; |
603 |
600 |
604 val fp_name = if coind then Sign.intern_const (Theory.sign_of Gfp.thy) "gfp" |
601 val fp_name = if coind then Sign.intern_const (Theory.sign_of Gfp.thy) "gfp" |
605 else Sign.intern_const (Theory.sign_of Lfp.thy) "lfp"; |
602 else Sign.intern_const (Theory.sign_of Lfp.thy) "lfp"; |
606 |
|
607 val ((intr_names, intr_ts), intr_atts) = apfst split_list (split_list intros); |
|
608 |
603 |
609 val used = foldr add_term_names (intr_ts, []); |
604 val used = foldr add_term_names (intr_ts, []); |
610 val [sname, xname] = variantlist (["S", "x"], used); |
605 val [sname, xname] = variantlist (["S", "x"], used); |
611 |
606 |
612 (* transform an introduction rule into a conjunction *) |
607 (* transform an introduction rule into a conjunction *) |
657 |> (if length cs < 2 then I |
652 |> (if length cs < 2 then I |
658 else Theory.add_consts_i [(rec_name, paramTs ---> setT, NoSyn)]) |
653 else Theory.add_consts_i [(rec_name, paramTs ---> setT, NoSyn)]) |
659 |> Theory.add_path rec_name |
654 |> Theory.add_path rec_name |
660 |> PureThy.add_defss_i [(("defs", def_terms), [])]; |
655 |> PureThy.add_defss_i [(("defs", def_terms), [])]; |
661 |
656 |
662 |
657 val mono = prove_mono setT fp_fun monos thy' |
663 (* prove and store theorems *) |
658 |
664 |
659 in |
665 val mono = prove_mono setT fp_fun monos thy'; |
660 (thy', mono, fp_def, rec_sets_defs, rec_const, sumT) |
|
661 end; |
|
662 |
|
663 fun add_ind_def verbose declare_consts alt_name coind no_elim no_ind cs |
|
664 atts intros monos con_defs thy params paramTs cTs cnames induct_cases = |
|
665 let |
|
666 val _ = if verbose then message ("Proofs for " ^ coind_prefix coind ^ "inductive set(s) " ^ |
|
667 commas_quote cnames) else (); |
|
668 |
|
669 val ((intr_names, intr_ts), intr_atts) = apfst split_list (split_list intros); |
|
670 |
|
671 val (thy', mono, fp_def, rec_sets_defs, rec_const, sumT) = |
|
672 mk_ind_def declare_consts alt_name coind cs intr_ts monos con_defs thy |
|
673 params paramTs cTs cnames; |
|
674 |
666 val (intrs, unfold) = prove_intrs coind mono fp_def intr_ts con_defs |
675 val (intrs, unfold) = prove_intrs coind mono fp_def intr_ts con_defs |
667 rec_sets_defs thy'; |
676 rec_sets_defs thy'; |
668 val elims = if no_elim then [] else |
677 val elims = if no_elim then [] else |
669 prove_elims cs cTs params intr_ts intr_names unfold rec_sets_defs thy'; |
678 prove_elims cs cTs params intr_ts intr_names unfold rec_sets_defs thy'; |
670 val raw_induct = if no_ind then Drule.asm_rl else |
679 val raw_induct = if no_ind then Drule.asm_rl else |
703 (** axiomatic introduction of (co)inductive sets **) |
712 (** axiomatic introduction of (co)inductive sets **) |
704 |
713 |
705 fun add_ind_axm verbose declare_consts alt_name coind no_elim no_ind cs |
714 fun add_ind_axm verbose declare_consts alt_name coind no_elim no_ind cs |
706 atts intros monos con_defs thy params paramTs cTs cnames induct_cases = |
715 atts intros monos con_defs thy params paramTs cTs cnames induct_cases = |
707 let |
716 let |
708 val rec_name = if alt_name = "" then space_implode "_" cnames else alt_name; |
717 val _ = message (coind_prefix coind ^ "inductive set(s) " ^ commas_quote cnames); |
709 |
718 |
710 val ((intr_names, intr_ts), intr_atts) = apfst split_list (split_list intros); |
719 val ((intr_names, intr_ts), intr_atts) = apfst split_list (split_list intros); |
|
720 val (thy', _, _, _, _, _) = |
|
721 mk_ind_def declare_consts alt_name coind cs intr_ts monos con_defs thy |
|
722 params paramTs cTs cnames; |
711 val (elim_ts, elim_cases) = Library.split_list (mk_elims cs cTs params intr_ts intr_names); |
723 val (elim_ts, elim_cases) = Library.split_list (mk_elims cs cTs params intr_ts intr_names); |
712 |
|
713 val (_, ind_prems, mutual_ind_concl) = mk_indrule cs cTs params intr_ts; |
724 val (_, ind_prems, mutual_ind_concl) = mk_indrule cs cTs params intr_ts; |
714 val ind_t = Logic.list_implies (ind_prems, mutual_ind_concl); |
725 val ind_t = Logic.list_implies (ind_prems, mutual_ind_concl); |
715 |
726 |
716 val thy' = |
727 val thy'' = |
717 thy |
728 thy' |
718 |> (if declare_consts then |
|
719 Theory.add_consts_i |
|
720 (map (fn (c, n) => (n, paramTs ---> fastype_of c, NoSyn)) (cs ~~ cnames)) |
|
721 else I) |
|
722 |> Theory.add_path rec_name |
|
723 |> (#1 o PureThy.add_axiomss_i [(("intrs", intr_ts), atts), (("raw_elims", elim_ts), [])]) |
729 |> (#1 o PureThy.add_axiomss_i [(("intrs", intr_ts), atts), (("raw_elims", elim_ts), [])]) |
724 |> (if coind then I else |
730 |> (if coind then I else |
725 #1 o PureThy.add_axioms_i [(("raw_induct", ind_t), [apsnd (standard o split_rule)])]); |
731 #1 o PureThy.add_axioms_i [(("raw_induct", ind_t), [apsnd (standard o split_rule)])]); |
726 |
732 |
727 val intrs = PureThy.get_thms thy' "intrs"; |
733 val intrs = PureThy.get_thms thy'' "intrs"; |
728 val elims = map2 (fn (th, cases) => RuleCases.name cases th) |
734 val elims = map2 (fn (th, cases) => RuleCases.name cases th) |
729 (PureThy.get_thms thy' "raw_elims", elim_cases); |
735 (PureThy.get_thms thy'' "raw_elims", elim_cases); |
730 val raw_induct = if coind then Drule.asm_rl else PureThy.get_thm thy' "raw_induct"; |
736 val raw_induct = if coind then Drule.asm_rl else PureThy.get_thm thy'' "raw_induct"; |
731 val induct = if coind orelse length cs > 1 then raw_induct |
737 val induct = if coind orelse length cs > 1 then raw_induct |
732 else standard (raw_induct RSN (2, rev_mp)); |
738 else standard (raw_induct RSN (2, rev_mp)); |
733 |
739 |
734 val (thy'', ([elims'], intrs')) = |
740 val (thy''', ([elims'], intrs')) = |
735 thy' |
741 thy'' |
736 |> PureThy.add_thmss [(("elims", elims), [])] |
742 |> PureThy.add_thmss [(("elims", elims), [])] |
737 |>> (if coind then I |
743 |>> (if coind then I |
738 else #1 o PureThy.add_thms [(("induct", induct), [RuleCases.case_names induct_cases])]) |
744 else #1 o PureThy.add_thms [(("induct", induct), [RuleCases.case_names induct_cases])]) |
739 |>>> PureThy.add_thms ((intr_names ~~ intrs) ~~ intr_atts) |
745 |>>> PureThy.add_thms ((intr_names ~~ intrs) ~~ intr_atts) |
740 |>> Theory.parent_path; |
746 |>> Theory.parent_path; |
741 val induct' = if coind then raw_induct else PureThy.get_thm thy'' "induct"; |
747 val induct' = if coind then raw_induct else PureThy.get_thm thy''' "induct"; |
742 in (thy'', |
748 in (thy''', |
743 {defs = [], |
749 {defs = [], |
744 mono = Drule.asm_rl, |
750 mono = Drule.asm_rl, |
745 unfold = Drule.asm_rl, |
751 unfold = Drule.asm_rl, |
746 intrs = intrs', |
752 intrs = intrs', |
747 elims = elims', |
753 elims = elims', |