| author | desharna | 
| Mon, 10 Oct 2022 19:07:54 +0200 | |
| changeset 76256 | 207b6fcfc47d | 
| parent 74561 | 8e6c973003c8 | 
| child 78095 | bc42c074e58f | 
| permissions | -rw-r--r-- | 
| 55467 
a5c9002bc54d
renamed 'enriched_type' to more informative 'functor' (following the renaming of enriched type constructors to bounded natural functors)
 blanchet parents: 
51717diff
changeset | 1 | (* Title: HOL/Tools/functor.ML | 
| 40582 | 2 | Author: Florian Haftmann, TU Muenchen | 
| 3 | ||
| 40968 
a6fcd305f7dc
replace `type_mapper` by the more adequate `type_lifting`
 haftmann parents: 
40857diff
changeset | 4 | Functorial structure of types. | 
| 40582 | 5 | *) | 
| 6 | ||
| 55467 
a5c9002bc54d
renamed 'enriched_type' to more informative 'functor' (following the renaming of enriched type constructors to bounded natural functors)
 blanchet parents: 
51717diff
changeset | 7 | signature FUNCTOR = | 
| 40582 | 8 | sig | 
| 41388 | 9 | val find_atomic: Proof.context -> typ -> (typ * (bool * bool)) list | 
| 10 | val construct_mapper: Proof.context -> (string * bool -> term) | |
| 40582 | 11 | -> bool -> typ -> typ -> term | 
| 60488 | 12 | val functor_: string option -> term -> local_theory -> Proof.state | 
| 55467 
a5c9002bc54d
renamed 'enriched_type' to more informative 'functor' (following the renaming of enriched type constructors to bounded natural functors)
 blanchet parents: 
51717diff
changeset | 13 | val functor_cmd: string option -> string -> Proof.context -> Proof.state | 
| 40582 | 14 | type entry | 
| 41390 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 15 | val entries: Proof.context -> entry list Symtab.table | 
| 40582 | 16 | end; | 
| 17 | ||
| 55467 
a5c9002bc54d
renamed 'enriched_type' to more informative 'functor' (following the renaming of enriched type constructors to bounded natural functors)
 blanchet parents: 
51717diff
changeset | 18 | structure Functor : FUNCTOR = | 
| 40582 | 19 | struct | 
| 20 | ||
| 41395 | 21 | (* bookkeeping *) | 
| 22 | ||
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 23 | val compN = "comp"; | 
| 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 24 | val idN = "id"; | 
| 40611 | 25 | val compositionalityN = "compositionality"; | 
| 40594 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 26 | val identityN = "identity"; | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 27 | |
| 41387 | 28 | type entry = { mapper: term, variances: (sort * (bool * bool)) list,
 | 
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 29 | comp: thm, id: thm }; | 
| 40582 | 30 | |
| 41472 
f6ab14e61604
misc tuning and comments based on review of Theory_Data, Proof_Data, Generic_Data usage;
 wenzelm parents: 
41395diff
changeset | 31 | structure Data = Generic_Data | 
| 
f6ab14e61604
misc tuning and comments based on review of Theory_Data, Proof_Data, Generic_Data usage;
 wenzelm parents: 
