209 val ns = map length ctr_Tsss; |
209 val ns = map length ctr_Tsss; |
210 val kss = map (fn n => 1 upto n) ns; |
210 val kss = map (fn n => 1 upto n) ns; |
211 val mss = map (map length) ctr_Tsss; |
211 val mss = map (map length) ctr_Tsss; |
212 val Css = map2 replicate ns Cs; |
212 val Css = map2 replicate ns Cs; |
213 |
213 |
214 fun mk_iter_like Ts Us t = |
214 fun mk_rec_like Ts Us t = |
215 let |
215 let |
216 val (bindings, body) = strip_type (fastype_of t); |
216 val (bindings, body) = strip_type (fastype_of t); |
217 val (f_Us, prebody) = split_last bindings; |
217 val (f_Us, prebody) = split_last bindings; |
218 val Type (_, Ts0) = if lfp then prebody else body; |
218 val Type (_, Ts0) = if lfp then prebody else body; |
219 val Us0 = distinct (op =) (map (if lfp then body_type else domain_type) f_Us); |
219 val Us0 = distinct (op =) (map (if lfp then body_type else domain_type) f_Us); |
220 in |
220 in |
221 Term.subst_atomic_types (Ts0 @ Us0 ~~ Ts @ Us) t |
221 Term.subst_atomic_types (Ts0 @ Us0 ~~ Ts @ Us) t |
222 end; |
222 end; |
223 |
223 |
224 val fp_iters as fp_iter1 :: _ = map (mk_iter_like As Cs) fp_iters0; |
224 val fp_folds as fp_fold1 :: _ = map (mk_rec_like As Cs) fp_folds0; |
225 val fp_recs as fp_rec1 :: _ = map (mk_iter_like As Cs) fp_recs0; |
225 val fp_recs as fp_rec1 :: _ = map (mk_rec_like As Cs) fp_recs0; |
226 |
226 |
227 val fp_iter_fun_Ts = fst (split_last (binder_types (fastype_of fp_iter1))); |
227 val fp_fold_fun_Ts = fst (split_last (binder_types (fastype_of fp_fold1))); |
228 val fp_rec_fun_Ts = fst (split_last (binder_types (fastype_of fp_rec1))); |
228 val fp_rec_fun_Ts = fst (split_last (binder_types (fastype_of fp_rec1))); |
229 |
229 |
230 val (((iter_only as (gss, _, _), rec_only as (hss, _, _)), |
230 val (((fold_only as (gss, _, _), rec_only as (hss, _, _)), |
231 (zs, cs, cpss, coiter_only as ((pgss, crgsss), _), corec_only as ((phss, cshsss), _))), |
231 (zs, cs, cpss, unfold_only as ((pgss, crgsss), _), corec_only as ((phss, cshsss), _))), |
232 names_lthy) = |
232 names_lthy) = |
233 if lfp then |
233 if lfp then |
234 let |
234 let |
235 val y_Tsss = |
235 val y_Tsss = |
236 map3 (fn n => fn ms => map2 dest_tupleT ms o dest_sumTN_balanced n o domain_type) |
236 map3 (fn n => fn ms => map2 dest_tupleT ms o dest_sumTN_balanced n o domain_type) |
237 ns mss fp_iter_fun_Ts; |
237 ns mss fp_fold_fun_Ts; |
238 val g_Tss = map2 (map2 (curry (op --->))) y_Tsss Css; |
238 val g_Tss = map2 (map2 (curry (op --->))) y_Tsss Css; |
239 |
239 |
240 val ((gss, ysss), lthy) = |
240 val ((gss, ysss), lthy) = |
241 lthy |
241 lthy |
242 |> mk_Freess "f" g_Tss |
242 |> mk_Freess "f" g_Tss |
411 map3 (fn k => fn m => fn ctr_def => fn {context = ctxt, ...} => |
411 map3 (fn k => fn m => fn ctr_def => fn {context = ctxt, ...} => |
412 mk_case_tac ctxt n k m case_def ctr_def dtor_ctor) ks ms ctr_defs; |
412 mk_case_tac ctxt n k m case_def ctr_def dtor_ctor) ks ms ctr_defs; |
413 |
413 |
414 val tacss = [exhaust_tac] :: inject_tacss @ half_distinct_tacss @ [case_tacs]; |
414 val tacss = [exhaust_tac] :: inject_tacss @ half_distinct_tacss @ [case_tacs]; |
415 |
415 |
416 fun define_iter_rec (wrap_res, no_defs_lthy) = |
416 fun define_fold_rec (wrap_res, no_defs_lthy) = |
417 let |
417 let |
418 val fpT_to_C = fpT --> C; |
418 val fpT_to_C = fpT --> C; |
419 |
419 |
420 fun generate_iter_like (suf, fp_iter_like, (fss, f_Tss, xssss)) = |
420 fun generate_rec_like (suf, fp_rec_like, (fss, f_Tss, xssss)) = |
421 let |
421 let |
422 val res_T = fold_rev (curry (op --->)) f_Tss fpT_to_C; |
422 val res_T = fold_rev (curry (op --->)) f_Tss fpT_to_C; |
423 val binding = Binding.suffix_name ("_" ^ suf) fp_b; |
423 val binding = Binding.suffix_name ("_" ^ suf) fp_b; |
424 val spec = |
424 val spec = |
425 mk_Trueprop_eq (lists_bmoc fss (Free (Binding.name_of binding, res_T)), |
425 mk_Trueprop_eq (lists_bmoc fss (Free (Binding.name_of binding, res_T)), |
426 Term.list_comb (fp_iter_like, |
426 Term.list_comb (fp_rec_like, |
427 map2 (mk_sum_caseN_balanced oo map2 mk_uncurried2_fun) fss xssss)); |
427 map2 (mk_sum_caseN_balanced oo map2 mk_uncurried2_fun) fss xssss)); |
428 in (binding, spec) end; |
428 in (binding, spec) end; |
429 |
429 |
430 val iter_like_infos = |
430 val rec_like_infos = |
431 [(iterN, fp_iter, iter_only), |
431 [(foldN, fp_fold, fold_only), |
432 (recN, fp_rec, rec_only)]; |
432 (recN, fp_rec, rec_only)]; |
433 |
433 |
434 val (bindings, specs) = map generate_iter_like iter_like_infos |> split_list; |
434 val (bindings, specs) = map generate_rec_like rec_like_infos |> split_list; |
435 |
435 |
436 val ((csts, defs), (lthy', lthy)) = no_defs_lthy |
436 val ((csts, defs), (lthy', lthy)) = no_defs_lthy |
437 |> apfst split_list o fold_map2 (fn b => fn spec => |
437 |> apfst split_list o fold_map2 (fn b => fn spec => |
438 Specification.definition (SOME (b, NONE, NoSyn), ((Thm.def_binding b, []), spec)) |
438 Specification.definition (SOME (b, NONE, NoSyn), ((Thm.def_binding b, []), spec)) |
439 #>> apsnd snd) bindings specs |
439 #>> apsnd snd) bindings specs |
440 ||> `Local_Theory.restore; |
440 ||> `Local_Theory.restore; |
441 |
441 |
442 val phi = Proof_Context.export_morphism lthy lthy'; |
442 val phi = Proof_Context.export_morphism lthy lthy'; |
443 |
443 |
444 val [iter_def, rec_def] = map (Morphism.thm phi) defs; |
444 val [fold_def, rec_def] = map (Morphism.thm phi) defs; |
445 |
445 |
446 val [iterx, recx] = map (mk_iter_like As Cs o Morphism.term phi) csts; |
446 val [foldx, recx] = map (mk_rec_like As Cs o Morphism.term phi) csts; |
447 in |
447 in |
448 ((wrap_res, ctrs, iterx, recx, xss, ctr_defs, iter_def, rec_def), lthy) |
448 ((wrap_res, ctrs, foldx, recx, xss, ctr_defs, fold_def, rec_def), lthy) |
449 end; |
449 end; |
450 |
450 |
451 fun define_coiter_corec (wrap_res, no_defs_lthy) = |
451 fun define_unfold_corec (wrap_res, no_defs_lthy) = |
452 let |
452 let |
453 val B_to_fpT = C --> fpT; |
453 val B_to_fpT = C --> fpT; |
454 |
454 |
455 fun mk_preds_getterss_join c n cps sum_prod_T cqfss = |
455 fun mk_preds_getterss_join c n cps sum_prod_T cqfss = |
456 Term.lambda c (mk_IfN sum_prod_T cps |
456 Term.lambda c (mk_IfN sum_prod_T cps |
457 (map2 (mk_InN_balanced sum_prod_T n) (map HOLogic.mk_tuple cqfss) (1 upto n))); |
457 (map2 (mk_InN_balanced sum_prod_T n) (map HOLogic.mk_tuple cqfss) (1 upto n))); |
458 |
458 |
459 fun generate_coiter_like (suf, fp_iter_like, ((pfss, cqfsss), (f_sum_prod_Ts, |
459 fun generate_corec_like (suf, fp_rec_like, ((pfss, cqfsss), (f_sum_prod_Ts, |
460 pf_Tss))) = |
460 pf_Tss))) = |
461 let |
461 let |
462 val res_T = fold_rev (curry (op --->)) pf_Tss B_to_fpT; |
462 val res_T = fold_rev (curry (op --->)) pf_Tss B_to_fpT; |
463 val binding = Binding.suffix_name ("_" ^ suf) fp_b; |
463 val binding = Binding.suffix_name ("_" ^ suf) fp_b; |
464 val spec = |
464 val spec = |
465 mk_Trueprop_eq (lists_bmoc pfss (Free (Binding.name_of binding, res_T)), |
465 mk_Trueprop_eq (lists_bmoc pfss (Free (Binding.name_of binding, res_T)), |
466 Term.list_comb (fp_iter_like, |
466 Term.list_comb (fp_rec_like, |
467 map5 mk_preds_getterss_join cs ns cpss f_sum_prod_Ts cqfsss)); |
467 map5 mk_preds_getterss_join cs ns cpss f_sum_prod_Ts cqfsss)); |
468 in (binding, spec) end; |
468 in (binding, spec) end; |
469 |
469 |
470 val coiter_like_infos = |
470 val corec_like_infos = |
471 [(coiterN, fp_iter, coiter_only), |
471 [(unfoldN, fp_fold, unfold_only), |
472 (corecN, fp_rec, corec_only)]; |
472 (corecN, fp_rec, corec_only)]; |
473 |
473 |
474 val (bindings, specs) = map generate_coiter_like coiter_like_infos |> split_list; |
474 val (bindings, specs) = map generate_corec_like corec_like_infos |> split_list; |
475 |
475 |
476 val ((csts, defs), (lthy', lthy)) = no_defs_lthy |
476 val ((csts, defs), (lthy', lthy)) = no_defs_lthy |
477 |> apfst split_list o fold_map2 (fn b => fn spec => |
477 |> apfst split_list o fold_map2 (fn b => fn spec => |
478 Specification.definition (SOME (b, NONE, NoSyn), ((Thm.def_binding b, []), spec)) |
478 Specification.definition (SOME (b, NONE, NoSyn), ((Thm.def_binding b, []), spec)) |
479 #>> apsnd snd) bindings specs |
479 #>> apsnd snd) bindings specs |
480 ||> `Local_Theory.restore; |
480 ||> `Local_Theory.restore; |
481 |
481 |
482 val phi = Proof_Context.export_morphism lthy lthy'; |
482 val phi = Proof_Context.export_morphism lthy lthy'; |
483 |
483 |
484 val [coiter_def, corec_def] = map (Morphism.thm phi) defs; |
484 val [unfold_def, corec_def] = map (Morphism.thm phi) defs; |
485 |
485 |
486 val [coiter, corec] = map (mk_iter_like As Cs o Morphism.term phi) csts; |
486 val [unfold, corec] = map (mk_rec_like As Cs o Morphism.term phi) csts; |
487 in |
487 in |
488 ((wrap_res, ctrs, coiter, corec, xss, ctr_defs, coiter_def, corec_def), lthy) |
488 ((wrap_res, ctrs, unfold, corec, xss, ctr_defs, unfold_def, corec_def), lthy) |
489 end; |
489 end; |
490 |
490 |
491 fun wrap lthy = |
491 fun wrap lthy = |
492 let val sel_defaultss = map (map (apsnd (prepare_term lthy))) raw_sel_defaultss in |
492 let val sel_defaultss = map (map (apsnd (prepare_term lthy))) raw_sel_defaultss in |
493 wrap_datatype tacss (((no_dests, ctrs0), casex0), (disc_bindings, (sel_bindingss, |
493 wrap_datatype tacss (((no_dests, ctrs0), casex0), (disc_bindings, (sel_bindingss, |
494 sel_defaultss))) lthy |
494 sel_defaultss))) lthy |
495 end; |
495 end; |
496 |
496 |
497 val define_iter_likes = if lfp then define_iter_rec else define_coiter_corec; |
497 val define_rec_likes = if lfp then define_fold_rec else define_unfold_corec; |
498 in |
498 in |
499 ((wrap, define_iter_likes), lthy') |
499 ((wrap, define_rec_likes), lthy') |
500 end; |
500 end; |
501 |
501 |
502 val pre_map_defs = map map_def_of_bnf pre_bnfs; |
502 val pre_map_defs = map map_def_of_bnf pre_bnfs; |
503 val pre_set_defss = map set_defs_of_bnf pre_bnfs; |
503 val pre_set_defss = map set_defs_of_bnf pre_bnfs; |
504 val nested_set_natural's = maps set_natural'_of_bnf nested_bnfs; |
504 val nested_set_natural's = maps set_natural'_of_bnf nested_bnfs; |
613 end; |
613 end; |
614 |
614 |
615 (* TODO: Generate nicer names in case of clashes *) |
615 (* TODO: Generate nicer names in case of clashes *) |
616 val induct_cases = Datatype_Prop.indexify_names (maps (map base_name_of_ctr) ctrss); |
616 val induct_cases = Datatype_Prop.indexify_names (maps (map base_name_of_ctr) ctrss); |
617 |
617 |
618 val (iter_thmss, rec_thmss) = |
618 val (fold_thmss, rec_thmss) = |
619 let |
619 let |
620 val xctrss = map2 (map2 (curry Term.list_comb)) ctrss xsss; |
620 val xctrss = map2 (map2 (curry Term.list_comb)) ctrss xsss; |
621 val giters = map (lists_bmoc gss) iters; |
621 val gfolds = map (lists_bmoc gss) folds; |
622 val hrecs = map (lists_bmoc hss) recs; |
622 val hrecs = map (lists_bmoc hss) recs; |
623 |
623 |
624 fun mk_goal fss fiter_like xctr f xs fxs = |
624 fun mk_goal fss frec_like xctr f xs fxs = |
625 fold_rev (fold_rev Logic.all) (xs :: fss) |
625 fold_rev (fold_rev Logic.all) (xs :: fss) |
626 (mk_Trueprop_eq (fiter_like $ xctr, Term.list_comb (f, fxs))); |
626 (mk_Trueprop_eq (frec_like $ xctr, Term.list_comb (f, fxs))); |
627 |
627 |
628 fun build_call fiter_likes maybe_tick (T, U) = |
628 fun build_call frec_likes maybe_tick (T, U) = |
629 if T = U then |
629 if T = U then |
630 id_const T |
630 id_const T |
631 else |
631 else |
632 (case find_index (curry (op =) T) fpTs of |
632 (case find_index (curry (op =) T) fpTs of |
633 ~1 => build_map (build_call fiter_likes maybe_tick) T U |
633 ~1 => build_map (build_call frec_likes maybe_tick) T U |
634 | j => maybe_tick (nth us j) (nth fiter_likes j)); |
634 | j => maybe_tick (nth us j) (nth frec_likes j)); |
635 |
635 |
636 fun mk_U maybe_mk_prodT = |
636 fun mk_U maybe_mk_prodT = |
637 typ_subst (map2 (fn fpT => fn C => (fpT, maybe_mk_prodT fpT C)) fpTs Cs); |
637 typ_subst (map2 (fn fpT => fn C => (fpT, maybe_mk_prodT fpT C)) fpTs Cs); |
638 |
638 |
639 fun intr_calls fiter_likes maybe_cons maybe_tick maybe_mk_prodT (x as Free (_, T)) = |
639 fun intr_calls frec_likes maybe_cons maybe_tick maybe_mk_prodT (x as Free (_, T)) = |
640 if member (op =) fpTs T then |
640 if member (op =) fpTs T then |
641 maybe_cons x [build_call fiter_likes (K I) (T, mk_U (K I) T) $ x] |
641 maybe_cons x [build_call frec_likes (K I) (T, mk_U (K I) T) $ x] |
642 else if exists_fp_subtype T then |
642 else if exists_fp_subtype T then |
643 [build_call fiter_likes maybe_tick (T, mk_U maybe_mk_prodT T) $ x] |
643 [build_call frec_likes maybe_tick (T, mk_U maybe_mk_prodT T) $ x] |
644 else |
644 else |
645 [x]; |
645 [x]; |
646 |
646 |
647 val gxsss = map (map (maps (intr_calls giters (K I) (K I) (K I)))) xsss; |
647 val gxsss = map (map (maps (intr_calls gfolds (K I) (K I) (K I)))) xsss; |
648 val hxsss = map (map (maps (intr_calls hrecs cons tick (curry HOLogic.mk_prodT)))) xsss; |
648 val hxsss = map (map (maps (intr_calls hrecs cons tick (curry HOLogic.mk_prodT)))) xsss; |
649 |
649 |
650 val iter_goalss = map5 (map4 o mk_goal gss) giters xctrss gss xsss gxsss; |
650 val fold_goalss = map5 (map4 o mk_goal gss) gfolds xctrss gss xsss gxsss; |
651 val rec_goalss = map5 (map4 o mk_goal hss) hrecs xctrss hss xsss hxsss; |
651 val rec_goalss = map5 (map4 o mk_goal hss) hrecs xctrss hss xsss hxsss; |
652 |
652 |
653 val iter_tacss = |
653 val fold_tacss = |
654 map2 (map o mk_iter_like_tac pre_map_defs nesting_map_ids iter_defs) fp_iter_thms |
654 map2 (map o mk_rec_like_tac pre_map_defs nesting_map_ids fold_defs) fp_fold_thms |
655 ctr_defss; |
655 ctr_defss; |
656 val rec_tacss = |
656 val rec_tacss = |
657 map2 (map o mk_iter_like_tac pre_map_defs nesting_map_ids rec_defs) fp_rec_thms |
657 map2 (map o mk_rec_like_tac pre_map_defs nesting_map_ids rec_defs) fp_rec_thms |
658 ctr_defss; |
658 ctr_defss; |
659 |
659 |
660 fun prove goal tac = Skip_Proof.prove lthy [] [] goal (tac o #context); |
660 fun prove goal tac = Skip_Proof.prove lthy [] [] goal (tac o #context); |
661 in |
661 in |
662 (map2 (map2 prove) iter_goalss iter_tacss, |
662 (map2 (map2 prove) fold_goalss fold_tacss, |
663 map2 (map2 prove) rec_goalss rec_tacss) |
663 map2 (map2 prove) rec_goalss rec_tacss) |
664 end; |
664 end; |
665 |
665 |
666 val simp_thmss = mk_simp_thmss wrap_ress rec_thmss iter_thmss; |
666 val simp_thmss = mk_simp_thmss wrap_ress rec_thmss fold_thmss; |
667 |
667 |
668 val induct_case_names_attr = Attrib.internal (K (Rule_Cases.case_names induct_cases)); |
668 val induct_case_names_attr = Attrib.internal (K (Rule_Cases.case_names induct_cases)); |
669 fun induct_type_attr T_name = Attrib.internal (K (Induct.induct_type T_name)); |
669 fun induct_type_attr T_name = Attrib.internal (K (Induct.induct_type T_name)); |
670 |
670 |
671 (* TODO: Also note "recs", "simps", and "splits" if "nn > 1" (for compatibility with the |
671 (* TODO: Also note "recs", "simps", and "splits" if "nn > 1" (for compatibility with the |
676 ((Binding.qualify true fp_common_name (Binding.name thmN), attrs), [(thms, [])])); |
676 ((Binding.qualify true fp_common_name (Binding.name thmN), attrs), [(thms, [])])); |
677 |
677 |
678 val notes = |
678 val notes = |
679 [(inductN, map single induct_thms, |
679 [(inductN, map single induct_thms, |
680 fn T_name => [induct_case_names_attr, induct_type_attr T_name]), |
680 fn T_name => [induct_case_names_attr, induct_type_attr T_name]), |
681 (itersN, iter_thmss, K (Code.add_default_eqn_attrib :: simp_attrs)), |
681 (foldsN, fold_thmss, K (Code.add_default_eqn_attrib :: simp_attrs)), |
682 (recsN, rec_thmss, K (Code.add_default_eqn_attrib :: simp_attrs)), |
682 (recsN, rec_thmss, K (Code.add_default_eqn_attrib :: simp_attrs)), |
683 (simpsN, simp_thmss, K [])] |
683 (simpsN, simp_thmss, K [])] |
684 |> maps (fn (thmN, thmss, attrs) => |
684 |> maps (fn (thmN, thmss, attrs) => |
685 map3 (fn b => fn Type (T_name, _) => fn thms => |
685 map3 (fn b => fn Type (T_name, _) => fn thms => |
686 ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), attrs T_name), |
686 ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), attrs T_name), |
687 [(thms, [])])) fp_bs fpTs thmss); |
687 [(thms, [])])) fp_bs fpTs thmss); |
688 in |
688 in |
689 lthy |> Local_Theory.notes (common_notes @ notes) |> snd |
689 lthy |> Local_Theory.notes (common_notes @ notes) |> snd |
690 end; |
690 end; |
691 |
691 |
692 fun derive_coinduct_coiter_corec_thms_for_types ((wrap_ress, ctrss, coiters, corecs, _, |
692 fun derive_coinduct_unfold_corec_thms_for_types ((wrap_ress, ctrss, unfolds, corecs, _, |
693 ctr_defss, coiter_defs, corec_defs), lthy) = |
693 ctr_defss, unfold_defs, corec_defs), lthy) = |
694 let |
694 let |
695 val discss = map (map (mk_disc_or_sel As) o #1) wrap_ress; |
695 val discss = map (map (mk_disc_or_sel As) o #1) wrap_ress; |
696 val selsss = map #2 wrap_ress; |
696 val selsss = map #2 wrap_ress; |
697 val disc_thmsss = map #6 wrap_ress; |
697 val disc_thmsss = map #6 wrap_ress; |
698 val discIss = map #7 wrap_ress; |
698 val discIss = map #7 wrap_ress; |
712 end; |
712 end; |
713 |
713 |
714 fun mk_maybe_not pos = not pos ? HOLogic.mk_not; |
714 fun mk_maybe_not pos = not pos ? HOLogic.mk_not; |
715 |
715 |
716 val z = the_single zs; |
716 val z = the_single zs; |
717 val gcoiters = map (lists_bmoc pgss) coiters; |
717 val gunfolds = map (lists_bmoc pgss) unfolds; |
718 val hcorecs = map (lists_bmoc phss) corecs; |
718 val hcorecs = map (lists_bmoc phss) corecs; |
719 |
719 |
720 val (coiter_thmss, corec_thmss, safe_coiter_thmss, safe_corec_thmss) = |
720 val (unfold_thmss, corec_thmss, safe_unfold_thmss, safe_corec_thmss) = |
721 let |
721 let |
722 fun mk_goal pfss c cps fcoiter_like n k ctr m cfs' = |
722 fun mk_goal pfss c cps fcorec_like n k ctr m cfs' = |
723 fold_rev (fold_rev Logic.all) ([c] :: pfss) |
723 fold_rev (fold_rev Logic.all) ([c] :: pfss) |
724 (Logic.list_implies (seq_conds (HOLogic.mk_Trueprop oo mk_maybe_not) n k cps, |
724 (Logic.list_implies (seq_conds (HOLogic.mk_Trueprop oo mk_maybe_not) n k cps, |
725 mk_Trueprop_eq (fcoiter_like $ c, Term.list_comb (ctr, take m cfs')))); |
725 mk_Trueprop_eq (fcorec_like $ c, Term.list_comb (ctr, take m cfs')))); |
726 |
726 |
727 fun build_call fiter_likes maybe_tack (T, U) = |
727 fun build_call frec_likes maybe_tack (T, U) = |
728 if T = U then |
728 if T = U then |
729 id_const T |
729 id_const T |
730 else |
730 else |
731 (case find_index (curry (op =) U) fpTs of |
731 (case find_index (curry (op =) U) fpTs of |
732 ~1 => build_map (build_call fiter_likes maybe_tack) T U |
732 ~1 => build_map (build_call frec_likes maybe_tack) T U |
733 | j => maybe_tack (nth cs j, nth us j) (nth fiter_likes j)); |
733 | j => maybe_tack (nth cs j, nth us j) (nth frec_likes j)); |
734 |
734 |
735 fun mk_U maybe_mk_sumT = |
735 fun mk_U maybe_mk_sumT = |
736 typ_subst (map2 (fn C => fn fpT => (maybe_mk_sumT fpT C, fpT)) Cs fpTs); |
736 typ_subst (map2 (fn C => fn fpT => (maybe_mk_sumT fpT C, fpT)) Cs fpTs); |
737 |
737 |
738 fun intr_calls fiter_likes maybe_mk_sumT maybe_tack cqf = |
738 fun intr_calls frec_likes maybe_mk_sumT maybe_tack cqf = |
739 let val T = fastype_of cqf in |
739 let val T = fastype_of cqf in |
740 if exists_subtype (member (op =) Cs) T then |
740 if exists_subtype (member (op =) Cs) T then |
741 build_call fiter_likes maybe_tack (T, mk_U maybe_mk_sumT T) $ cqf |
741 build_call frec_likes maybe_tack (T, mk_U maybe_mk_sumT T) $ cqf |
742 else |
742 else |
743 cqf |
743 cqf |
744 end; |
744 end; |
745 |
745 |
746 val crgsss' = map (map (map (intr_calls gcoiters (K I) (K I)))) crgsss; |
746 val crgsss' = map (map (map (intr_calls gunfolds (K I) (K I)))) crgsss; |
747 val cshsss' = map (map (map (intr_calls hcorecs (curry mk_sumT) (tack z)))) cshsss; |
747 val cshsss' = map (map (map (intr_calls hcorecs (curry mk_sumT) (tack z)))) cshsss; |
748 |
748 |
749 val coiter_goalss = |
749 val unfold_goalss = |
750 map8 (map4 oooo mk_goal pgss) cs cpss gcoiters ns kss ctrss mss crgsss'; |
750 map8 (map4 oooo mk_goal pgss) cs cpss gunfolds ns kss ctrss mss crgsss'; |
751 val corec_goalss = |
751 val corec_goalss = |
752 map8 (map4 oooo mk_goal phss) cs cpss hcorecs ns kss ctrss mss cshsss'; |
752 map8 (map4 oooo mk_goal phss) cs cpss hcorecs ns kss ctrss mss cshsss'; |
753 |
753 |
754 val coiter_tacss = |
754 val unfold_tacss = |
755 map3 (map oo mk_coiter_like_tac coiter_defs nesting_map_ids) fp_iter_thms pre_map_defs |
755 map3 (map oo mk_corec_like_tac unfold_defs nesting_map_ids) fp_fold_thms pre_map_defs |
756 ctr_defss; |
756 ctr_defss; |
757 val corec_tacss = |
757 val corec_tacss = |
758 map3 (map oo mk_coiter_like_tac corec_defs nesting_map_ids) fp_rec_thms pre_map_defs |
758 map3 (map oo mk_corec_like_tac corec_defs nesting_map_ids) fp_rec_thms pre_map_defs |
759 ctr_defss; |
759 ctr_defss; |
760 |
760 |
761 fun prove goal tac = |
761 fun prove goal tac = |
762 Skip_Proof.prove lthy [] [] goal (tac o #context) |> Thm.close_derivation; |
762 Skip_Proof.prove lthy [] [] goal (tac o #context) |> Thm.close_derivation; |
763 |
763 |
764 val coiter_thmss = map2 (map2 prove) coiter_goalss coiter_tacss; |
764 val unfold_thmss = map2 (map2 prove) unfold_goalss unfold_tacss; |
765 val corec_thmss = |
765 val corec_thmss = |
766 map2 (map2 prove) corec_goalss corec_tacss |
766 map2 (map2 prove) corec_goalss corec_tacss |
767 |> map (map (unfold_defs lthy @{thms sum_case_if})); |
767 |> map (map (unfold_thms lthy @{thms sum_case_if})); |
768 |
768 |
769 val coiter_safesss = map2 (map2 (map2 (curry (op =)))) crgsss' crgsss; |
769 val unfold_safesss = map2 (map2 (map2 (curry (op =)))) crgsss' crgsss; |
770 val corec_safesss = map2 (map2 (map2 (curry (op =)))) cshsss' cshsss; |
770 val corec_safesss = map2 (map2 (map2 (curry (op =)))) cshsss' cshsss; |
771 |
771 |
772 val filter_safesss = |
772 val filter_safesss = |
773 map2 (map_filter (fn (safes, thm) => if forall I safes then SOME thm else NONE) oo |
773 map2 (map_filter (fn (safes, thm) => if forall I safes then SOME thm else NONE) oo |
774 curry (op ~~)); |
774 curry (op ~~)); |
775 |
775 |
776 val safe_coiter_thmss = filter_safesss coiter_safesss coiter_thmss; |
776 val safe_unfold_thmss = filter_safesss unfold_safesss unfold_thmss; |
777 val safe_corec_thmss = filter_safesss corec_safesss corec_thmss; |
777 val safe_corec_thmss = filter_safesss corec_safesss corec_thmss; |
778 in |
778 in |
779 (coiter_thmss, corec_thmss, safe_coiter_thmss, safe_corec_thmss) |
779 (unfold_thmss, corec_thmss, safe_unfold_thmss, safe_corec_thmss) |
780 end; |
780 end; |
781 |
781 |
782 val (disc_coiter_iff_thmss, disc_corec_iff_thmss) = |
782 val (disc_unfold_iff_thmss, disc_corec_iff_thmss) = |
783 let |
783 let |
784 fun mk_goal c cps fcoiter_like n k disc = |
784 fun mk_goal c cps fcorec_like n k disc = |
785 mk_Trueprop_eq (disc $ (fcoiter_like $ c), |
785 mk_Trueprop_eq (disc $ (fcorec_like $ c), |
786 if n = 1 then @{const True} |
786 if n = 1 then @{const True} |
787 else Library.foldr1 HOLogic.mk_conj (seq_conds mk_maybe_not n k cps)); |
787 else Library.foldr1 HOLogic.mk_conj (seq_conds mk_maybe_not n k cps)); |
788 |
788 |
789 val coiter_goalss = map6 (map2 oooo mk_goal) cs cpss gcoiters ns kss discss; |
789 val unfold_goalss = map6 (map2 oooo mk_goal) cs cpss gunfolds ns kss discss; |
790 val corec_goalss = map6 (map2 oooo mk_goal) cs cpss hcorecs ns kss discss; |
790 val corec_goalss = map6 (map2 oooo mk_goal) cs cpss hcorecs ns kss discss; |
791 |
791 |
792 fun mk_case_split' cp = |
792 fun mk_case_split' cp = |
793 Drule.instantiate' [] [SOME (certify lthy cp)] @{thm case_split}; |
793 Drule.instantiate' [] [SOME (certify lthy cp)] @{thm case_split}; |
794 |
794 |
795 val case_splitss' = map (map mk_case_split') cpss; |
795 val case_splitss' = map (map mk_case_split') cpss; |
796 |
796 |
797 val coiter_tacss = |
797 val unfold_tacss = |
798 map3 (map oo mk_disc_coiter_like_iff_tac) case_splitss' coiter_thmss disc_thmsss; |
798 map3 (map oo mk_disc_corec_like_iff_tac) case_splitss' unfold_thmss disc_thmsss; |
799 val corec_tacss = |
799 val corec_tacss = |
800 map3 (map oo mk_disc_coiter_like_iff_tac) case_splitss' corec_thmss disc_thmsss; |
800 map3 (map oo mk_disc_corec_like_iff_tac) case_splitss' corec_thmss disc_thmsss; |
801 |
801 |
802 fun prove goal tac = |
802 fun prove goal tac = |
803 Skip_Proof.prove lthy [] [] goal (tac o #context) |
803 Skip_Proof.prove lthy [] [] goal (tac o #context) |
804 |> Thm.close_derivation |
804 |> Thm.close_derivation |
805 |> singleton (Proof_Context.export names_lthy no_defs_lthy); |
805 |> singleton (Proof_Context.export names_lthy no_defs_lthy); |
806 |
806 |
807 fun proves [_] [_] = [] |
807 fun proves [_] [_] = [] |
808 | proves goals tacs = map2 prove goals tacs; |
808 | proves goals tacs = map2 prove goals tacs; |
809 in |
809 in |
810 (map2 proves coiter_goalss coiter_tacss, |
810 (map2 proves unfold_goalss unfold_tacss, |
811 map2 proves corec_goalss corec_tacss) |
811 map2 proves corec_goalss corec_tacss) |
812 end; |
812 end; |
813 |
813 |
814 fun mk_disc_coiter_like_thms coiter_likes discIs = |
814 fun mk_disc_corec_like_thms corec_likes discIs = |
815 map (op RS) (filter_out (is_triv_implies o snd) (coiter_likes ~~ discIs)); |
815 map (op RS) (filter_out (is_triv_implies o snd) (corec_likes ~~ discIs)); |
816 |
816 |
817 val disc_coiter_thmss = map2 mk_disc_coiter_like_thms coiter_thmss discIss; |
817 val disc_unfold_thmss = map2 mk_disc_corec_like_thms unfold_thmss discIss; |
818 val disc_corec_thmss = map2 mk_disc_coiter_like_thms corec_thmss discIss; |
818 val disc_corec_thmss = map2 mk_disc_corec_like_thms corec_thmss discIss; |
819 |
819 |
820 fun mk_sel_coiter_like_thm coiter_like_thm sel sel_thm = |
820 fun mk_sel_corec_like_thm corec_like_thm sel sel_thm = |
821 let |
821 let |
822 val (domT, ranT) = dest_funT (fastype_of sel); |
822 val (domT, ranT) = dest_funT (fastype_of sel); |
823 val arg_cong' = |
823 val arg_cong' = |
824 Drule.instantiate' (map (SOME o certifyT lthy) [domT, ranT]) |
824 Drule.instantiate' (map (SOME o certifyT lthy) [domT, ranT]) |
825 [NONE, NONE, SOME (certify lthy sel)] arg_cong |
825 [NONE, NONE, SOME (certify lthy sel)] arg_cong |
826 |> Thm.varifyT_global; |
826 |> Thm.varifyT_global; |
827 val sel_thm' = sel_thm RSN (2, trans); |
827 val sel_thm' = sel_thm RSN (2, trans); |
828 in |
828 in |
829 coiter_like_thm RS arg_cong' RS sel_thm' |
829 corec_like_thm RS arg_cong' RS sel_thm' |
830 end; |
830 end; |
831 |
831 |
832 fun mk_sel_coiter_like_thms coiter_likess = |
832 fun mk_sel_corec_like_thms corec_likess = |
833 map3 (map3 (map2 o mk_sel_coiter_like_thm)) coiter_likess selsss sel_thmsss |> map flat; |
833 map3 (map3 (map2 o mk_sel_corec_like_thm)) corec_likess selsss sel_thmsss |> map flat; |
834 |
834 |
835 val sel_coiter_thmss = mk_sel_coiter_like_thms coiter_thmss; |
835 val sel_unfold_thmss = mk_sel_corec_like_thms unfold_thmss; |
836 val sel_corec_thmss = mk_sel_coiter_like_thms corec_thmss; |
836 val sel_corec_thmss = mk_sel_corec_like_thms corec_thmss; |
837 |
837 |
838 fun zip_coiter_like_thms coiter_likes disc_coiter_likes sel_coiter_likes = |
838 fun zip_corec_like_thms corec_likes disc_corec_likes sel_corec_likes = |
839 coiter_likes @ disc_coiter_likes @ sel_coiter_likes; |
839 corec_likes @ disc_corec_likes @ sel_corec_likes; |
840 |
840 |
841 val simp_thmss = |
841 val simp_thmss = |
842 mk_simp_thmss wrap_ress |
842 mk_simp_thmss wrap_ress |
843 (map3 zip_coiter_like_thms safe_corec_thmss disc_corec_thmss sel_corec_thmss) |
843 (map3 zip_corec_like_thms safe_corec_thmss disc_corec_thmss sel_corec_thmss) |
844 (map3 zip_coiter_like_thms safe_coiter_thmss disc_coiter_thmss sel_coiter_thmss); |
844 (map3 zip_corec_like_thms safe_unfold_thmss disc_unfold_thmss sel_unfold_thmss); |
845 |
845 |
846 val anonymous_notes = |
846 val anonymous_notes = |
847 [(flat safe_coiter_thmss @ flat safe_corec_thmss, simp_attrs)] |
847 [(flat safe_unfold_thmss @ flat safe_corec_thmss, simp_attrs)] |
848 |> map (fn (thms, attrs) => ((Binding.empty, attrs), [(thms, [])])); |
848 |> map (fn (thms, attrs) => ((Binding.empty, attrs), [(thms, [])])); |
849 |
849 |
850 val common_notes = |
850 val common_notes = |
851 (if nn > 1 then [(coinductN, [coinduct_thm], [])] (* FIXME: attribs *) else []) |
851 (if nn > 1 then [(coinductN, [coinduct_thm], [])] (* FIXME: attribs *) else []) |
852 |> map (fn (thmN, thms, attrs) => |
852 |> map (fn (thmN, thms, attrs) => |
853 ((Binding.qualify true fp_common_name (Binding.name thmN), attrs), [(thms, [])])); |
853 ((Binding.qualify true fp_common_name (Binding.name thmN), attrs), [(thms, [])])); |
854 |
854 |
855 val notes = |
855 val notes = |
856 [(coinductN, map single coinduct_thms, []), (* FIXME: attribs *) |
856 [(coinductN, map single coinduct_thms, []), (* FIXME: attribs *) |
857 (coitersN, coiter_thmss, []), |
857 (unfoldsN, unfold_thmss, []), |
858 (corecsN, corec_thmss, []), |
858 (corecsN, corec_thmss, []), |
859 (disc_coiter_iffN, disc_coiter_iff_thmss, simp_attrs), |
859 (disc_unfold_iffN, disc_unfold_iff_thmss, simp_attrs), |
860 (disc_coitersN, disc_coiter_thmss, simp_attrs), |
860 (disc_unfoldsN, disc_unfold_thmss, simp_attrs), |
861 (disc_corec_iffN, disc_corec_iff_thmss, simp_attrs), |
861 (disc_corec_iffN, disc_corec_iff_thmss, simp_attrs), |
862 (disc_corecsN, disc_corec_thmss, simp_attrs), |
862 (disc_corecsN, disc_corec_thmss, simp_attrs), |
863 (sel_coitersN, sel_coiter_thmss, simp_attrs), |
863 (sel_unfoldsN, sel_unfold_thmss, simp_attrs), |
864 (sel_corecsN, sel_corec_thmss, simp_attrs), |
864 (sel_corecsN, sel_corec_thmss, simp_attrs), |
865 (simpsN, simp_thmss, [])] |
865 (simpsN, simp_thmss, [])] |
866 |> maps (fn (thmN, thmss, attrs) => |
866 |> maps (fn (thmN, thmss, attrs) => |
867 map_filter (fn (_, []) => NONE | (b, thms) => |
867 map_filter (fn (_, []) => NONE | (b, thms) => |
868 SOME ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), attrs), |
868 SOME ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), attrs), |
869 [(thms, [])])) (fp_bs ~~ thmss)); |
869 [(thms, [])])) (fp_bs ~~ thmss)); |
870 in |
870 in |
871 lthy |> Local_Theory.notes (anonymous_notes @ common_notes @ notes) |> snd |
871 lthy |> Local_Theory.notes (anonymous_notes @ common_notes @ notes) |> snd |
872 end; |
872 end; |
873 |
873 |
874 fun wrap_types_and_define_iter_likes ((wraps, define_iter_likess), lthy) = |
874 fun wrap_types_and_define_rec_likes ((wraps, define_rec_likess), lthy) = |
875 fold_map2 (curry (op o)) define_iter_likess wraps lthy |>> split_list8 |
875 fold_map2 (curry (op o)) define_rec_likess wraps lthy |>> split_list8 |
876 |
876 |
877 val lthy' = lthy |
877 val lthy' = lthy |
878 |> fold_map define_ctrs_case_for_type (fp_bs ~~ fpTs ~~ Cs ~~ ctors ~~ dtors ~~ fp_iters ~~ |
878 |> fold_map define_ctrs_case_for_type (fp_bs ~~ fpTs ~~ Cs ~~ ctors ~~ dtors ~~ fp_folds ~~ |
879 fp_recs ~~ ctor_dtors ~~ dtor_ctors ~~ ctor_injects ~~ ns ~~ kss ~~ mss ~~ ctr_bindingss ~~ |
879 fp_recs ~~ ctor_dtors ~~ dtor_ctors ~~ ctor_injects ~~ ns ~~ kss ~~ mss ~~ ctr_bindingss ~~ |
880 ctr_mixfixess ~~ ctr_Tsss ~~ disc_bindingss ~~ sel_bindingsss ~~ raw_sel_defaultsss) |
880 ctr_mixfixess ~~ ctr_Tsss ~~ disc_bindingss ~~ sel_bindingsss ~~ raw_sel_defaultsss) |
881 |>> split_list |> wrap_types_and_define_iter_likes |
881 |>> split_list |> wrap_types_and_define_rec_likes |
882 |> (if lfp then derive_induct_iter_rec_thms_for_types |
882 |> (if lfp then derive_induct_fold_rec_thms_for_types |
883 else derive_coinduct_coiter_corec_thms_for_types); |
883 else derive_coinduct_unfold_corec_thms_for_types); |
884 |
884 |
885 val timer = time (timer ("Constructors, discriminators, selectors, etc., for the new " ^ |
885 val timer = time (timer ("Constructors, discriminators, selectors, etc., for the new " ^ |
886 (if lfp then "" else "co") ^ "datatype")); |
886 (if lfp then "" else "co") ^ "datatype")); |
887 in |
887 in |
888 timer; lthy' |
888 timer; lthy' |