| author | wenzelm | 
| Tue, 11 Jul 2006 12:17:08 +0200 | |
| changeset 20083 | 717b1eb434f1 | 
| parent 20071 | 8f3e1ddb50e6 | 
| child 21021 | 6f19e5eb3a44 | 
| permissions | -rw-r--r-- | 
| 5177 | 1 | (* Title: HOL/Tools/datatype_abs_proofs.ML | 
| 2 | ID: $Id$ | |
| 11539 | 3 | Author: Stefan Berghofer, TU Muenchen | 
| 5177 | 4 | |
| 5 | Proofs and defintions independent of concrete representation | |
| 6 | of datatypes (i.e. requiring only abstract properties such as | |
| 7 | injectivity / distinctness of constructors and induction) | |
| 8 | ||
| 9 | - case distinction (exhaustion) theorems | |
| 10 | - characteristic equations for primrec combinators | |
| 11 | - characteristic equations for case combinators | |
| 12 | - equations for splitting "P (case ...)" expressions | |
| 13 | - datatype size function | |
| 14 | - "nchotomy" and "case_cong" theorems for TFL | |
| 15 | ||
| 16 | *) | |
| 17 | ||
| 18 | signature DATATYPE_ABS_PROOFS = | |
| 19 | sig | |
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 20 | val prove_casedist_thms : string list -> | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 21 | DatatypeAux.descr list -> (string * sort) list -> thm -> | 
| 18728 | 22 | attribute list -> theory -> thm list * theory | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 23 | val prove_primrec_thms : bool -> string list -> | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 24 | DatatypeAux.descr list -> (string * sort) list -> | 
| 5177 | 25 | DatatypeAux.datatype_info Symtab.table -> thm list list -> thm list list -> | 
| 18314 | 26 | simpset -> thm -> theory -> (string list * thm list) * theory | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 27 | val prove_case_thms : bool -> string list -> | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 28 | DatatypeAux.descr list -> (string * sort) list -> | 
| 18314 | 29 | string list -> thm list -> theory -> (thm list list * string list) * theory | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 30 | val prove_split_thms : string list -> | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 31 | DatatypeAux.descr list -> (string * sort) list -> | 
| 5177 | 32 | thm list list -> thm list list -> thm list -> thm list list -> theory -> | 
| 18314 | 33 | (thm * thm) list * theory | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 34 | val prove_size_thms : bool -> string list -> | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 35 | DatatypeAux.descr list -> (string * sort) list -> | 
| 18314 | 36 | string list -> thm list -> theory -> thm list * theory | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 37 | val prove_nchotomys : string list -> DatatypeAux.descr list -> | 
| 18314 | 38 | (string * sort) list -> thm list -> theory -> thm list * theory | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 39 | val prove_weak_case_congs : string list -> DatatypeAux.descr list -> | 
| 18314 | 40 | (string * sort) list -> theory -> thm list * theory | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 41 | val prove_case_congs : string list -> | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 42 | DatatypeAux.descr list -> (string * sort) list -> | 
| 18314 | 43 | thm list -> thm list list -> theory -> thm list * theory | 
| 5177 | 44 | end; | 
| 45 | ||
| 8436 | 46 | structure DatatypeAbsProofs: DATATYPE_ABS_PROOFS = | 
| 5177 | 47 | struct | 
| 48 | ||
| 49 | open DatatypeAux; | |
| 50 | ||
| 51 | (************************ case distinction theorems ***************************) | |
| 52 | ||
| 8436 | 53 | fun prove_casedist_thms new_type_names descr sorts induct case_names_exhausts thy = | 
| 5177 | 54 | let | 
| 6427 | 55 | val _ = message "Proving case distinction theorems ..."; | 
| 5177 | 56 | |
| 15570 | 57 | val descr' = List.concat descr; | 
| 5177 | 58 | val recTs = get_rec_types descr' sorts; | 
| 15570 | 59 | val newTs = Library.take (length (hd descr), recTs); | 
| 5177 | 60 | |
| 8477 
17231d71171a
- Fixed bug in prove_casedist_thms (proof failed because of
 berghofe parents: 
8436diff
changeset | 61 |     val {maxidx, ...} = rep_thm induct;
 | 
| 8305 | 62 | val induct_Ps = map head_of (HOLogic.dest_conj (HOLogic.dest_Trueprop (concl_of induct))); | 
| 5177 | 63 | |
| 64 | fun prove_casedist_thm ((i, t), T) = | |
| 65 | let | |
| 66 | val dummyPs = map (fn (Var (_, Type (_, [T', T'']))) => | |
| 67 |           Abs ("z", T', Const ("True", T''))) induct_Ps;
 | |
| 8477 
17231d71171a
- Fixed bug in prove_casedist_thms (proof failed because of
 berghofe parents: 
8436diff
changeset | 68 |         val P = Abs ("z", T, HOLogic.imp $ HOLogic.mk_eq (Var (("a", maxidx+1), T), Bound 0) $
 | 
| 5177 | 69 |           Var (("P", 0), HOLogic.boolT))
 | 
| 15570 | 70 | val insts = Library.take (i, dummyPs) @ (P::(Library.drop (i + 1, dummyPs))); | 
| 17985 | 71 | val cert = cterm_of thy; | 
| 5177 | 72 | val insts' = (map cert induct_Ps) ~~ (map cert insts); | 
| 15570 | 73 | val induct' = refl RS ((List.nth | 
| 74 | (split_conj_thm (cterm_instantiate insts' induct), i)) RSN (2, rev_mp)) | |
| 5177 | 75 | |
| 17985 | 76 | in | 
| 20046 | 77 | Goal.prove_global thy [] (Logic.strip_imp_prems t) (Logic.strip_imp_concl t) | 
| 17985 | 78 | (fn prems => EVERY | 
| 79 | [rtac induct' 1, | |
| 80 | REPEAT (rtac TrueI 1), | |
| 81 | REPEAT ((rtac impI 1) THEN (eresolve_tac prems 1)), | |
| 20046 | 82 | REPEAT (rtac TrueI 1)]) | 
| 5177 | 83 | end; | 
| 84 | ||
| 85 | val casedist_thms = map prove_casedist_thm ((0 upto (length newTs - 1)) ~~ | |
| 86 | (DatatypeProp.make_casedists descr sorts) ~~ newTs) | |
| 18314 | 87 | in | 
| 88 | thy | |
| 89 | |> store_thms_atts "exhaust" new_type_names (map single case_names_exhausts) casedist_thms | |
| 90 | end; | |
| 5177 | 91 | |
| 92 | ||
| 93 | (*************************** primrec combinators ******************************) | |
| 94 | ||
| 5661 | 95 | fun prove_primrec_thms flat_names new_type_names descr sorts | 
| 7015 
85be09eb136c
- Datatype package now also supports arbitrarily branching datatypes
 berghofe parents: 
6522diff
changeset | 96 | (dt_info : datatype_info Symtab.table) constr_inject dist_rewrites dist_ss induct thy = | 
| 5177 | 97 | let | 
| 6427 | 98 | val _ = message "Constructing primrec combinators ..."; | 
| 5661 | 99 | |
| 100 | val big_name = space_implode "_" new_type_names; | |
| 101 | val thy0 = add_path flat_names big_name thy; | |
| 5177 | 102 | |
| 15570 | 103 | val descr' = List.concat descr; | 
| 5177 | 104 | val recTs = get_rec_types descr' sorts; | 
| 15574 
b1d1b5bfc464
Removed practically all references to Library.foldr.
 skalberg parents: 
15570diff
changeset | 105 | val used = foldr add_typ_tfree_names [] recTs; | 
| 15570 | 106 | val newTs = Library.take (length (hd descr), recTs); | 
| 5177 | 107 | |
| 8305 | 108 | val induct_Ps = map head_of (HOLogic.dest_conj (HOLogic.dest_Trueprop (concl_of induct))); | 
| 5177 | 109 | |
| 5661 | 110 | val big_rec_name' = big_name ^ "_rec_set"; | 
| 6394 | 111 | val rec_set_names = map (Sign.full_name (Theory.sign_of thy0)) | 
| 5177 | 112 | (if length descr' = 1 then [big_rec_name'] else | 
| 113 | (map ((curry (op ^) (big_rec_name' ^ "_")) o string_of_int) | |
| 114 | (1 upto (length descr')))); | |
| 115 | ||
| 15459 
16dd63c78049
Introduced function DatatypeProp.make_primrec_Ts to avoid code duplication.
 berghofe parents: 
14981diff
changeset | 116 | val (rec_result_Ts, reccomb_fn_Ts) = DatatypeProp.make_primrec_Ts descr sorts used; | 
| 5177 | 117 | |
| 118 | val rec_set_Ts = map (fn (T1, T2) => reccomb_fn_Ts ---> HOLogic.mk_setT | |
| 119 | (HOLogic.mk_prodT (T1, T2))) (recTs ~~ rec_result_Ts); | |
| 120 | ||
| 121 | val rec_fns = map (uncurry (mk_Free "f")) | |
| 122 | (reccomb_fn_Ts ~~ (1 upto (length reccomb_fn_Ts))); | |
| 123 | val rec_sets = map (fn c => list_comb (Const c, rec_fns)) | |
| 124 | (rec_set_names ~~ rec_set_Ts); | |
| 125 | ||
| 126 | (* introduction rules for graph of primrec function *) | |
| 127 | ||
| 128 | fun make_rec_intr T set_name ((rec_intr_ts, l), (cname, cargs)) = | |
| 129 | let | |
| 7015 
85be09eb136c
- Datatype package now also supports arbitrarily branching datatypes
 berghofe parents: 
6522diff
changeset | 130 | fun mk_prem ((dt, U), (j, k, prems, t1s, t2s)) = | 
| 
85be09eb136c
- Datatype package now also supports arbitrarily branching datatypes
 berghofe parents: 
6522diff
changeset | 131 | let val free1 = mk_Free "x" U j | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 132 | in (case (strip_dtyp dt, strip_type U) of | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 133 | ((_, DtRec m), (Us, _)) => | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 134 | let | 
| 15570 | 135 | val free2 = mk_Free "y" (Us ---> List.nth (rec_result_Ts, m)) k; | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 136 | val i = length Us | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 137 | in (j + 1, k + 1, HOLogic.mk_Trueprop (HOLogic.list_all | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 138 | (map (pair "x") Us, HOLogic.mk_mem (HOLogic.mk_prod | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 139 | (app_bnds free1 i, app_bnds free2 i), | 
| 15570 | 140 | List.nth (rec_sets, m)))) :: prems, | 
| 5177 | 141 | free1::t1s, free2::t2s) | 
| 142 | end | |
| 143 | | _ => (j + 1, k, prems, free1::t1s, t2s)) | |
| 144 | end; | |
| 145 | ||
| 146 | val Ts = map (typ_of_dtyp descr' sorts) cargs; | |
| 15574 
b1d1b5bfc464
Removed practically all references to Library.foldr.
 skalberg parents: 
15570diff
changeset | 147 | val (_, _, prems, t1s, t2s) = foldr mk_prem (1, 1, [], [], []) (cargs ~~ Ts) | 
| 5177 | 148 | |
| 149 | in (rec_intr_ts @ [Logic.list_implies (prems, HOLogic.mk_Trueprop (HOLogic.mk_mem | |
| 150 | (HOLogic.mk_prod (list_comb (Const (cname, Ts ---> T), t1s), | |
| 15570 | 151 | list_comb (List.nth (rec_fns, l), t1s @ t2s)), set_name)))], l + 1) | 
| 5177 | 152 | end; | 
| 153 | ||
| 15570 | 154 | val (rec_intr_ts, _) = Library.foldl (fn (x, ((d, T), set_name)) => | 
| 155 | Library.foldl (make_rec_intr T set_name) (x, #3 (snd d))) | |
| 5177 | 156 | (([], 0), descr' ~~ recTs ~~ rec_sets); | 
| 157 | ||
| 158 |     val (thy1, {intrs = rec_intrs, elims = rec_elims, ...}) =
 | |
| 5661 | 159 | setmp InductivePackage.quiet_mode (!quiet_mode) | 
| 160 | (InductivePackage.add_inductive_i false true big_rec_name' false false true | |
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 161 |            rec_sets (map (fn x => (("", x), [])) rec_intr_ts) []) thy0;
 | 
| 5177 | 162 | |
| 163 | (* prove uniqueness and termination of primrec combinators *) | |
| 164 | ||
| 6427 | 165 | val _ = message "Proving termination and uniqueness of primrec functions ..."; | 
| 5177 | 166 | |
| 167 | fun mk_unique_tac ((tac, intrs), ((((i, (tname, _, constrs)), elim), T), T')) = | |
| 168 | let | |
| 169 | val distinct_tac = (etac Pair_inject 1) THEN | |
| 170 | (if i < length newTs then | |
| 15570 | 171 | full_simp_tac (HOL_ss addsimps (List.nth (dist_rewrites, i))) 1 | 
| 7015 
85be09eb136c
- Datatype package now also supports arbitrarily branching datatypes
 berghofe parents: 
6522diff
changeset | 172 | else full_simp_tac dist_ss 1); | 
| 5177 | 173 | |
| 174 | val inject = map (fn r => r RS iffD1) | |
| 15570 | 175 | (if i < length newTs then List.nth (constr_inject, i) | 
| 17412 | 176 | else #inject (the (Symtab.lookup dt_info tname))); | 
| 5177 | 177 | |
| 178 | fun mk_unique_constr_tac n ((tac, intr::intrs, j), (cname, cargs)) = | |
| 179 | let | |
| 15570 | 180 | val k = length (List.filter is_rec_type cargs) | 
| 5177 | 181 | |
| 182 | in (EVERY [DETERM tac, | |
| 183 | REPEAT (etac ex1E 1), rtac ex1I 1, | |
| 184 | DEPTH_SOLVE_1 (ares_tac [intr] 1), | |
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 185 | REPEAT_DETERM_N k (etac thin_rl 1 THEN rotate_tac 1 1), | 
| 5177 | 186 | etac elim 1, | 
| 187 | REPEAT_DETERM_N j distinct_tac, | |
| 188 | etac Pair_inject 1, TRY (dresolve_tac inject 1), | |
| 189 | REPEAT (etac conjE 1), hyp_subst_tac 1, | |
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 190 | REPEAT (EVERY [etac allE 1, dtac mp 1, atac 1]), | 
| 5177 | 191 | TRY (hyp_subst_tac 1), | 
| 192 | rtac refl 1, | |
| 193 | REPEAT_DETERM_N (n - j - 1) distinct_tac], | |
| 194 | intrs, j + 1) | |
| 195 | end; | |
| 196 | ||
| 15570 | 197 | val (tac', intrs', _) = Library.foldl (mk_unique_constr_tac (length constrs)) | 
| 5177 | 198 | ((tac, intrs, 0), constrs); | 
| 199 | ||
| 200 | in (tac', intrs') end; | |
| 201 | ||
| 202 | val rec_unique_thms = | |
| 203 | let | |
| 204 | val rec_unique_ts = map (fn (((set_t, T1), T2), i) => | |
| 205 |           Const ("Ex1", (T2 --> HOLogic.boolT) --> HOLogic.boolT) $
 | |
| 206 |             absfree ("y", T2, HOLogic.mk_mem (HOLogic.mk_prod
 | |
| 207 |               (mk_Free "x" T1 i, Free ("y", T2)), set_t)))
 | |
| 208 | (rec_sets ~~ recTs ~~ rec_result_Ts ~~ (1 upto length recTs)); | |
| 17985 | 209 | val cert = cterm_of thy1 | 
| 5177 | 210 |         val insts = map (fn ((i, T), t) => absfree ("x" ^ (string_of_int i), T, t))
 | 
| 211 | ((1 upto length recTs) ~~ recTs ~~ rec_unique_ts); | |
| 212 | val induct' = cterm_instantiate ((map cert induct_Ps) ~~ | |
| 213 | (map cert insts)) induct; | |
| 15570 | 214 | val (tac, _) = Library.foldl mk_unique_tac | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 215 | (((rtac induct' THEN_ALL_NEW ObjectLogic.atomize_tac) 1 | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 216 | THEN rewtac (mk_meta_eq choice_eq), rec_intrs), | 
| 10911 
eb5721204b38
proper induction rule for arbitrarily branching datatype;
 wenzelm parents: 
10214diff
changeset | 217 | descr' ~~ rec_elims ~~ recTs ~~ rec_result_Ts); | 
| 5177 | 218 | |
| 20046 | 219 | in split_conj_thm (Goal.prove_global thy1 [] [] | 
| 220 | (HOLogic.mk_Trueprop (mk_conj rec_unique_ts)) (K tac)) | |
| 5177 | 221 | end; | 
| 222 | ||
| 11435 | 223 | val rec_total_thms = map (fn r => r RS theI') rec_unique_thms; | 
| 5177 | 224 | |
| 225 | (* define primrec combinators *) | |
| 226 | ||
| 227 | val big_reccomb_name = (space_implode "_" new_type_names) ^ "_rec"; | |
| 6394 | 228 | val reccomb_names = map (Sign.full_name (Theory.sign_of thy1)) | 
| 5177 | 229 | (if length descr' = 1 then [big_reccomb_name] else | 
| 230 | (map ((curry (op ^) (big_reccomb_name ^ "_")) o string_of_int) | |
| 231 | (1 upto (length descr')))); | |
| 232 | val reccombs = map (fn ((name, T), T') => list_comb | |
| 233 | (Const (name, reccomb_fn_Ts @ [T] ---> T'), rec_fns)) | |
| 234 | (reccomb_names ~~ recTs ~~ rec_result_Ts); | |
| 235 | ||
| 18358 | 236 | val (reccomb_defs, thy2) = | 
| 237 | thy1 | |
| 238 | |> Theory.add_consts_i (map (fn ((name, T), T') => | |
| 239 | (Sign.base_name name, reccomb_fn_Ts @ [T] ---> T', NoSyn)) | |
| 240 | (reccomb_names ~~ recTs ~~ rec_result_Ts)) | |
| 241 | |> (PureThy.add_defs_i false o map Thm.no_attributes) (map (fn ((((name, comb), set), T), T') => | |
| 242 |           ((Sign.base_name name) ^ "_def", Logic.mk_equals (comb, absfree ("x", T,
 | |
| 11435 | 243 |            Const ("The", (T' --> HOLogic.boolT) --> T') $ absfree ("y", T',
 | 
| 7015 
85be09eb136c
- Datatype package now also supports arbitrarily branching datatypes
 berghofe parents: 
6522diff
changeset | 244 |              HOLogic.mk_mem (HOLogic.mk_prod (Free ("x", T), Free ("y", T')), set))))))
 | 
| 18358 | 245 | (reccomb_names ~~ reccombs ~~ rec_sets ~~ recTs ~~ rec_result_Ts)) | 
| 246 | ||> parent_path flat_names; | |
| 5177 | 247 | |
| 248 | ||
| 249 | (* prove characteristic equations for primrec combinators *) | |
| 250 | ||
| 6427 | 251 | val _ = message "Proving characteristic theorems for primrec combinators ..." | 
| 5177 | 252 | |
| 20046 | 253 | val rec_thms = map (fn t => Goal.prove_global thy2 [] [] t | 
| 17985 | 254 | (fn _ => EVERY | 
| 255 | [rewrite_goals_tac reccomb_defs, | |
| 256 | rtac the1_equality 1, | |
| 5177 | 257 | resolve_tac rec_unique_thms 1, | 
| 258 | resolve_tac rec_intrs 1, | |
| 20046 | 259 | REPEAT (rtac allI 1 ORELSE resolve_tac rec_total_thms 1)])) | 
| 5177 | 260 | (DatatypeProp.make_primrecs new_type_names descr sorts thy2) | 
| 261 | ||
| 262 | in | |
| 18314 | 263 | thy2 | 
| 264 | |> Theory.add_path (space_implode "_" new_type_names) | |
| 18377 | 265 |     |> PureThy.add_thmss [(("recs", rec_thms), [])]
 | 
| 18314 | 266 | ||> Theory.parent_path | 
| 267 | |-> (fn thms => pair (reccomb_names, Library.flat thms)) | |
| 5177 | 268 | end; | 
| 269 | ||
| 8477 
17231d71171a
- Fixed bug in prove_casedist_thms (proof failed because of
 berghofe parents: 
8436diff
changeset | 270 | |
| 5177 | 271 | (***************************** case combinators *******************************) | 
| 272 | ||
| 5661 | 273 | fun prove_case_thms flat_names new_type_names descr sorts reccomb_names primrec_thms thy = | 
| 5177 | 274 | let | 
| 6427 | 275 | val _ = message "Proving characteristic theorems for case combinators ..."; | 
| 5661 | 276 | |
| 277 | val thy1 = add_path flat_names (space_implode "_" new_type_names) thy; | |
| 5177 | 278 | |
| 15570 | 279 | val descr' = List.concat descr; | 
| 5177 | 280 | val recTs = get_rec_types descr' sorts; | 
| 15574 
b1d1b5bfc464
Removed practically all references to Library.foldr.
 skalberg parents: 
15570diff
changeset | 281 | val used = foldr add_typ_tfree_names [] recTs; | 
| 15570 | 282 | val newTs = Library.take (length (hd descr), recTs); | 
| 20071 
8f3e1ddb50e6
replaced Term.variant(list) by Name.variant(_list);
 wenzelm parents: 
20046diff
changeset | 283 | val T' = TFree (Name.variant used "'t", HOLogic.typeS); | 
| 5177 | 284 | |
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 285 | fun mk_dummyT dt = binder_types (typ_of_dtyp descr' sorts dt) ---> T'; | 
| 7015 
85be09eb136c
- Datatype package now also supports arbitrarily branching datatypes
 berghofe parents: 
6522diff
changeset | 286 | |
| 5177 | 287 | val case_dummy_fns = map (fn (_, (_, _, constrs)) => map (fn (_, cargs) => | 
| 288 | let | |
| 289 | val Ts = map (typ_of_dtyp descr' sorts) cargs; | |
| 15570 | 290 | val Ts' = map mk_dummyT (List.filter is_rec_type cargs) | 
| 5578 
7de426cf179c
Package now chooses type variable names more carefully to
 berghofe parents: 
5553diff
changeset | 291 |       in Const ("arbitrary", Ts @ Ts' ---> T')
 | 
| 5177 | 292 | end) constrs) descr'; | 
| 293 | ||
| 294 | val case_names = map (fn s => | |
| 6394 | 295 | Sign.full_name (Theory.sign_of thy1) (s ^ "_case")) new_type_names; | 
| 5177 | 296 | |
| 297 | (* define case combinators via primrec combinators *) | |
| 298 | ||
| 15570 | 299 | val (case_defs, thy2) = Library.foldl (fn ((defs, thy), | 
| 5177 | 300 | ((((i, (_, _, constrs)), T), name), recname)) => | 
| 301 | let | |
| 302 | val (fns1, fns2) = ListPair.unzip (map (fn ((_, cargs), j) => | |
| 303 | let | |
| 304 | val Ts = map (typ_of_dtyp descr' sorts) cargs; | |
| 15570 | 305 | val Ts' = Ts @ map mk_dummyT (List.filter is_rec_type cargs); | 
| 5177 | 306 | val frees' = map (uncurry (mk_Free "x")) (Ts' ~~ (1 upto length Ts')); | 
| 15570 | 307 | val frees = Library.take (length cargs, frees'); | 
| 5177 | 308 | val free = mk_Free "f" (Ts ---> T') j | 
| 309 | in | |
| 310 | (free, list_abs_free (map dest_Free frees', | |
| 311 | list_comb (free, frees))) | |
| 312 | end) (constrs ~~ (1 upto length constrs))); | |
| 313 | ||
| 314 | val caseT = (map (snd o dest_Free) fns1) @ [T] ---> T'; | |
| 15570 | 315 | val fns = (List.concat (Library.take (i, case_dummy_fns))) @ | 
| 316 | fns2 @ (List.concat (Library.drop (i + 1, case_dummy_fns))); | |
| 5177 | 317 | val reccomb = Const (recname, (map fastype_of fns) @ [T] ---> T'); | 
| 318 | val decl = (Sign.base_name name, caseT, NoSyn); | |
| 319 | val def = ((Sign.base_name name) ^ "_def", | |
| 320 | Logic.mk_equals (list_comb (Const (name, caseT), fns1), | |
| 15570 | 321 | list_comb (reccomb, (List.concat (Library.take (i, case_dummy_fns))) @ | 
| 322 | fns2 @ (List.concat (Library.drop (i + 1, case_dummy_fns))) ))); | |
| 18358 | 323 | val ([def_thm], thy') = | 
| 324 | thy | |
| 325 | |> Theory.add_consts_i [decl] | |
| 326 | |> (PureThy.add_defs_i false o map Thm.no_attributes) [def]; | |
| 5177 | 327 | |
| 8436 | 328 | in (defs @ [def_thm], thy') | 
| 5661 | 329 | end) (([], thy1), (hd descr) ~~ newTs ~~ case_names ~~ | 
| 15570 | 330 | (Library.take (length newTs, reccomb_names))); | 
| 5177 | 331 | |
| 20046 | 332 | val case_thms = map (map (fn t => Goal.prove_global thy2 [] [] t | 
| 333 | (fn _ => EVERY [rewrite_goals_tac (case_defs @ map mk_meta_eq primrec_thms), rtac refl 1]))) | |
| 8477 
17231d71171a
- Fixed bug in prove_casedist_thms (proof failed because of
 berghofe parents: 
8436diff
changeset | 334 | (DatatypeProp.make_cases new_type_names descr sorts thy2) | 
| 5177 | 335 | |
| 8477 
17231d71171a
- Fixed bug in prove_casedist_thms (proof failed because of
 berghofe parents: 
8436diff
changeset | 336 | in | 
| 18314 | 337 | thy2 | 
| 338 | |> parent_path flat_names | |
| 339 | |> store_thmss "cases" new_type_names case_thms | |
| 340 | |-> (fn thmss => pair (thmss, case_names)) | |
| 8477 
17231d71171a
- Fixed bug in prove_casedist_thms (proof failed because of
 berghofe parents: 
8436diff
changeset | 341 | end; | 
| 5177 | 342 | |
| 343 | ||
| 344 | (******************************* case splitting *******************************) | |
| 345 | ||
| 346 | fun prove_split_thms new_type_names descr sorts constr_inject dist_rewrites | |
| 347 | casedist_thms case_thms thy = | |
| 348 | let | |
| 6427 | 349 | val _ = message "Proving equations for case splitting ..."; | 
| 5177 | 350 | |
| 15570 | 351 | val descr' = List.concat descr; | 
| 5177 | 352 | val recTs = get_rec_types descr' sorts; | 
| 15570 | 353 | val newTs = Library.take (length (hd descr), recTs); | 
| 5177 | 354 | |
| 355 | fun prove_split_thms ((((((t1, t2), inject), dist_rewrites'), | |
| 356 | exhaustion), case_thms'), T) = | |
| 357 | let | |
| 17985 | 358 | val cert = cterm_of thy; | 
| 5177 | 359 | val _ $ (_ $ lhs $ _) = hd (Logic.strip_assums_hyp (hd (prems_of exhaustion))); | 
| 360 | val exhaustion' = cterm_instantiate | |
| 361 |           [(cert lhs, cert (Free ("x", T)))] exhaustion;
 | |
| 17985 | 362 | val tacf = K (EVERY [rtac exhaustion' 1, ALLGOALS (asm_simp_tac | 
| 363 | (HOL_ss addsimps (dist_rewrites' @ inject @ case_thms')))]) | |
| 5177 | 364 | in | 
| 20046 | 365 | (Goal.prove_global thy [] [] t1 tacf, | 
| 366 | Goal.prove_global thy [] [] t2 tacf) | |
| 5177 | 367 | end; | 
| 368 | ||
| 369 | val split_thm_pairs = map prove_split_thms | |
| 370 | ((DatatypeProp.make_splits new_type_names descr sorts thy) ~~ constr_inject ~~ | |
| 371 | dist_rewrites ~~ casedist_thms ~~ case_thms ~~ newTs); | |
| 372 | ||
| 373 | val (split_thms, split_asm_thms) = ListPair.unzip split_thm_pairs | |
| 374 | ||
| 375 | in | |
| 18314 | 376 | thy | 
| 377 | |> store_thms "split" new_type_names split_thms | |
| 378 | ||>> store_thms "split_asm" new_type_names split_asm_thms | |
| 379 | |-> (fn (thms1, thms2) => pair (thms1 ~~ thms2)) | |
| 5177 | 380 | end; | 
| 381 | ||
| 382 | (******************************* size functions *******************************) | |
| 383 | ||
| 5661 | 384 | fun prove_size_thms flat_names new_type_names descr sorts reccomb_names primrec_thms thy = | 
| 13641 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 385 | if exists (fn (_, (_, _, constrs)) => exists (fn (_, cargs) => exists (fn dt => | 
| 
63d1790a43ed
Reimplemented parts of datatype package dealing with datatypes involving
 berghofe parents: 
12910diff
changeset | 386 | is_rec_type dt andalso not (null (fst (strip_dtyp dt)))) cargs) constrs) | 
| 15570 | 387 | (List.concat descr) | 
| 7015 
85be09eb136c
- Datatype package now also supports arbitrarily branching datatypes
 berghofe parents: 
6522diff
changeset | 388 | then | 
| 18314 | 389 | ([], thy) | 
| 7015 
85be09eb136c
- Datatype package now also supports arbitrarily branching datatypes
 berghofe parents: 
6522diff
changeset | 390 | else | 
| 5177 | 391 | let | 
| 6427 | 392 | val _ = message "Proving equations for size function ..."; | 
| 5661 | 393 | |
| 394 | val big_name = space_implode "_" new_type_names; | |
| 395 | val thy1 = add_path flat_names big_name thy; | |
| 5177 | 396 | |
| 15570 | 397 | val descr' = List.concat descr; | 
| 5177 | 398 | val recTs = get_rec_types descr' sorts; | 
| 399 | ||
| 11957 | 400 | val size_name = "Nat.size"; | 
| 5177 | 401 | val size_names = replicate (length (hd descr)) size_name @ | 
| 9739 | 402 | map (Sign.full_name (Theory.sign_of thy1)) (DatatypeProp.indexify_names | 
| 15570 | 403 | (map (fn T => name_of_typ T ^ "_size") (Library.drop (length (hd descr), recTs)))); | 
| 9739 | 404 | val def_names = map (fn s => s ^ "_def") (DatatypeProp.indexify_names | 
| 405 | (map (fn T => name_of_typ T ^ "_size") recTs)); | |
| 5177 | 406 | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
18728diff
changeset | 407 |     fun plus (t1, t2) = Const ("HOL.plus", [HOLogic.natT, HOLogic.natT] ---> HOLogic.natT) $ t1 $ t2;
 | 
| 5177 | 408 | |
| 409 | fun make_sizefun (_, cargs) = | |
| 410 | let | |
| 411 | val Ts = map (typ_of_dtyp descr' sorts) cargs; | |
| 15570 | 412 | val k = length (List.filter is_rec_type cargs); | 
| 5177 | 413 | val t = if k = 0 then HOLogic.zero else | 
| 7704 | 414 | foldl1 plus (map Bound (k - 1 downto 0) @ [HOLogic.mk_nat 1]) | 
| 5177 | 415 | in | 
| 15574 
b1d1b5bfc464
Removed practically all references to Library.foldr.
 skalberg parents: 
15570diff
changeset | 416 |         foldr (fn (T, t') => Abs ("x", T, t')) t (Ts @ replicate k HOLogic.natT)
 | 
| 5177 | 417 | end; | 
| 418 | ||
| 15570 | 419 | val fs = List.concat (map (fn (_, (_, _, constrs)) => map make_sizefun constrs) descr'); | 
| 5177 | 420 | val fTs = map fastype_of fs; | 
| 421 | ||
| 18358 | 422 | val (size_def_thms, thy') = | 
| 423 | thy1 | |
| 424 | |> Theory.add_consts_i (map (fn (s, T) => | |
| 425 | (Sign.base_name s, T --> HOLogic.natT, NoSyn)) | |
| 426 | (Library.drop (length (hd descr), size_names ~~ recTs))) | |
| 427 | |> (PureThy.add_defs_i true o map Thm.no_attributes) (map (fn (((s, T), def_name), rec_name) => | |
| 428 | (def_name, Logic.mk_equals (Const (s, T --> HOLogic.natT), | |
| 429 | list_comb (Const (rec_name, fTs @ [T] ---> HOLogic.natT), fs)))) | |
| 430 | (size_names ~~ recTs ~~ def_names ~~ reccomb_names)) | |
| 431 | ||> parent_path flat_names; | |
| 5177 | 432 | |
| 5553 | 433 | val rewrites = size_def_thms @ map mk_meta_eq primrec_thms; | 
| 5177 | 434 | |
| 20046 | 435 | val size_thms = map (fn t => Goal.prove_global thy' [] [] t | 
| 436 | (fn _ => EVERY [rewrite_goals_tac rewrites, rtac refl 1])) | |
| 9739 | 437 | (DatatypeProp.make_size descr sorts thy') | 
| 5177 | 438 | |
| 439 | in | |
| 18314 | 440 | thy' | 
| 441 | |> Theory.add_path big_name | |
| 18377 | 442 |     |> PureThy.add_thmss [(("size", size_thms), [])]
 | 
| 18314 | 443 | ||> Theory.parent_path | 
| 444 | |-> (fn thmss => pair (Library.flat thmss)) | |
| 5177 | 445 | end; | 
| 446 | ||
| 8601 | 447 | fun prove_weak_case_congs new_type_names descr sorts thy = | 
| 448 | let | |
| 449 | fun prove_weak_case_cong t = | |
| 20046 | 450 | Goal.prove_global thy [] (Logic.strip_imp_prems t) (Logic.strip_imp_concl t) | 
| 451 | (fn prems => EVERY [rtac ((hd prems) RS arg_cong) 1]) | |
| 8601 | 452 | |
| 453 | val weak_case_congs = map prove_weak_case_cong (DatatypeProp.make_weak_case_congs | |
| 454 | new_type_names descr sorts thy) | |
| 455 | ||
| 456 | in thy |> store_thms "weak_case_cong" new_type_names weak_case_congs end; | |
| 8477 
17231d71171a
- Fixed bug in prove_casedist_thms (proof failed because of
 berghofe parents: 
8436diff
changeset | 457 | |
| 5177 | 458 | (************************* additional theorems for TFL ************************) | 
| 459 | ||
| 460 | fun prove_nchotomys new_type_names descr sorts casedist_thms thy = | |
| 461 | let | |
| 6427 | 462 | val _ = message "Proving additional theorems for TFL ..."; | 
| 5177 | 463 | |
| 464 | fun prove_nchotomy (t, exhaustion) = | |
| 465 | let | |
| 466 | (* For goal i, select the correct disjunct to attack, then prove it *) | |
| 467 | fun tac i 0 = EVERY [TRY (rtac disjI1 i), | |
| 468 | hyp_subst_tac i, REPEAT (rtac exI i), rtac refl i] | |
| 469 | | tac i n = rtac disjI2 i THEN tac i (n - 1) | |
| 470 | in | |
| 20046 | 471 | Goal.prove_global thy [] [] t (fn _ => | 
| 17985 | 472 | EVERY [rtac allI 1, | 
| 5177 | 473 | exh_tac (K exhaustion) 1, | 
| 20046 | 474 | ALLGOALS (fn i => tac i (i-1))]) | 
| 5177 | 475 | end; | 
| 476 | ||
| 477 | val nchotomys = | |
| 478 | map prove_nchotomy (DatatypeProp.make_nchotomys descr sorts ~~ casedist_thms) | |
| 479 | ||
| 8436 | 480 | in thy |> store_thms "nchotomy" new_type_names nchotomys end; | 
| 5177 | 481 | |
| 482 | fun prove_case_congs new_type_names descr sorts nchotomys case_thms thy = | |
| 483 | let | |
| 484 | fun prove_case_cong ((t, nchotomy), case_rewrites) = | |
| 485 | let | |
| 486 |         val (Const ("==>", _) $ tm $ _) = t;
 | |
| 487 |         val (Const ("Trueprop", _) $ (Const ("op =", _) $ _ $ Ma)) = tm;
 | |
| 6394 | 488 | val cert = cterm_of (Theory.sign_of thy); | 
| 5177 | 489 | val nchotomy' = nchotomy RS spec; | 
| 490 | val nchotomy'' = cterm_instantiate | |
| 491 | [(cert (hd (add_term_vars (concl_of nchotomy', []))), cert Ma)] nchotomy' | |
| 492 | in | |
| 20046 | 493 | Goal.prove_global thy [] (Logic.strip_imp_prems t) (Logic.strip_imp_concl t) | 
| 17985 | 494 | (fn prems => | 
| 495 | let val simplify = asm_simp_tac (HOL_ss addsimps (prems @ case_rewrites)) | |
| 496 | in EVERY [simp_tac (HOL_ss addsimps [hd prems]) 1, | |
| 497 | cut_facts_tac [nchotomy''] 1, | |
| 498 | REPEAT (etac disjE 1 THEN REPEAT (etac exE 1) THEN simplify 1), | |
| 499 | REPEAT (etac exE 1) THEN simplify 1 (* Get last disjunct *)] | |
| 20046 | 500 | end) | 
| 5177 | 501 | end; | 
| 502 | ||
| 503 | val case_congs = map prove_case_cong (DatatypeProp.make_case_congs | |
| 504 | new_type_names descr sorts thy ~~ nchotomys ~~ case_thms) | |
| 505 | ||
| 8436 | 506 | in thy |> store_thms "case_cong" new_type_names case_congs end; | 
| 5177 | 507 | |
| 508 | end; |