241 fun merge_type_arg fp T T' = if T = T' then T else cannot_merge_types fp; |
241 fun merge_type_arg fp T T' = if T = T' then T else cannot_merge_types fp; |
242 |
242 |
243 fun merge_type_args fp (As, As') = |
243 fun merge_type_args fp (As, As') = |
244 if length As = length As' then map2 (merge_type_arg fp) As As' else cannot_merge_types fp; |
244 if length As = length As' then map2 (merge_type_arg fp) As As' else cannot_merge_types fp; |
245 |
245 |
246 fun reassoc_conjs thm = |
|
247 reassoc_conjs (thm RS @{thm conj_assoc[THEN iffD1]}) |
|
248 handle THM _ => thm; |
|
249 |
|
250 fun type_args_named_constrained_of_spec (((((ncAs, _), _), _), _), _) = ncAs; |
246 fun type_args_named_constrained_of_spec (((((ncAs, _), _), _), _), _) = ncAs; |
251 fun type_binding_of_spec (((((_, b), _), _), _), _) = b; |
247 fun type_binding_of_spec (((((_, b), _), _), _), _) = b; |
252 fun mixfix_of_spec ((((_, mx), _), _), _) = mx; |
248 fun mixfix_of_spec ((((_, mx), _), _), _) = mx; |
253 fun mixfixed_ctr_specs_of_spec (((_, mx_ctr_specs), _), _) = mx_ctr_specs; |
249 fun mixfixed_ctr_specs_of_spec (((_, mx_ctr_specs), _), _) = mx_ctr_specs; |
254 fun map_binding_of_spec ((_, (b, _)), _) = b; |
250 fun map_binding_of_spec ((_, (b, _)), _) = b; |
440 val fpT = range_type (snd (strip_typeN nn (fastype_of dtor_corec))); |
436 val fpT = range_type (snd (strip_typeN nn (fastype_of dtor_corec))); |
441 in |
437 in |
442 define_co_rec Greatest_FP fpT Cs (mk_binding corecN) |
438 define_co_rec Greatest_FP fpT Cs (mk_binding corecN) |
443 (fold_rev (fold_rev Term.lambda) pgss (Term.list_comb (dtor_corec, |
439 (fold_rev (fold_rev Term.lambda) pgss (Term.list_comb (dtor_corec, |
444 map5 mk_preds_getterss_join cs cpss f_absTs abss cqgsss))) |
440 map5 mk_preds_getterss_join cs cpss f_absTs abss cqgsss))) |
|
441 end; |
|
442 |
|
443 fun postproc_co_induct lthy nn prop prop_conj = |
|
444 Drule.zero_var_indexes |
|
445 #> `(conj_dests nn) |
|
446 #>> map (fn thm => Thm.permute_prems 0 (~1) (thm RS prop)) |
|
447 ##> (fn thm => Thm.permute_prems 0 (~nn) |
|
448 (if nn = 1 then thm RS prop |
|
449 else funpow nn (fn thm => Local_Defs.unfold lthy @{thms conj_assoc} (thm RS prop_conj)) thm)); |
|
450 |
|
451 fun mk_induct_attrs ctrss = |
|
452 let |
|
453 val induct_cases = quasi_unambiguous_case_names (maps (map name_of_ctr) ctrss); |
|
454 val induct_case_names_attr = Attrib.internal (K (Rule_Cases.case_names induct_cases)); |
|
455 in |
|
456 [induct_case_names_attr] |
|
457 end; |
|
458 |
|
459 fun derive_rel_induct_thm_for_types lthy fpA_Ts ns As Bs mss ctrAss ctrAs_Tsss ctr_sugars |
|
460 ctor_rel_induct ctor_defss ctor_injects pre_rel_defs abs_inverses live_nesting_rel_eqs = |
|
461 let |
|
462 val B_ify = typ_subst_nonatomic (As ~~ Bs) |
|
463 val fpB_Ts = map B_ify fpA_Ts; |
|
464 val ctrBs_Tsss = map (map (map B_ify)) ctrAs_Tsss; |
|
465 val ctrBss = map (map (subst_nonatomic_types (As ~~ Bs))) ctrAss; |
|
466 |
|
467 val ((((Rs, IRs), ctrAsss), ctrBsss), names_lthy) = lthy |
|
468 |> mk_Frees "R" (map2 mk_pred2T As Bs) |
|
469 ||>> mk_Frees "IR" (map2 mk_pred2T fpA_Ts fpB_Ts) |
|
470 ||>> mk_Freesss "a" ctrAs_Tsss |
|
471 ||>> mk_Freesss "b" ctrBs_Tsss; |
|
472 |
|
473 fun choose_relator AB = the (find_first |
|
474 (fastype_of #> binder_types #> (fn [T1, T2] => AB = (T1, T2))) (Rs @ IRs)); |
|
475 |
|
476 val premises = |
|
477 let |
|
478 fun build_the_rel A B = build_rel lthy fpA_Ts choose_relator (A, B); |
|
479 fun build_rel_app a b = build_the_rel (fastype_of a) (fastype_of b) $ a $ b; |
|
480 |
|
481 fun mk_prem ctrA ctrB argAs argBs = |
|
482 fold_rev Logic.all (argAs @ argBs) (fold_rev (curry Logic.mk_implies) |
|
483 (map2 (HOLogic.mk_Trueprop oo build_rel_app) argAs argBs) |
|
484 (HOLogic.mk_Trueprop |
|
485 (build_rel_app (Term.list_comb (ctrA, argAs)) (Term.list_comb (ctrB, argBs))))); |
|
486 in |
|
487 flat (map4 (map4 mk_prem) ctrAss ctrBss ctrAsss ctrBsss) |
|
488 end; |
|
489 |
|
490 val goal = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj |
|
491 (map2 mk_leq (map (build_rel lthy [] choose_relator) (fpA_Ts ~~ fpB_Ts)) IRs)); |
|
492 |
|
493 val rel_induct0_thm = Goal.prove_sorry lthy [] premises goal |
|
494 (fn {context = ctxt, prems = prems} => |
|
495 mk_rel_induct0_tac ctxt ctor_rel_induct prems (map (certify ctxt) IRs) |
|
496 (map #exhaust ctr_sugars) ctor_defss ctor_injects pre_rel_defs abs_inverses |
|
497 live_nesting_rel_eqs) |
|
498 |> singleton (Proof_Context.export names_lthy lthy) |
|
499 |> Thm.close_derivation; |
|
500 in |
|
501 (postproc_co_induct lthy (length fpA_Ts) @{thm predicate2D} @{thm predicate2D_conj} |
|
502 rel_induct0_thm, |
|
503 mk_induct_attrs ctrAss) |
445 end; |
504 end; |
446 |
505 |
447 fun derive_induct_recs_thms_for_types pre_bnfs rec_args_typess ctor_induct ctor_rec_thms |
506 fun derive_induct_recs_thms_for_types pre_bnfs rec_args_typess ctor_induct ctor_rec_thms |
448 live_nesting_bnfs fp_nesting_bnfs fpTs Cs Xs ctrXs_Tsss fp_abs_inverses fp_type_definitions |
507 live_nesting_bnfs fp_nesting_bnfs fpTs Cs Xs ctrXs_Tsss fp_abs_inverses fp_type_definitions |
449 abs_inverses ctrss ctr_defss recs rec_defs lthy = |
508 abs_inverses ctrss ctr_defss recs rec_defs lthy = |
592 map2 (map2 prove) goalss tacss |
648 map2 (map2 prove) goalss tacss |
593 end; |
649 end; |
594 |
650 |
595 val rec_thmss = mk_rec_thmss (the rec_args_typess) recs rec_defs ctor_rec_thms; |
651 val rec_thmss = mk_rec_thmss (the rec_args_typess) recs rec_defs ctor_rec_thms; |
596 in |
652 in |
597 ((induct_thms, induct_thm, [induct_case_names_attr]), |
653 ((induct_thms, induct_thm, mk_induct_attrs ctrss), |
598 (rec_thmss, code_nitpicksimp_attrs @ simp_attrs)) |
654 (rec_thmss, code_nitpicksimp_attrs @ simp_attrs)) |
599 end; |
655 end; |
600 |
656 |
601 fun coinduct_attrs fpTs ctr_sugars mss = |
657 fun mk_coinduct_attrs fpTs ctr_sugars mss = |
602 let |
658 let |
603 val nn = length fpTs; |
659 val nn = length fpTs; |
604 val fp_b_names = map base_name_of_typ fpTs; |
660 val fp_b_names = map base_name_of_typ fpTs; |
605 val ctrss = map #ctrs ctr_sugars; |
661 val ctrss = map #ctrs ctr_sugars; |
606 val discss = map #discs ctr_sugars; |
662 val discss = map #discs ctr_sugars; |
633 coinduct_consumes_attr :: coinduct_case_names_attr :: coinduct_case_concl_attrs; |
689 coinduct_consumes_attr :: coinduct_case_names_attr :: coinduct_case_concl_attrs; |
634 in |
690 in |
635 (coinduct_attrs, common_coinduct_attrs) |
691 (coinduct_attrs, common_coinduct_attrs) |
636 end; |
692 end; |
637 |
693 |
638 fun postproc_coinduct nn prop prop_conj = |
694 fun derive_rel_coinduct_thm_for_types lthy fpA_Ts ns As Bs mss ctr_sugars abs_inverses abs_injects |
639 Drule.zero_var_indexes |
695 ctor_injects dtor_ctors rel_pre_defs ctor_defss dtor_rel_coinduct live_nesting_rel_eqs = |
640 #> `(conj_dests nn) |
|
641 #>> map (fn thm => Thm.permute_prems 0 nn (thm RS prop)) |
|
642 ##> (fn thm => Thm.permute_prems 0 nn |
|
643 (if nn = 1 then thm RS prop |
|
644 else funpow nn (fn thm => reassoc_conjs (thm RS prop_conj)) thm)); |
|
645 |
|
646 fun derive_rel_coinduct0_thm_for_types lthy fpA_Ts ns As Bs mss ctr_sugars abs_inverses abs_injects |
|
647 ctor_injects dtor_ctors rel_pre_defs ctor_defss dtor_rel_coinduct = |
|
648 let |
696 let |
649 val fpB_Ts = map (typ_subst_nonatomic (As ~~ Bs)) fpA_Ts; |
697 val fpB_Ts = map (typ_subst_nonatomic (As ~~ Bs)) fpA_Ts; |
650 |
698 |
651 val (Rs, IRs, fpAs, fpBs, names_lthy) = |
699 val (Rs, IRs, fpAs, fpBs, names_lthy) = |
652 let |
700 let |
711 val rel_coinduct0_thm = Goal.prove_sorry lthy [] premises goal |
759 val rel_coinduct0_thm = Goal.prove_sorry lthy [] premises goal |
712 (fn {context = ctxt, prems = prems} => |
760 (fn {context = ctxt, prems = prems} => |
713 mk_rel_coinduct0_tac ctxt dtor_rel_coinduct (map (certify ctxt) IRs) prems |
761 mk_rel_coinduct0_tac ctxt dtor_rel_coinduct (map (certify ctxt) IRs) prems |
714 (map #exhaust ctr_sugars) (map (flat o #disc_thmss) ctr_sugars) |
762 (map #exhaust ctr_sugars) (map (flat o #disc_thmss) ctr_sugars) |
715 (map (flat o #sel_thmss) ctr_sugars) ctor_defss dtor_ctors ctor_injects abs_injects |
763 (map (flat o #sel_thmss) ctr_sugars) ctor_defss dtor_ctors ctor_injects abs_injects |
716 rel_pre_defs abs_inverses) |
764 rel_pre_defs abs_inverses live_nesting_rel_eqs) |
717 |> singleton (Proof_Context.export names_lthy lthy) |
765 |> singleton (Proof_Context.export names_lthy lthy) |
718 |> Thm.close_derivation; |
766 |> Thm.close_derivation; |
719 in |
767 in |
720 (postproc_coinduct (length fpA_Ts) @{thm predicate2D} @{thm predicate2D_conj} rel_coinduct0_thm, |
768 (postproc_co_induct lthy (length fpA_Ts) @{thm predicate2D} @{thm predicate2D_conj} |
721 coinduct_attrs fpA_Ts ctr_sugars mss) |
769 rel_coinduct0_thm, |
|
770 mk_coinduct_attrs fpA_Ts ctr_sugars mss) |
722 end; |
771 end; |
723 |
772 |
724 fun derive_coinduct_corecs_thms_for_types pre_bnfs (x, cs, cpss, ((pgss, cqgsss), _)) |
773 fun derive_coinduct_corecs_thms_for_types pre_bnfs (x, cs, cpss, ((pgss, cqgsss), _)) |
725 dtor_coinduct dtor_injects dtor_ctors dtor_corec_thms live_nesting_bnfs fpTs Cs Xs ctrXs_Tsss |
774 dtor_coinduct dtor_injects dtor_ctors dtor_corec_thms live_nesting_bnfs fpTs Cs Xs ctrXs_Tsss |
726 kss mss ns fp_abs_inverses abs_inverses mk_vimage2p ctr_defss (ctr_sugars : ctr_sugar list) |
775 kss mss ns fp_abs_inverses abs_inverses mk_vimage2p ctr_defss (ctr_sugars : ctr_sugar list) |
910 fun mk_sel_corec_thms corec_thmss = |
959 fun mk_sel_corec_thms corec_thmss = |
911 map3 (map3 (map2 o mk_sel_corec_thm)) corec_thmss selsss sel_thmsss; |
960 map3 (map3 (map2 o mk_sel_corec_thm)) corec_thmss selsss sel_thmsss; |
912 |
961 |
913 val sel_corec_thmsss = mk_sel_corec_thms corec_thmss; |
962 val sel_corec_thmsss = mk_sel_corec_thms corec_thmss; |
914 in |
963 in |
915 ((coinduct_thms_pairs, coinduct_attrs fpTs ctr_sugars mss), |
964 ((coinduct_thms_pairs, mk_coinduct_attrs fpTs ctr_sugars mss), |
916 (corec_thmss, code_nitpicksimp_attrs), |
965 (corec_thmss, code_nitpicksimp_attrs), |
917 (disc_corec_thmss, []), |
966 (disc_corec_thmss, []), |
918 (disc_corec_iff_thmss, simp_attrs), |
967 (disc_corec_iff_thmss, simp_attrs), |
919 (sel_corec_thmsss, simp_attrs)) |
968 (sel_corec_thmsss, simp_attrs)) |
920 end; |
969 end; |
1529 derive_induct_recs_thms_for_types pre_bnfs recs_args_types xtor_co_induct xtor_co_rec_thms |
1578 derive_induct_recs_thms_for_types pre_bnfs recs_args_types xtor_co_induct xtor_co_rec_thms |
1530 live_nesting_bnfs fp_nesting_bnfs fpTs Cs Xs ctrXs_Tsss abs_inverses type_definitions |
1579 live_nesting_bnfs fp_nesting_bnfs fpTs Cs Xs ctrXs_Tsss abs_inverses type_definitions |
1531 abs_inverses ctrss ctr_defss recs rec_defs lthy; |
1580 abs_inverses ctrss ctr_defss recs rec_defs lthy; |
1532 |
1581 |
1533 val induct_type_attr = Attrib.internal o K o Induct.induct_type; |
1582 val induct_type_attr = Attrib.internal o K o Induct.induct_type; |
|
1583 val induct_pred_attr = Attrib.internal o K o Induct.induct_pred; |
|
1584 |
|
1585 val ((rel_induct_thmss, common_rel_induct_thms), |
|
1586 (rel_induct_attrs, common_rel_induct_attrs)) = |
|
1587 if live = 0 then |
|
1588 ((replicate nn [], []), ([], [])) |
|
1589 else |
|
1590 let |
|
1591 val ((rel_induct_thms, common_rel_induct_thm), rel_induct_attrs) = |
|
1592 derive_rel_induct_thm_for_types lthy fpTs ns As Bs mss ctrss ctr_Tsss ctr_sugars |
|
1593 rel_xtor_co_induct_thm ctr_defss ctor_injects pre_rel_defs abs_inverses |
|
1594 (map rel_eq_of_bnf live_nesting_bnfs); |
|
1595 in |
|
1596 ((map single rel_induct_thms, single common_rel_induct_thm), |
|
1597 (rel_induct_attrs, rel_induct_attrs)) |
|
1598 end; |
1534 |
1599 |
1535 val simp_thmss = |
1600 val simp_thmss = |
1536 map6 mk_simp_thms ctr_sugars rec_thmss mapss rel_injectss rel_distinctss setss; |
1601 map6 mk_simp_thms ctr_sugars rec_thmss mapss rel_injectss rel_distinctss setss; |
1537 |
1602 |
1538 val common_notes = |
1603 val common_notes = |
1539 (if nn > 1 then [(inductN, [induct_thm], induct_attrs)] else []) |
1604 (if nn > 1 then |
|
1605 [(inductN, [induct_thm], induct_attrs), |
|
1606 (rel_inductN, common_rel_induct_thms, common_rel_induct_attrs)] |
|
1607 else []) |
1540 |> massage_simple_notes fp_common_name; |
1608 |> massage_simple_notes fp_common_name; |
1541 |
1609 |
1542 val notes = |
1610 val notes = |
1543 [(inductN, map single induct_thms, fn T_name => induct_attrs @ [induct_type_attr T_name]), |
1611 [(inductN, map single induct_thms, fn T_name => induct_attrs @ [induct_type_attr T_name]), |
1544 (recN, rec_thmss, K rec_attrs), |
1612 (recN, rec_thmss, K rec_attrs), |
|
1613 (rel_inductN, rel_induct_thmss, K (rel_induct_attrs @ [induct_pred_attr ""])), |
1545 (simpsN, simp_thmss, K [])] |
1614 (simpsN, simp_thmss, K [])] |
1546 |> massage_multi_notes; |
1615 |> massage_multi_notes; |
1547 in |
1616 in |
1548 lthy |
1617 lthy |
1549 |> Spec_Rules.add Spec_Rules.Equational (recs, flat rec_thmss) |
1618 |> Spec_Rules.add Spec_Rules.Equational (recs, flat rec_thmss) |
1565 derive_coinduct_corecs_thms_for_types pre_bnfs (the corecs_args_types) xtor_co_induct |
1634 derive_coinduct_corecs_thms_for_types pre_bnfs (the corecs_args_types) xtor_co_induct |
1566 dtor_injects dtor_ctors xtor_co_rec_thms live_nesting_bnfs fpTs Cs Xs ctrXs_Tsss kss mss |
1635 dtor_injects dtor_ctors xtor_co_rec_thms live_nesting_bnfs fpTs Cs Xs ctrXs_Tsss kss mss |
1567 ns abs_inverses abs_inverses I ctr_defss ctr_sugars corecs corec_defs |
1636 ns abs_inverses abs_inverses I ctr_defss ctr_sugars corecs corec_defs |
1568 (Proof_Context.export lthy' no_defs_lthy) lthy; |
1637 (Proof_Context.export lthy' no_defs_lthy) lthy; |
1569 |
1638 |
1570 val ((rel_coinduct_thms, rel_coinduct_thm), |
|
1571 (rel_coinduct_attrs, common_rel_coinduct_attrs)) = |
|
1572 derive_rel_coinduct0_thm_for_types lthy fpTs ns As Bs mss ctr_sugars abs_inverses |
|
1573 abs_injects ctor_injects dtor_ctors pre_rel_defs ctr_defss rel_xtor_co_induct_thm; |
|
1574 |
|
1575 val sel_corec_thmss = map flat sel_corec_thmsss; |
1639 val sel_corec_thmss = map flat sel_corec_thmsss; |
1576 |
1640 |
1577 val coinduct_type_attr = Attrib.internal o K o Induct.coinduct_type; |
1641 val coinduct_type_attr = Attrib.internal o K o Induct.coinduct_type; |
1578 val coinduct_pred_attr = Attrib.internal o K o Induct.coinduct_pred; |
1642 val coinduct_pred_attr = Attrib.internal o K o Induct.coinduct_pred; |
1579 |
1643 |
1580 val flat_corec_thms = append oo append; |
1644 val flat_corec_thms = append oo append; |
|
1645 |
|
1646 val ((rel_coinduct_thmss, common_rel_coinduct_thms), |
|
1647 (rel_coinduct_attrs, common_rel_coinduct_attrs)) = |
|
1648 if live = 0 then |
|
1649 ((replicate nn [], []), ([], [])) |
|
1650 else |
|
1651 let |
|
1652 val ((rel_coinduct_thms, common_rel_coinduct_thm), |
|
1653 (rel_coinduct_attrs, common_rel_coinduct_attrs)) = |
|
1654 derive_rel_coinduct_thm_for_types lthy fpTs ns As Bs mss ctr_sugars abs_inverses |
|
1655 abs_injects ctor_injects dtor_ctors pre_rel_defs ctr_defss rel_xtor_co_induct_thm |
|
1656 (map rel_eq_of_bnf live_nesting_bnfs) |
|
1657 in |
|
1658 ((map single rel_coinduct_thms, single common_rel_coinduct_thm), |
|
1659 (rel_coinduct_attrs, common_rel_coinduct_attrs)) |
|
1660 end; |
1581 |
1661 |
1582 val simp_thmss = |
1662 val simp_thmss = |
1583 map6 mk_simp_thms ctr_sugars |
1663 map6 mk_simp_thms ctr_sugars |
1584 (map3 flat_corec_thms disc_corec_thmss disc_corec_iff_thmss sel_corec_thmss) |
1664 (map3 flat_corec_thms disc_corec_thmss disc_corec_iff_thmss sel_corec_thmss) |
1585 mapss rel_injectss rel_distinctss setss; |
1665 mapss rel_injectss rel_distinctss setss; |
1586 |
1666 |
1587 val common_notes = |
1667 val common_notes = |
1588 (if nn > 1 then |
1668 (if nn > 1 then |
1589 [(rel_coinductN, [rel_coinduct_thm], common_rel_coinduct_attrs), |
1669 [(coinductN, [coinduct_thm], common_coinduct_attrs), |
1590 (coinductN, [coinduct_thm], common_coinduct_attrs), |
1670 (rel_coinductN, common_rel_coinduct_thms, common_rel_coinduct_attrs), |
1591 (strong_coinductN, [strong_coinduct_thm], common_coinduct_attrs)] |
1671 (strong_coinductN, [strong_coinduct_thm], common_coinduct_attrs)] |
1592 else |
1672 else []) |
1593 []) |
|
1594 |> massage_simple_notes fp_common_name; |
1673 |> massage_simple_notes fp_common_name; |
1595 |
1674 |
1596 val notes = |
1675 val notes = |
1597 [(coinductN, map single coinduct_thms, |
1676 [(coinductN, map single coinduct_thms, |
1598 fn T_name => coinduct_attrs @ [coinduct_type_attr T_name]), |
1677 fn T_name => coinduct_attrs @ [coinduct_type_attr T_name]), |
1599 (rel_coinductN, map single rel_coinduct_thms, |
|
1600 K (rel_coinduct_attrs @ [coinduct_pred_attr ""])), |
|
1601 (corecN, corec_thmss, K corec_attrs), |
1678 (corecN, corec_thmss, K corec_attrs), |
1602 (disc_corecN, disc_corec_thmss, K disc_corec_attrs), |
1679 (disc_corecN, disc_corec_thmss, K disc_corec_attrs), |
1603 (disc_corec_iffN, disc_corec_iff_thmss, K disc_corec_iff_attrs), |
1680 (disc_corec_iffN, disc_corec_iff_thmss, K disc_corec_iff_attrs), |
|
1681 (rel_coinductN, rel_coinduct_thmss, K (rel_coinduct_attrs @ [coinduct_pred_attr ""])), |
1604 (sel_corecN, sel_corec_thmss, K sel_corec_attrs), |
1682 (sel_corecN, sel_corec_thmss, K sel_corec_attrs), |
1605 (simpsN, simp_thmss, K []), |
1683 (simpsN, simp_thmss, K []), |
1606 (strong_coinductN, map single strong_coinduct_thms, K coinduct_attrs)] |
1684 (strong_coinductN, map single strong_coinduct_thms, K coinduct_attrs)] |
1607 |> massage_multi_notes; |
1685 |> massage_multi_notes; |
1608 in |
1686 in |