5 |
5 |
6 *) |
6 *) |
7 |
7 |
8 signature QUOTIENT_TYPE = |
8 signature QUOTIENT_TYPE = |
9 sig |
9 sig |
10 val add_quotient_type: ((string list * binding * mixfix) * (typ * term)) * thm |
10 val add_quotient_type: ((string list * binding * mixfix) * (typ * term * bool)) * thm |
11 -> Proof.context -> (thm * thm) * local_theory |
11 -> Proof.context -> (thm * thm) * local_theory |
12 |
12 |
13 val quotient_type: ((string list * binding * mixfix) * (typ * term)) list |
13 val quotient_type: ((string list * binding * mixfix) * (typ * term * bool)) list |
14 -> Proof.context -> Proof.state |
14 -> Proof.context -> Proof.state |
15 |
15 |
16 val quotient_type_cmd: ((((string list * binding) * mixfix) * string) * string) list |
16 val quotient_type_cmd: ((((string list * binding) * mixfix) * string) * (bool * string)) list |
17 -> Proof.context -> Proof.state |
17 -> Proof.context -> Proof.state |
18 end; |
18 end; |
19 |
19 |
20 structure Quotient_Type: QUOTIENT_TYPE = |
20 structure Quotient_Type: QUOTIENT_TYPE = |
21 struct |
21 struct |
62 [("x", rty), ("c", HOLogic.mk_setT rty)] |
62 [("x", rty), ("c", HOLogic.mk_setT rty)] |
63 |> Variable.variant_frees lthy [rel] |
63 |> Variable.variant_frees lthy [rel] |
64 |> map Free |
64 |> map Free |
65 in |
65 in |
66 lambda c (HOLogic.exists_const rty $ |
66 lambda c (HOLogic.exists_const rty $ |
67 lambda x (HOLogic.mk_eq (c, (rel $ x)))) |
67 lambda x (HOLogic.mk_conj ((rel $ x $ x), (HOLogic.mk_eq (c, (rel $ x)))))) |
68 end |
68 end |
69 |
69 |
70 |
70 |
71 (* makes the new type definitions and proves non-emptyness *) |
71 (* makes the new type definitions and proves non-emptyness *) |
72 fun typedef_make (vs, qty_name, mx, rel, rty) lthy = |
72 fun typedef_make (vs, qty_name, mx, rel, rty) equiv_thm lthy = |
73 let |
73 let |
74 val typedef_tac = |
74 val typedef_tac = |
75 EVERY1 (map rtac [@{thm exI}, mem_def2, @{thm exI}, @{thm refl}]) |
75 EVERY1 (map rtac [@{thm part_equivp_typedef}, equiv_thm]) |
76 in |
76 in |
77 (* FIXME: purely local typedef causes at the moment |
77 (* FIXME: purely local typedef causes at the moment |
78 problems with type variables |
78 problems with type variables |
79 |
79 |
80 Typedef.add_typedef false NONE (qty_name, vs, mx) |
80 Typedef.add_typedef false NONE (qty_name, vs, mx) |
91 (* tactic to prove the quot_type theorem for the new type *) |
91 (* tactic to prove the quot_type theorem for the new type *) |
92 fun typedef_quot_type_tac equiv_thm ((_, typedef_info): Typedef.info) = |
92 fun typedef_quot_type_tac equiv_thm ((_, typedef_info): Typedef.info) = |
93 let |
93 let |
94 val rep_thm = #Rep typedef_info RS mem_def1 |
94 val rep_thm = #Rep typedef_info RS mem_def1 |
95 val rep_inv = #Rep_inverse typedef_info |
95 val rep_inv = #Rep_inverse typedef_info |
96 val abs_inv = mem_def2 RS #Abs_inverse typedef_info |
96 val abs_inv = #Abs_inverse typedef_info |
97 val rep_inj = #Rep_inject typedef_info |
97 val rep_inj = #Rep_inject typedef_info |
98 in |
98 in |
99 (rtac @{thm quot_type.intro} THEN' RANGE [ |
99 (rtac @{thm quot_type.intro} THEN' RANGE [ |
100 rtac equiv_thm, |
100 rtac equiv_thm, |
101 rtac rep_thm, |
101 rtac rep_thm, |
102 rtac rep_inv, |
102 rtac rep_inv, |
103 EVERY' (map rtac [abs_inv, @{thm exI}, @{thm refl}]), |
103 rtac abs_inv THEN' rtac mem_def2 THEN' atac, |
104 rtac rep_inj]) 1 |
104 rtac rep_inj]) 1 |
105 end |
105 end |
106 |
106 |
107 |
107 |
108 (* proves the quot_type theorem for the new type *) |
108 (* proves the quot_type theorem for the new type *) |
135 (K typedef_quotient_thm_tac) |
135 (K typedef_quotient_thm_tac) |
136 end |
136 end |
137 |
137 |
138 |
138 |
139 (* main function for constructing a quotient type *) |
139 (* main function for constructing a quotient type *) |
140 fun add_quotient_type (((vs, qty_name, mx), (rty, rel)), equiv_thm) lthy = |
140 fun add_quotient_type (((vs, qty_name, mx), (rty, rel, partial)), equiv_thm) lthy = |
141 let |
141 let |
|
142 val part_equiv = if partial then equiv_thm else equiv_thm RS @{thm equivp_implies_part_equivp} |
|
143 |
142 (* generates the typedef *) |
144 (* generates the typedef *) |
143 val ((qty_full_name, typedef_info), lthy1) = typedef_make (vs, qty_name, mx, rel, rty) lthy |
145 val ((qty_full_name, typedef_info), lthy1) = typedef_make (vs, qty_name, mx, rel, rty) part_equiv lthy |
144 |
146 |
145 (* abs and rep functions from the typedef *) |
147 (* abs and rep functions from the typedef *) |
146 val Abs_ty = #abs_type (#1 typedef_info) |
148 val Abs_ty = #abs_type (#1 typedef_info) |
147 val Rep_ty = #rep_type (#1 typedef_info) |
149 val Rep_ty = #rep_type (#1 typedef_info) |
148 val Abs_name = #Abs_name (#1 typedef_info) |
150 val Abs_name = #Abs_name (#1 typedef_info) |
160 |
162 |
161 val ((abs, abs_def), lthy2) = define (abs_name, NoSyn, abs_trm) lthy1 |
163 val ((abs, abs_def), lthy2) = define (abs_name, NoSyn, abs_trm) lthy1 |
162 val ((rep, rep_def), lthy3) = define (rep_name, NoSyn, rep_trm) lthy2 |
164 val ((rep, rep_def), lthy3) = define (rep_name, NoSyn, rep_trm) lthy2 |
163 |
165 |
164 (* quot_type theorem *) |
166 (* quot_type theorem *) |
165 val quot_thm = typedef_quot_type_thm (rel, Abs_const, Rep_const, equiv_thm, typedef_info) lthy3 |
167 val quot_thm = typedef_quot_type_thm (rel, Abs_const, Rep_const, part_equiv, typedef_info) lthy3 |
166 |
168 |
167 (* quotient theorem *) |
169 (* quotient theorem *) |
168 val quotient_thm = typedef_quotient_thm (rel, abs, rep, abs_def, rep_def, quot_thm) lthy3 |
170 val quotient_thm = typedef_quotient_thm (rel, abs, rep, abs_def, rep_def, quot_thm) lthy3 |
169 val quotient_thm_name = Binding.prefix_name "Quotient_" qty_name |
171 val quotient_thm_name = Binding.prefix_name "Quotient_" qty_name |
170 |
172 |
177 val lthy4 = Local_Theory.declaration true |
179 val lthy4 = Local_Theory.declaration true |
178 (fn phi => quotdata_update_gen qty_full_name (qinfo phi)) lthy3 |
180 (fn phi => quotdata_update_gen qty_full_name (qinfo phi)) lthy3 |
179 in |
181 in |
180 lthy4 |
182 lthy4 |
181 |> note (quotient_thm_name, quotient_thm, [intern_attr quotient_rules_add]) |
183 |> note (quotient_thm_name, quotient_thm, [intern_attr quotient_rules_add]) |
182 ||>> note (equiv_thm_name, equiv_thm, [intern_attr equiv_rules_add]) |
184 ||>> note (equiv_thm_name, equiv_thm, if partial then [] else [intern_attr equiv_rules_add]) |
183 end |
185 end |
184 |
186 |
185 |
187 |
186 (* sanity checks for the quotient type specifications *) |
188 (* sanity checks for the quotient type specifications *) |
187 fun sanity_check ((vs, qty_name, _), (rty, rel)) = |
189 fun sanity_check ((vs, qty_name, _), (rty, rel, _)) = |
188 let |
190 let |
189 val rty_tfreesT = map fst (Term.add_tfreesT rty []) |
191 val rty_tfreesT = map fst (Term.add_tfreesT rty []) |
190 val rel_tfrees = map fst (Term.add_tfrees rel []) |
192 val rel_tfrees = map fst (Term.add_tfrees rel []) |
191 val rel_frees = map fst (Term.add_frees rel []) |
193 val rel_frees = map fst (Term.add_frees rel []) |
192 val rel_vars = Term.add_vars rel [] |
194 val rel_vars = Term.add_vars rel [] |
221 in |
223 in |
222 if null errs then () else error (cat_lines errs) |
224 if null errs then () else error (cat_lines errs) |
223 end |
225 end |
224 |
226 |
225 (* check for existence of map functions *) |
227 (* check for existence of map functions *) |
226 fun map_check ctxt (_, (rty, _)) = |
228 fun map_check ctxt (_, (rty, _, _)) = |
227 let |
229 let |
228 val thy = ProofContext.theory_of ctxt |
230 val thy = ProofContext.theory_of ctxt |
229 |
231 |
230 fun map_check_aux rty warns = |
232 fun map_check_aux rty warns = |
231 case rty of |
233 case rty of |
261 let |
263 let |
262 (* sanity check *) |
264 (* sanity check *) |
263 val _ = List.app sanity_check quot_list |
265 val _ = List.app sanity_check quot_list |
264 val _ = List.app (map_check lthy) quot_list |
266 val _ = List.app (map_check lthy) quot_list |
265 |
267 |
266 fun mk_goal (rty, rel) = |
268 fun mk_goal (rty, rel, partial) = |
267 let |
269 let |
268 val equivp_ty = ([rty, rty] ---> @{typ bool}) --> @{typ bool} |
270 val equivp_ty = ([rty, rty] ---> @{typ bool}) --> @{typ bool} |
|
271 val const = if partial then @{const_name part_equivp} else @{const_name equivp} |
269 in |
272 in |
270 HOLogic.mk_Trueprop (Const (@{const_name equivp}, equivp_ty) $ rel) |
273 HOLogic.mk_Trueprop (Const (const, equivp_ty) $ rel) |
271 end |
274 end |
272 |
275 |
273 val goals = map (mk_goal o snd) quot_list |
276 val goals = map (mk_goal o snd) quot_list |
274 |
277 |
275 fun after_qed thms lthy = |
278 fun after_qed thms lthy = |
278 theorem after_qed goals lthy |
281 theorem after_qed goals lthy |
279 end |
282 end |
280 |
283 |
281 fun quotient_type_cmd specs lthy = |
284 fun quotient_type_cmd specs lthy = |
282 let |
285 let |
283 fun parse_spec ((((vs, qty_name), mx), rty_str), rel_str) lthy = |
286 fun parse_spec ((((vs, qty_name), mx), rty_str), (partial, rel_str)) lthy = |
284 let |
287 let |
285 val rty = Syntax.read_typ lthy rty_str |
288 val rty = Syntax.read_typ lthy rty_str |
286 val lthy1 = Variable.declare_typ rty lthy |
289 val lthy1 = Variable.declare_typ rty lthy |
287 val rel = |
290 val rel = |
288 Syntax.parse_term lthy1 rel_str |
291 Syntax.parse_term lthy1 rel_str |
289 |> Syntax.type_constraint (rty --> rty --> @{typ bool}) |
292 |> Syntax.type_constraint (rty --> rty --> @{typ bool}) |
290 |> Syntax.check_term lthy1 |
293 |> Syntax.check_term lthy1 |
291 val lthy2 = Variable.declare_term rel lthy1 |
294 val lthy2 = Variable.declare_term rel lthy1 |
292 in |
295 in |
293 (((vs, qty_name, mx), (rty, rel)), lthy2) |
296 (((vs, qty_name, mx), (rty, rel, partial)), lthy2) |
294 end |
297 end |
295 |
298 |
296 val (spec', lthy') = fold_map parse_spec specs lthy |
299 val (spec', lthy') = fold_map parse_spec specs lthy |
297 in |
300 in |
298 quotient_type spec' lthy' |
301 quotient_type spec' lthy' |
299 end |
302 end |
300 |
303 |
|
304 val partial = Scan.optional (Parse.reserved "partial" -- Parse.$$$ ":" >> K true) false |
|
305 |
301 val quotspec_parser = |
306 val quotspec_parser = |
302 Parse.and_list1 |
307 Parse.and_list1 |
303 ((Parse.type_args -- Parse.binding) -- |
308 ((Parse.type_args -- Parse.binding) -- |
304 Parse.opt_mixfix -- (Parse.$$$ "=" |-- Parse.typ) -- |
309 Parse.opt_mixfix -- (Parse.$$$ "=" |-- Parse.typ) -- |
305 (Parse.$$$ "/" |-- Parse.term)) |
310 (Parse.$$$ "/" |-- (partial -- Parse.term))) |
306 |
311 |
307 val _ = Keyword.keyword "/" |
312 val _ = Keyword.keyword "/" |
308 |
313 |
309 val _ = |
314 val _ = |
310 Outer_Syntax.local_theory_to_proof "quotient_type" |
315 Outer_Syntax.local_theory_to_proof "quotient_type" |