1 (* Title: HOL/Tools/Lifting/lifting_term.ML
4 Proves Quotient theorem.
7 signature LIFTING_TERM =
9 exception QUOT_THM of typ * typ * Pretty.T
10 exception PARAM_QUOT_THM of typ * Pretty.T
11 exception CHECK_RTY of typ * typ
13 val prove_quot_thm: Proof.context -> typ * typ -> thm
15 val abs_fun: Proof.context -> typ * typ -> term
17 val equiv_relation: Proof.context -> typ * typ -> term
19 val prove_param_quot_thm: Proof.context -> typ -> thm * (typ * thm) list
22 structure Lifting_Term: LIFTING_TERM =
28 exception QUOT_THM_INTERNAL of Pretty.T
29 exception QUOT_THM of typ * typ * Pretty.T
30 exception PARAM_QUOT_THM of typ * Pretty.T
31 exception CHECK_RTY of typ * typ
33 fun match ctxt err ty_pat ty =
35 val thy = Proof_Context.theory_of ctxt
37 Sign.typ_match thy (ty_pat, ty) Vartab.empty
38 handle Type.TYPE_MATCH => err ctxt ty_pat ty
41 fun equiv_match_err ctxt ty_pat ty =
43 val ty_pat_str = Syntax.string_of_typ ctxt ty_pat
44 val ty_str = Syntax.string_of_typ ctxt ty
46 raise QUOT_THM_INTERNAL (Pretty.block
47 [Pretty.str ("The quotient type " ^ quote ty_str),
49 Pretty.str ("and the quotient type pattern " ^ quote ty_pat_str),
51 Pretty.str "don't match."])
54 fun get_quot_thm ctxt s =
56 val thy = Proof_Context.theory_of ctxt
58 (case Lifting_Info.lookup_quotients ctxt s of
59 SOME qdata => Thm.transfer thy (#quot_thm qdata)
60 | NONE => raise QUOT_THM_INTERNAL (Pretty.block
61 [Pretty.str ("No quotient type " ^ quote s),
63 Pretty.str "found."]))
66 fun get_rel_quot_thm ctxt s =
68 val thy = Proof_Context.theory_of ctxt
70 (case Lifting_Info.lookup_quotmaps ctxt s of
71 SOME map_data => Thm.transfer thy (#rel_quot_thm map_data)
72 | NONE => raise QUOT_THM_INTERNAL (Pretty.block
73 [Pretty.str ("No relator for the type " ^ quote s),
75 Pretty.str "found."]))
78 fun is_id_quot thm = (prop_of thm = prop_of @{thm identity_quotient})
80 fun check_raw_types (provided_rty_name, rty_of_qty_name) qty_name =
81 if provided_rty_name <> rty_of_qty_name then
82 raise QUOT_THM_INTERNAL (Pretty.block
83 [Pretty.str ("The type " ^ quote provided_rty_name),
85 Pretty.str ("is not a raw type for the quotient type " ^ quote qty_name ^ ";"),
87 Pretty.str ("the correct raw type is " ^ quote rty_of_qty_name ^ ".")])
91 fun zip_Tvars ctxt type_name rty_Tvars qty_Tvars =
92 case try (get_rel_quot_thm ctxt) type_name of
93 NONE => rty_Tvars ~~ qty_Tvars
94 | SOME rel_quot_thm =>
96 fun quot_term_absT quot_term =
98 val (_, abs, _, _) = (dest_Quotient o HOLogic.dest_Trueprop) quot_term
103 fun equiv_univ_err ctxt ty_pat ty =
105 val ty_pat_str = Syntax.string_of_typ ctxt ty_pat
106 val ty_str = Syntax.string_of_typ ctxt ty
108 raise QUOT_THM_INTERNAL (Pretty.block
109 [Pretty.str ("The type " ^ quote ty_str),
111 Pretty.str ("and the relator type pattern " ^ quote ty_pat_str),
113 Pretty.str "don't unify."])
116 fun raw_match (TVar (v, S), T) subs =
117 (case Vartab.defined subs v of
118 false => Vartab.update_new (v, (S, T)) subs
120 | raw_match (Type (_, Ts), Type (_, Us)) subs =
121 raw_matches (Ts, Us) subs
122 | raw_match _ subs = subs
123 and raw_matches (T :: Ts, U :: Us) subs = raw_matches (Ts, Us) (raw_match (T, U) subs)
124 | raw_matches _ subs = subs
126 val rty = Type (type_name, rty_Tvars)
127 val qty = Type (type_name, qty_Tvars)
128 val rel_quot_thm_concl = (Logic.strip_imp_concl o prop_of) rel_quot_thm
129 val schematic_rel_absT = quot_term_absT rel_quot_thm_concl;
130 val ctxt' = Variable.declare_typ schematic_rel_absT ctxt
131 val thy = Proof_Context.theory_of ctxt'
132 val absT = rty --> qty
133 val schematic_absT = Logic.type_map (singleton (Variable.polymorphic ctxt')) absT
134 val maxidx = Term.maxidx_of_typs [schematic_rel_absT, schematic_absT]
135 val _ = Sign.typ_unify thy (schematic_rel_absT, schematic_absT) (Vartab.empty,maxidx)
136 handle Type.TUNIFY => equiv_univ_err ctxt schematic_rel_absT schematic_absT
137 val subs = raw_match (schematic_rel_absT, absT) Vartab.empty
138 val rel_quot_thm_prems = (Logic.strip_imp_prems o prop_of) rel_quot_thm
141 Envir.subst_type subs o
146 fun prove_schematic_quot_thm ctxt (rty, qty) =
148 (Type (s, tys), Type (s', tys')) =>
152 val args = map (prove_schematic_quot_thm ctxt) (zip_Tvars ctxt s tys tys')
154 if forall is_id_quot args
156 @{thm identity_quotient}
158 args MRSL (get_rel_quot_thm ctxt s)
162 val quot_thm = get_quot_thm ctxt s'
163 val (Type (rs, rtys), qty_pat) = quot_thm_rty_qty quot_thm
164 val _ = check_raw_types (s, rs) s'
165 val qtyenv = match ctxt equiv_match_err qty_pat qty
166 val rtys' = map (Envir.subst_type qtyenv) rtys
167 val args = map (prove_schematic_quot_thm ctxt) (tys ~~ rtys')
169 if forall is_id_quot args
174 val rel_quot_thm = args MRSL (get_rel_quot_thm ctxt s)
176 [rel_quot_thm, quot_thm] MRSL @{thm Quotient_compose}
179 | (_, Type (s', tys')) =>
180 (case try (get_quot_thm ctxt) s' of
183 val rty_pat = (fst o quot_thm_rty_qty) quot_thm
185 prove_schematic_quot_thm ctxt (rty_pat, qty)
189 val rty_pat = Type (s', map (fn _ => TFree ("a",[])) tys')
191 prove_schematic_quot_thm ctxt (rty_pat, qty)
193 | _ => @{thm identity_quotient})
194 handle QUOT_THM_INTERNAL pretty_msg => raise QUOT_THM (rty, qty, pretty_msg)
196 fun force_qty_type thy qty quot_thm =
198 val (_, qty_schematic) = quot_thm_rty_qty quot_thm
199 val match_env = Sign.typ_match thy (qty_schematic, qty) Vartab.empty
200 fun prep_ty thy (x, (S, ty)) =
201 (ctyp_of thy (TVar (x, S)), ctyp_of thy ty)
202 val ty_inst = Vartab.fold (cons o (prep_ty thy)) match_env []
204 Thm.instantiate (ty_inst, []) quot_thm
207 fun check_rty_type ctxt rty quot_thm =
209 val thy = Proof_Context.theory_of ctxt
210 val (rty_forced, _) = quot_thm_rty_qty quot_thm
211 val rty_schematic = Logic.type_map (singleton (Variable.polymorphic ctxt)) rty
212 val _ = Sign.typ_match thy (rty_schematic, rty_forced) Vartab.empty
213 handle Type.TYPE_MATCH => raise CHECK_RTY (rty_schematic, rty_forced)
219 The function tries to prove that rty and qty form a quotient.
221 Returns: Quotient theorem; an abstract type of the theorem is exactly
222 qty, a representation type of the theorem is an instance of rty in general.
225 fun prove_quot_thm ctxt (rty, qty) =
227 val thy = Proof_Context.theory_of ctxt
228 val schematic_quot_thm = prove_schematic_quot_thm ctxt (rty, qty)
229 val quot_thm = force_qty_type thy qty schematic_quot_thm
230 val _ = check_rty_type ctxt rty quot_thm
235 fun abs_fun ctxt (rty, qty) =
236 quot_thm_abs (prove_quot_thm ctxt (rty, qty))
238 fun equiv_relation ctxt (rty, qty) =
239 quot_thm_rel (prove_quot_thm ctxt (rty, qty))
241 fun get_fresh_Q_t ctxt =
243 val Q_t = Syntax.read_term ctxt "Trueprop (Quotient R Abs Rep T)"
244 val ctxt = Variable.declare_names Q_t ctxt
245 val frees_Q_t = Term.add_free_names Q_t []
246 val (_, ctxt) = Variable.variant_fixes frees_Q_t ctxt
251 fun prove_param_quot_thm ctxt ty =
253 fun generate (ty as Type (s, tys)) (table_ctxt as (table, ctxt)) =
257 val thy = Proof_Context.theory_of ctxt
258 val instantiated_id_quot_thm = instantiate' [SOME (ctyp_of thy ty)] [] @{thm identity_quotient}
260 (instantiated_id_quot_thm, (table, ctxt))
264 val (args, table_ctxt) = fold_map generate tys table_ctxt
266 (args MRSL (get_rel_quot_thm ctxt s), table_ctxt)
268 | generate (ty as (TVar _)) (table, ctxt) =
269 if AList.defined (op=) table ty
270 then (the (AList.lookup (op=) table ty), (table, ctxt))
273 val thy = Proof_Context.theory_of ctxt
274 val (Q_t, ctxt') = get_fresh_Q_t ctxt
275 val Q_thm = Thm.assume (cterm_of thy Q_t)
276 val table' = (ty, Q_thm)::table
278 (Q_thm, (table', ctxt'))
280 | generate _ _ = error "generate_param_quot_thm: TFree"
282 val (param_quot_thm, (table, _)) = generate ty ([], ctxt)
284 (param_quot_thm, rev table)
286 handle QUOT_THM_INTERNAL pretty_msg => raise PARAM_QUOT_THM (ty, pretty_msg)