35 fun index_of_half_row _ 0 = 0 |
35 fun index_of_half_row _ 0 = 0 |
36 | index_of_half_row n j = index_of_half_row n (j - 1) + n - j; |
36 | index_of_half_row n j = index_of_half_row n (j - 1) + n - j; |
37 |
37 |
38 fun index_of_half_cell n j k = index_of_half_row n j + k - (j + 1); |
38 fun index_of_half_cell n j k = index_of_half_row n j + k - (j + 1); |
39 |
39 |
|
40 val mk_Trueprop_eq = HOLogic.mk_Trueprop o HOLogic.mk_eq; |
|
41 |
|
42 fun eta_expand_caseof_arg f xs = fold_rev Term.lambda xs (Term.list_comb (f, xs)); |
|
43 |
40 fun prepare_sugar prep_term (((raw_ctrs, raw_caseof), disc_names), sel_namess) no_defs_lthy = |
44 fun prepare_sugar prep_term (((raw_ctrs, raw_caseof), disc_names), sel_namess) no_defs_lthy = |
41 let |
45 let |
42 (* TODO: sanity checks on arguments *) |
46 (* TODO: sanity checks on arguments *) |
43 |
47 |
44 (* TODO: normalize types of constructors w.r.t. each other *) |
48 (* TODO: normalize types of constructors w.r.t. each other *) |
76 val ms = map length ctr_Tss; |
80 val ms = map length ctr_Tss; |
77 |
81 |
78 val caseofB = mk_caseof As B; |
82 val caseofB = mk_caseof As B; |
79 val caseofB_Ts = map (fn Ts => Ts ---> B) ctr_Tss; |
83 val caseofB_Ts = map (fn Ts => Ts ---> B) ctr_Tss; |
80 |
84 |
81 val (((((xss, yss), fs), (v, v')), p), names_lthy) = no_defs_lthy |> |
85 val (((((((xss, yss), fs), gs), (v, v')), w), p), names_lthy) = no_defs_lthy |> |
82 mk_Freess "x" ctr_Tss |
86 mk_Freess "x" ctr_Tss |
83 ||>> mk_Freess "y" ctr_Tss |
87 ||>> mk_Freess "y" ctr_Tss |
84 ||>> mk_Frees "f" caseofB_Ts |
88 ||>> mk_Frees "f" caseofB_Ts |
|
89 ||>> mk_Frees "g" caseofB_Ts |
85 ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "v") T |
90 ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "v") T |
|
91 ||>> yield_singleton (mk_Frees "w") T |
86 ||>> yield_singleton (mk_Frees "P") HOLogic.boolT; |
92 ||>> yield_singleton (mk_Frees "P") HOLogic.boolT; |
87 |
93 |
88 val xctrs = map2 (curry Term.list_comb) ctrs xss; |
94 val xctrs = map2 (curry Term.list_comb) ctrs xss; |
89 val yctrs = map2 (curry Term.list_comb) ctrs yss; |
95 val yctrs = map2 (curry Term.list_comb) ctrs yss; |
90 val eta_fs = map2 (fn f => fn xs => fold_rev Term.lambda xs (Term.list_comb (f, xs))) fs xss; |
96 |
|
97 val eta_fs = map2 eta_expand_caseof_arg fs xss; |
|
98 val eta_gs = map2 eta_expand_caseof_arg gs xss; |
91 |
99 |
92 val exist_xs_v_eq_ctrs = |
100 val exist_xs_v_eq_ctrs = |
93 map2 (fn xctr => fn xs => list_exists_free xs (HOLogic.mk_eq (v, xctr))) xctrs xss; |
101 map2 (fn xctr => fn xs => list_exists_free xs (HOLogic.mk_eq (v, xctr))) xctrs xss; |
94 |
102 |
95 fun mk_caseof_args k xs x T = |
103 fun mk_sel_caseof_args k xs x T = |
96 map2 (fn Ts => fn i => if i = k then fold_rev Term.lambda xs x else mk_undef T Ts) ctr_Tss ks; |
104 map2 (fn Ts => fn i => if i = k then fold_rev Term.lambda xs x else mk_undef T Ts) ctr_Tss ks; |
97 |
105 |
98 fun disc_spec b exist_xs_v_eq_ctr = |
106 fun disc_spec b exist_xs_v_eq_ctr = |
99 HOLogic.mk_Trueprop (HOLogic.mk_eq (Free (Binding.name_of b, T --> HOLogic.boolT) $ v, |
107 mk_Trueprop_eq (Free (Binding.name_of b, T --> HOLogic.boolT) $ v, exist_xs_v_eq_ctr); |
100 exist_xs_v_eq_ctr)); |
|
101 |
108 |
102 fun sel_spec b x xs k = |
109 fun sel_spec b x xs k = |
103 let val T' = fastype_of x in |
110 let val T' = fastype_of x in |
104 HOLogic.mk_Trueprop (HOLogic.mk_eq (Free (Binding.name_of b, T --> T') $ v, |
111 mk_Trueprop_eq (Free (Binding.name_of b, T --> T') $ v, |
105 Term.list_comb (mk_caseof As T', mk_caseof_args k xs x T') $ v)) |
112 Term.list_comb (mk_caseof As T', mk_sel_caseof_args k xs x T') $ v) |
106 end; |
113 end; |
107 |
114 |
108 val (((raw_discs, (_, raw_disc_defs)), (raw_selss, (_, raw_sel_defss))), (lthy', lthy)) = |
115 val (((raw_discs, (_, raw_disc_defs)), (raw_selss, (_, raw_sel_defss))), (lthy', lthy)) = |
109 no_defs_lthy |
116 no_defs_lthy |
110 |> apfst (apsnd split_list o split_list) o fold_map2 (fn b => fn exist_xs_v_eq_ctr => |
117 |> apfst (apsnd split_list o split_list) o fold_map2 (fn b => fn exist_xs_v_eq_ctr => |
129 Term.subst_atomic_types (snd (dest_Type (domain_type (fastype_of t))) ~~ Ts) t; |
136 Term.subst_atomic_types (snd (dest_Type (domain_type (fastype_of t))) ~~ Ts) t; |
130 |
137 |
131 val discs = map (mk_disc_or_sel As) discs0; |
138 val discs = map (mk_disc_or_sel As) discs0; |
132 val selss = map (map (mk_disc_or_sel As)) selss0; |
139 val selss = map (map (mk_disc_or_sel As)) selss0; |
133 |
140 |
134 fun mk_imp_p Q = Logic.list_implies (Q, HOLogic.mk_Trueprop p); |
141 fun mk_imp_p Qs = Logic.list_implies (Qs, HOLogic.mk_Trueprop p); |
135 |
142 |
136 val goal_exhaust = |
143 val goal_exhaust = |
137 let |
144 let fun mk_prem xctr xs = fold_rev Logic.all xs (mk_imp_p [mk_Trueprop_eq (v, xctr)]) in |
138 fun mk_prem xctr xs = |
|
139 fold_rev Logic.all xs (mk_imp_p [HOLogic.mk_Trueprop (HOLogic.mk_eq (v, xctr))]); |
|
140 in |
|
141 mk_imp_p (map2 mk_prem xctrs xss) |
145 mk_imp_p (map2 mk_prem xctrs xss) |
142 end; |
146 end; |
143 |
147 |
144 val goal_injects = |
148 val goal_injects = |
145 let |
149 let |
146 fun mk_goal _ _ [] [] = NONE |
150 fun mk_goal _ _ [] [] = NONE |
147 | mk_goal xctr yctr xs ys = |
151 | mk_goal xctr yctr xs ys = |
148 SOME (HOLogic.mk_Trueprop (HOLogic.mk_eq |
152 SOME (mk_Trueprop_eq (HOLogic.mk_eq (xctr, yctr), |
149 (HOLogic.mk_eq (xctr, yctr), |
153 Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_eq) xs ys))); |
150 Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_eq) xs ys)))); |
|
151 in |
154 in |
152 map_filter I (map4 mk_goal xctrs yctrs xss yss) |
155 map_filter I (map4 mk_goal xctrs yctrs xss yss) |
153 end; |
156 end; |
154 |
157 |
155 val goal_half_distincts = |
158 val goal_half_distincts = |
156 map (HOLogic.mk_Trueprop o HOLogic.mk_not o HOLogic.mk_eq) (mk_half_pairs xctrs); |
159 map (HOLogic.mk_Trueprop o HOLogic.mk_not o HOLogic.mk_eq) (mk_half_pairs xctrs); |
157 |
160 |
158 val goal_cases = |
161 val goal_cases = |
159 let |
162 let |
160 val lhs0 = Term.list_comb (caseofB, eta_fs); |
163 val lhs0 = Term.list_comb (caseofB, eta_fs); |
161 fun mk_goal xctr xs f = |
164 fun mk_goal xctr xs f = mk_Trueprop_eq (lhs0 $ xctr, Term.list_comb (f, xs)); |
162 HOLogic.mk_Trueprop (HOLogic.mk_eq (lhs0 $ xctr, Term.list_comb (f, xs))); |
|
163 in |
165 in |
164 map3 mk_goal xctrs xss fs |
166 map3 mk_goal xctrs xss fs |
165 end; |
167 end; |
166 |
168 |
167 val goals = [[goal_exhaust], goal_injects, goal_half_distincts, goal_cases]; |
169 val goals = [[goal_exhaust], goal_injects, goal_half_distincts, goal_cases]; |
168 |
170 |
169 fun after_qed thmss lthy = |
171 fun after_qed thmss lthy = |
170 let |
172 let |
171 val [[exhaust_thm], inject_thms, half_distinct_thms, case_thms] = thmss; |
173 val [[exhaust_thm], inject_thms, half_distinct_thms, case_thms] = thmss; |
|
174 |
|
175 val exhaust_thm' = |
|
176 let val Tinst = map (pairself (certifyT lthy)) (map Logic.varifyT_global As ~~ As) in |
|
177 Drule.instantiate' [] [SOME (certify lthy v)] |
|
178 (Thm.instantiate (Tinst, []) (Drule.zero_var_indexes exhaust_thm)) |
|
179 end; |
172 |
180 |
173 val other_half_distinct_thms = map (fn thm => thm RS not_sym) half_distinct_thms; |
181 val other_half_distinct_thms = map (fn thm => thm RS not_sym) half_distinct_thms; |
174 |
182 |
175 val nchotomy_thm = |
183 val nchotomy_thm = |
176 let |
184 let |
187 let |
195 let |
188 val T = fastype_of x; |
196 val T = fastype_of x; |
189 val cTs = |
197 val cTs = |
190 map ((fn T' => certifyT lthy (if T' = B then T else T')) o TFree) |
198 map ((fn T' => certifyT lthy (if T' = B then T else T')) o TFree) |
191 (rev (Term.add_tfrees goal_case [])); |
199 (rev (Term.add_tfrees goal_case [])); |
192 val cxs = map (certify lthy) (mk_caseof_args k xs x T); |
200 val cxs = map (certify lthy) (mk_sel_caseof_args k xs x T); |
193 in |
201 in |
194 Local_Defs.fold lthy [sel_def] |
202 Local_Defs.fold lthy [sel_def] |
195 (Drule.instantiate' (map SOME cTs) (map SOME cxs) case_thm) |
203 (Drule.instantiate' (map SOME cTs) (map SOME cxs) case_thm) |
196 end; |
204 end; |
197 fun mk_thms k xs goal_case case_thm sel_defs = |
205 fun mk_thms k xs goal_case case_thm sel_defs = |
253 |
261 |
254 val ctr_sel_thms = |
262 val ctr_sel_thms = |
255 let |
263 let |
256 fun mk_goal ctr disc sels = |
264 fun mk_goal ctr disc sels = |
257 Logic.all v (Logic.mk_implies (HOLogic.mk_Trueprop (disc $ v), |
265 Logic.all v (Logic.mk_implies (HOLogic.mk_Trueprop (disc $ v), |
258 HOLogic.mk_Trueprop (HOLogic.mk_eq ((null sels ? swap) |
266 mk_Trueprop_eq ((null sels ? swap) |
259 (Term.list_comb (ctr, map (fn sel => sel $ v) sels), v))))); |
267 (Term.list_comb (ctr, map (fn sel => sel $ v) sels), v)))); |
260 val goals = map3 mk_goal ctrs discs selss; |
268 val goals = map3 mk_goal ctrs discs selss; |
261 in |
269 in |
262 map4 (fn goal => fn m => fn discD => fn sel_thms => |
270 map4 (fn goal => fn m => fn discD => fn sel_thms => |
263 Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} => |
271 Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} => |
264 mk_ctr_sel_tac ctxt m discD sel_thms)) |
272 mk_ctr_sel_tac ctxt m discD sel_thms)) |
273 Const (@{const_name If}, HOLogic.boolT --> B --> B --> B) $ |
281 Const (@{const_name If}, HOLogic.boolT --> B --> B --> B) $ |
274 (disc $ v) $ mk_core f sels $ mk_rhs discs fs selss; |
282 (disc $ v) $ mk_core f sels $ mk_rhs discs fs selss; |
275 |
283 |
276 val lhs = Term.list_comb (caseofB, eta_fs) $ v; |
284 val lhs = Term.list_comb (caseofB, eta_fs) $ v; |
277 val rhs = mk_rhs discs fs selss; |
285 val rhs = mk_rhs discs fs selss; |
278 val goal = HOLogic.mk_Trueprop (HOLogic.mk_eq (lhs, rhs)); |
286 val goal = mk_Trueprop_eq (lhs, rhs); |
279 |
|
280 val Tinst = map (pairself (certifyT lthy)) (map Logic.varifyT_global As ~~ As); |
|
281 val exhaust_thm' = |
|
282 Drule.instantiate' [] [SOME (certify lthy v)] |
|
283 (Thm.instantiate (Tinst, []) (Drule.zero_var_indexes exhaust_thm)); |
|
284 in |
287 in |
285 Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} => |
288 Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} => |
286 mk_case_disc_tac ctxt exhaust_thm' case_thms disc_thms sel_thmss) |
289 mk_case_disc_tac ctxt exhaust_thm' case_thms disc_thms sel_thmss) |
287 |> singleton (Proof_Context.export names_lthy lthy) |
290 |> singleton (Proof_Context.export names_lthy lthy) |
288 end; |
291 end; |
289 |
292 |
290 val case_cong_thm = TrueI; |
293 val case_cong_thm = |
|
294 let |
|
295 fun mk_prem xctr xs f g = |
|
296 fold_rev Logic.all xs (Logic.mk_implies (mk_Trueprop_eq (v, xctr), |
|
297 mk_Trueprop_eq (f, g))); |
|
298 fun mk_caseof_term fs v = Term.list_comb (caseofB, fs) $ v; |
|
299 |
|
300 val goal = |
|
301 Logic.list_implies (mk_Trueprop_eq (v, w) :: map4 mk_prem xctrs xss fs gs, |
|
302 mk_Trueprop_eq (mk_caseof_term eta_fs v, mk_caseof_term eta_gs w)); |
|
303 in |
|
304 Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} => |
|
305 mk_case_cong_tac ctxt exhaust_thm' case_thms) |
|
306 |> singleton (Proof_Context.export names_lthy lthy) |
|
307 end; |
291 |
308 |
292 val weak_case_cong_thms = TrueI; |
309 val weak_case_cong_thms = TrueI; |
293 |
310 |
294 val split_thms = []; |
311 val split_thms = []; |
295 |
312 |