41395diff
changeset | 32 | ( | 
| 41390 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 33 | type T = entry list Symtab.table | 
| 40582 | 34 | val empty = Symtab.empty | 
| 41472 
f6ab14e61604
misc tuning and comments based on review of Theory_Data, Proof_Data, Generic_Data usage;
 wenzelm parents: 
41395diff
changeset | 35 | fun merge data = Symtab.merge (K true) data | 
| 40582 | 36 | ); | 
| 37 | ||
| 41388 | 38 | val entries = Data.get o Context.Proof; | 
| 40582 | 39 | |
| 40 | ||
| 41 | (* type analysis *) | |
| 42 | ||
| 59838 | 43 | fun term_with_typ ctxt T t = | 
| 44 | Envir.subst_term_types | |
| 45 | (Sign.typ_match (Proof_Context.theory_of ctxt) (fastype_of t, T) Vartab.empty) t; | |
| 41389 | 46 | |
| 41388 | 47 | fun find_atomic ctxt T = | 
| 40582 | 48 | let | 
| 41390 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 49 | val variances_of = Option.map #variances o try hd o Symtab.lookup_list (entries ctxt); | 
| 40582 | 50 | fun add_variance is_contra T = | 
| 51 | AList.map_default (op =) (T, (false, false)) | |
| 52 | ((if is_contra then apsnd else apfst) (K true)); | |
| 53 | fun analyze' is_contra (_, (co, contra)) T = | |
| 54 | (if co then analyze is_contra T else I) | |
| 55 | #> (if contra then analyze (not is_contra) T else I) | |
| 56 | and analyze is_contra (T as Type (tyco, Ts)) = (case variances_of tyco | |
| 57 | of NONE => add_variance is_contra T | |
| 58 | | SOME variances => fold2 (analyze' is_contra) variances Ts) | |
| 59 | | analyze is_contra T = add_variance is_contra T; | |
| 60 | in analyze false T [] end; | |
| 61 | ||
| 41388 | 62 | fun construct_mapper ctxt atomic = | 
| 40582 | 63 | let | 
| 41390 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 64 | val lookup = hd o Symtab.lookup_list (entries ctxt); | 
| 40582 | 65 | fun constructs is_contra (_, (co, contra)) T T' = | 
| 66 | (if co then [construct is_contra T T'] else []) | |
| 67 | @ (if contra then [construct (not is_contra) T T'] else []) | |
| 68 | and construct is_contra (T as Type (tyco, Ts)) (T' as Type (_, Ts')) = | |
| 69 | let | |
| 41388 | 70 |             val { mapper = raw_mapper, variances, ... } = lookup tyco;
 | 
| 40582 | 71 | val args = maps (fn (arg_pattern, (T, T')) => | 
| 72 | constructs is_contra arg_pattern T T') | |
| 73 | (variances ~~ (Ts ~~ Ts')); | |
| 74 | val (U, U') = if is_contra then (T', T) else (T, T'); | |
| 41388 | 75 | val mapper = term_with_typ ctxt (map fastype_of args ---> U --> U') raw_mapper; | 
| 76 | in list_comb (mapper, args) end | |
| 40582 | 77 | | construct is_contra (TFree (v, _)) (TFree _) = atomic (v, is_contra); | 
| 78 | in construct end; | |
| 79 | ||
| 80 | ||
| 81 | (* mapper properties *) | |
| 82 | ||
| 51717 
9e7d1c139569
simplifier uses proper Proof.context instead of historic type simpset;
 wenzelm parents: 
51551diff
changeset | 83 | val compositionality_ss = | 
| 69593 | 84 |   simpset_of (put_simpset HOL_basic_ss \<^context> addsimps [Simpdata.mk_eq @{thm comp_def}]);
 | 
| 41387 | 85 | |
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 86 | fun make_comp_prop ctxt variances (tyco, mapper) = | 
| 40582 | 87 | let | 
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 88 | val sorts = map fst variances | 
| 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 89 | val (((vs3, vs2), vs1), _) = ctxt | 
| 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 90 | |> Variable.invent_types sorts | 
| 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 91 | ||>> Variable.invent_types sorts | 
| 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 92 | ||>> Variable.invent_types sorts | 
| 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 93 | val (Ts1, Ts2, Ts3) = (map TFree vs1, map TFree vs2, map TFree vs3); | 
| 40582 | 94 | fun mk_argT ((T, T'), (_, (co, contra))) = | 
| 95 | (if co then [(T --> T')] else []) | |
| 96 | @ (if contra then [(T' --> T)] else []); | |
| 97 | val contras = maps (fn (_, (co, contra)) => | |
| 98 | (if co then [false] else []) @ (if contra then [true] else [])) variances; | |
| 99 | val Ts21 = maps mk_argT ((Ts2 ~~ Ts1) ~~ variances); | |
| 100 | val Ts32 = maps mk_argT ((Ts3 ~~ Ts2) ~~ variances); | |
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 101 | fun invents n k nctxt = | 
| 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 102 | let | 
| 43329 
84472e198515
tuned signature: Name.invent and Name.invent_names;
 wenzelm parents: 
42388diff
changeset | 103 | val names = Name.invent nctxt n k; | 
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 104 | in (names, fold Name.declare names nctxt) end; | 
| 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 105 | val ((names21, names32), nctxt) = Variable.names_of ctxt | 
| 40582 | 106 | |> invents "f" (length Ts21) | 
| 107 | ||>> invents "f" (length Ts32); | |
| 108 | val T1 = Type (tyco, Ts1); | |
| 109 | val T2 = Type (tyco, Ts2); | |
| 110 | val T3 = Type (tyco, Ts3); | |
| 111 | val (args21, args32) = (names21 ~~ Ts21, names32 ~~ Ts32); | |
| 112 | val args31 = map2 (fn is_contra => fn ((f21, T21), (f32, T32)) => | |
| 113 | if not is_contra then | |
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 114 | HOLogic.mk_comp (Free (f21, T21), Free (f32, T32)) | 
| 40582 | 115 | else | 
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 116 | HOLogic.mk_comp (Free (f32, T32), Free (f21, T21)) | 
| 40582 | 117 | ) contras (args21 ~~ args32) | 
| 41395 | 118 | fun mk_mapper T T' args = list_comb | 
| 119 | (term_with_typ ctxt (map fastype_of args ---> T --> T') mapper, args); | |
| 41387 | 120 | val mapper21 = mk_mapper T2 T1 (map Free args21); | 
| 121 | val mapper32 = mk_mapper T3 T2 (map Free args32); | |
| 122 | val mapper31 = mk_mapper T3 T1 args31; | |
| 41395 | 123 | val eq1 = (HOLogic.mk_Trueprop o HOLogic.mk_eq) | 
| 124 | (HOLogic.mk_comp (mapper21, mapper32), mapper31); | |
| 43329 
84472e198515
tuned signature: Name.invent and Name.invent_names;
 wenzelm parents: 
42388diff
changeset | 125 | val x = Free (the_single (Name.invent nctxt (Long_Name.base_name tyco) 1), T3) | 
| 41395 | 126 | val eq2 = (HOLogic.mk_Trueprop o HOLogic.mk_eq) | 
| 127 | (mapper21 $ (mapper32 $ x), mapper31 $ x); | |
| 41387 | 128 | val comp_prop = fold_rev Logic.all (map Free (args21 @ args32)) eq1; | 
| 129 | val compositionality_prop = fold_rev Logic.all (map Free (args21 @ args32) @ [x]) eq2; | |
| 61841 
4d3527b94f2a
more general types Proof.method / context_tactic;
 wenzelm parents: 
60488diff
changeset | 130 | fun prove_compositionality ctxt comp_thm = | 
| 
4d3527b94f2a
more general types Proof.method / context_tactic;
 wenzelm parents: 
60488diff
changeset | 131 | Goal.prove_sorry ctxt [] [] compositionality_prop | 
| 
4d3527b94f2a
more general types Proof.method / context_tactic;
 wenzelm parents: 
60488diff
changeset | 132 |         (K (ALLGOALS (Method.insert_tac ctxt [@{thm fun_cong} OF [comp_thm]]
 | 
| 
4d3527b94f2a
more general types Proof.method / context_tactic;
 wenzelm parents: 
60488diff
changeset | 133 | THEN' Simplifier.asm_lr_simp_tac (put_simpset compositionality_ss ctxt) | 
| 
4d3527b94f2a
more general types Proof.method / context_tactic;
 wenzelm parents: 
60488diff
changeset | 134 | THEN_ALL_NEW (Goal.assume_rule_tac ctxt)))); | 
| 41387 | 135 | in (comp_prop, prove_compositionality) end; | 
| 136 | ||
| 51717 
9e7d1c139569
simplifier uses proper Proof.context instead of historic type simpset;
 wenzelm parents: 
51551diff
changeset | 137 | val identity_ss = | 
| 69593 | 138 |   simpset_of (put_simpset HOL_basic_ss \<^context> addsimps [Simpdata.mk_eq @{thm id_def}]);
 | 
| 40582 | 139 | |
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 140 | fun make_id_prop ctxt variances (tyco, mapper) = | 
| 40582 | 141 | let | 
| 46810 | 142 | val (vs, _) = Variable.invent_types (map fst variances) ctxt; | 
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 143 | val Ts = map TFree vs; | 
| 40582 | 144 | fun bool_num b = if b then 1 else 0; | 
| 145 | fun mk_argT (T, (_, (co, contra))) = | |
| 41387 | 146 | replicate (bool_num co + bool_num contra) T | 
| 147 | val arg_Ts = maps mk_argT (Ts ~~ variances) | |
| 40582 | 148 | val T = Type (tyco, Ts); | 
| 41387 | 149 | val head = term_with_typ ctxt (map (fn T => T --> T) arg_Ts ---> T --> T) mapper; | 
| 150 | val lhs1 = list_comb (head, map (HOLogic.id_const) arg_Ts); | |
| 151 |     val lhs2 = list_comb (head, map (fn arg_T => Abs ("x", arg_T, Bound 0)) arg_Ts);
 | |
| 152 | val rhs = HOLogic.id_const T; | |
| 59058 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
55467diff
changeset | 153 | val (id_prop, identity_prop) = | 
| 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
55467diff
changeset | 154 | apply2 (HOLogic.mk_Trueprop o HOLogic.mk_eq o rpair rhs) (lhs1, lhs2); | 
| 61841 
4d3527b94f2a
more general types Proof.method / context_tactic;
 wenzelm parents: 
60488diff
changeset | 155 | fun prove_identity ctxt id_thm = | 
| 
4d3527b94f2a
more general types Proof.method / context_tactic;
 wenzelm parents: 
60488diff
changeset | 156 | Goal.prove_sorry ctxt [] [] identity_prop | 
| 
4d3527b94f2a
more general types Proof.method / context_tactic;
 wenzelm parents: 
60488diff
changeset | 157 | (K (ALLGOALS (Method.insert_tac ctxt [id_thm] THEN' | 
| 
4d3527b94f2a
more general types Proof.method / context_tactic;
 wenzelm parents: 
60488diff
changeset | 158 | Simplifier.asm_lr_simp_tac (put_simpset identity_ss ctxt)))); | 
| 41387 | 159 | in (id_prop, prove_identity) end; | 
| 40582 | 160 | |
| 161 | ||
| 40597 | 162 | (* analyzing and registering mappers *) | 
| 40582 | 163 | |
| 55467 
a5c9002bc54d
renamed 'enriched_type' to more informative 'functor' (following the renaming of enriched type constructors to bounded natural functors)
 blanchet parents: 
51717diff
changeset | 164 | fun consume _ _ [] = (false, []) | 
| 40594 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 165 | | consume eq x (ys as z :: zs) = if eq (x, z) then (true, zs) else (false, ys); | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 166 | |
| 40587 | 167 | fun split_mapper_typ "fun" T = | 
| 168 | let | |
| 169 | val (Ts', T') = strip_type T; | |
| 170 | val (Ts'', T'') = split_last Ts'; | |
| 171 | val (Ts''', T''') = split_last Ts''; | |
| 172 | in (Ts''', T''', T'' --> T') end | |
| 46810 | 173 | | split_mapper_typ _ T = | 
| 40587 | 174 | let | 
| 175 | val (Ts', T') = strip_type T; | |
| 176 | val (Ts'', T'') = split_last Ts'; | |
| 177 | in (Ts'', T'', T') end; | |
| 178 | ||
| 46852 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 179 | fun analyze_mapper ctxt input_mapper = | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 180 | let | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 181 | val T = fastype_of input_mapper; | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 182 | val _ = Type.no_tvars T; | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 183 | val _ = | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 184 | if null (subtract (op =) (Term.add_tfreesT T []) (Term.add_tfrees input_mapper [])) | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 185 | then () | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 186 |       else error ("Illegal additional type variable(s) in term: " ^ Syntax.string_of_term ctxt input_mapper);
 | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 187 | val _ = | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 188 | if null (Term.add_vars (singleton | 
| 70308 | 189 | (Variable.export_terms (Proof_Context.augment input_mapper ctxt) ctxt) input_mapper) []) | 
| 46852 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 190 | then () | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 191 |       else error ("Illegal locally free variable(s) in term: "
 | 
| 63568 | 192 | ^ Syntax.string_of_term ctxt input_mapper); | 
| 46852 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 193 | val mapper = singleton (Variable.polymorphic ctxt) input_mapper; | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 194 | val _ = | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 195 | if null (Term.add_tfreesT (fastype_of mapper) []) then () | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 196 |       else error ("Illegal locally fixed type variable(s) in type: " ^ Syntax.string_of_typ ctxt T);
 | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 197 | fun add_tycos (Type (tyco, Ts)) = insert (op =) tyco #> fold add_tycos Ts | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 198 | | add_tycos _ = I; | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 199 | val tycos = add_tycos T []; | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 200 | val tyco = if tycos = ["fun"] then "fun" | 
| 67405 
e9ab4ad7bd15
uniform use of Standard ML op-infix -- eliminated warnings;
 wenzelm parents: 
67399diff
changeset | 201 | else case remove (op =) "fun" tycos | 
| 46852 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 202 | of [tyco] => tyco | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 203 |         | _ => error ("Bad number of type constructors: " ^ Syntax.string_of_typ ctxt T);
 | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 204 | in (mapper, T, tyco) end; | 
| 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 205 | |
| 41390 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 206 | fun analyze_variances ctxt tyco T = | 
| 40587 | 207 | let | 
| 41390 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 208 |     fun bad_typ () = error ("Bad mapper type: " ^ Syntax.string_of_typ ctxt T);
 | 
| 40587 | 209 | val (Ts, T1, T2) = split_mapper_typ tyco T | 
| 210 | handle List.Empty => bad_typ (); | |
| 59058 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
55467diff
changeset | 211 | val _ = | 
| 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
55467diff
changeset | 212 | apply2 ((fn tyco' => if tyco' = tyco then () else bad_typ ()) o fst o dest_Type) (T1, T2) | 
| 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
55467diff
changeset | 213 | handle TYPE _ => bad_typ (); | 
| 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
55467diff
changeset | 214 | val (vs1, vs2) = | 
| 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
55467diff
changeset | 215 | apply2 (map dest_TFree o snd o dest_Type) (T1, T2) | 
| 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
55467diff
changeset | 216 | handle TYPE _ => bad_typ (); | 
| 40587 | 217 | val _ = if has_duplicates (eq_fst (op =)) (vs1 @ vs2) | 
| 218 | then bad_typ () else (); | |
| 46810 | 219 | fun check_variance_pair (var1 as (_, sort1), var2 as (_, sort2)) = | 
| 40594 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 220 | let | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 221 | val coT = TFree var1 --> TFree var2; | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 222 | val contraT = TFree var2 --> TFree var1; | 
| 42361 | 223 | val sort = Sign.inter_sort (Proof_Context.theory_of ctxt) (sort1, sort2); | 
| 40594 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 224 | in | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 225 | consume (op =) coT | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 226 | ##>> consume (op =) contraT | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 227 | #>> pair sort | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 228 | end; | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 229 | val (variances, left_variances) = fold_map check_variance_pair (vs1 ~~ vs2) Ts; | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 230 | val _ = if null left_variances then () else bad_typ (); | 
| 
fae1da97bb5e
infer variances of user-given mapper operation; proper thm storing
 haftmann parents: 
40587diff
changeset | 231 | in variances end; | 
| 40587 | 232 | |
| 55467 
a5c9002bc54d
renamed 'enriched_type' to more informative 'functor' (following the renaming of enriched type constructors to bounded natural functors)
 blanchet parents: 
51717diff
changeset | 233 | fun gen_functor prep_term some_prfx raw_mapper lthy = | 
| 40583 | 234 | let | 
| 46852 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 235 | val (mapper, T, tyco) = analyze_mapper lthy (prep_term lthy raw_mapper); | 
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 236 | val prfx = the_default (Long_Name.base_name tyco) some_prfx; | 
| 41390 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 237 | val variances = analyze_variances lthy tyco T; | 
| 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 238 | val (comp_prop, prove_compositionality) = make_comp_prop lthy variances (tyco, mapper); | 
| 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 239 | val (id_prop, prove_identity) = make_id_prop lthy variances (tyco, mapper); | 
| 40856 
3ad8a5925ba4
optional explicit prefix for type mapper theorems
 haftmann parents: 
40855diff
changeset | 240 | val qualify = Binding.qualify true prfx o Binding.name; | 
| 41389 | 241 | fun mapper_declaration comp_thm id_thm phi context = | 
| 242 | let | |
| 42388 | 243 | val typ_instance = Sign.typ_instance (Context.theory_of context); | 
| 41389 | 244 | val mapper' = Morphism.term phi mapper; | 
| 59058 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
55467diff
changeset | 245 | val T_T' = apply2 fastype_of (mapper, mapper'); | 
| 46852 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 246 | val vars = Term.add_vars mapper' []; | 
| 42388 | 247 | in | 
| 46852 
0b8dd4c8c79a
more precise checking for wellformedness of mapper, before and after morphism application
 haftmann parents: 
46851diff
changeset | 248 | if null vars andalso typ_instance T_T' andalso typ_instance (swap T_T') | 
| 41390 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 249 | then (Data.map o Symtab.cons_list) (tyco, | 
| 41389 | 250 |           { mapper = mapper', variances = variances,
 | 
| 41390 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 251 | comp = Morphism.thm phi comp_thm, id = Morphism.thm phi id_thm }) context | 
| 41389 | 252 | else context | 
| 253 | end; | |
| 41387 | 254 | fun after_qed [single_comp_thm, single_id_thm] lthy = | 
| 40587 | 255 | lthy | 
| 41387 | 256 | |> Local_Theory.note ((qualify compN, []), single_comp_thm) | 
| 257 | ||>> Local_Theory.note ((qualify idN, []), single_id_thm) | |
| 258 | |-> (fn ((_, [comp_thm]), (_, [id_thm])) => fn lthy => | |
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 259 | lthy | 
| 41388 | 260 | |> Local_Theory.note ((qualify compositionalityN, []), | 
| 261 | [prove_compositionality lthy comp_thm]) | |
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 262 | |> snd | 
| 41388 | 263 | |> Local_Theory.note ((qualify identityN, []), | 
| 264 | [prove_identity lthy id_thm]) | |
| 265 | |> snd | |
| 45291 
57cd50f98fdc
uniform Local_Theory.declaration with explicit params;
 wenzelm parents: 
43329diff
changeset | 266 |         |> Local_Theory.declaration {syntax = false, pervasive = false}
 | 
| 
57cd50f98fdc
uniform Local_Theory.declaration with explicit params;
 wenzelm parents: 
43329diff
changeset | 267 | (mapper_declaration comp_thm id_thm)) | 
| 40583 | 268 | in | 
| 41390 
207ee8f8a19c
full localization with possibly multiple entries;
 haftmann parents: 
41389diff
changeset | 269 | lthy | 
| 41371 
35d2241c169c
prove more algebraic version of functorial properties; retain old properties for convenience
 haftmann parents: 
41298diff
changeset | 270 | |> Proof.theorem NONE after_qed (map (fn t => [(t, [])]) [comp_prop, id_prop]) | 
| 40583 | 271 | end | 
| 272 | ||
| 60488 | 273 | val functor_ = gen_functor Syntax.check_term; | 
| 55467 
a5c9002bc54d
renamed 'enriched_type' to more informative 'functor' (following the renaming of enriched type constructors to bounded natural functors)
 blanchet parents: 
51717diff
changeset | 274 | val functor_cmd = gen_functor Syntax.read_term; | 
| 40583 | 275 | |
| 46961 
5c6955f487e5
outer syntax command definitions based on formal command_spec derived from theory header declarations;
 wenzelm parents: 
46949diff
changeset | 276 | val _ = | 
| 67149 | 277 | Outer_Syntax.local_theory_to_proof \<^command_keyword>\<open>functor\<close> | 
| 46961 
5c6955f487e5
outer syntax command definitions based on formal command_spec derived from theory header declarations;
 wenzelm parents: 
46949diff
changeset | 278 | "register operations managing the functorial structure of a type" | 
| 67149 | 279 | (Scan.option (Parse.name --| \<^keyword>\<open>:\<close>) -- Parse.term >> uncurry functor_cmd); | 
| 40583 | 280 | |
| 40582 | 281 | end; |