src/HOL/Tools/inductive_package.ML
changeset 9072 a4896cf23638
parent 8720 840c75ab2a7f
child 9116 9df44b5c610b
equal deleted inserted replaced
9071:6416d5a5f712 9072:a4896cf23638
   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',