src/Pure/Isar/class.ML
author wenzelm
Sun May 03 20:04:38 2015 +0200 (2015-05-03)
changeset 60249 09377954133b
parent 60246 1f9cd721ece2
child 60337 c7ca6bb006b0
permissions -rw-r--r--
tuned output to resemble input syntax more closely;
     1 (*  Title:      Pure/Isar/class.ML
     2     Author:     Florian Haftmann, TU Muenchen
     3 
     4 Type classes derived from primitive axclasses and locales.
     5 *)
     6 
     7 signature CLASS =
     8 sig
     9   (*classes*)
    10   val is_class: theory -> class -> bool
    11   val these_params: theory -> sort -> (string * (class * (string * typ))) list
    12   val base_sort: theory -> class -> sort
    13   val rules: theory -> class -> thm option * thm
    14   val these_defs: theory -> sort -> thm list
    15   val these_operations: theory -> sort
    16     -> (string * (class * (typ * term))) list
    17   val print_classes: Proof.context -> unit
    18   val init: class -> theory -> Proof.context
    19   val begin: class list -> sort -> Proof.context -> Proof.context
    20   val const: class -> (binding * mixfix) * term -> term list * term list -> local_theory -> local_theory
    21   val abbrev: class -> Syntax.mode -> (binding * mixfix) * term -> term -> term list * term list -> local_theory -> local_theory
    22   val redeclare_operations: theory -> sort -> Proof.context -> Proof.context
    23   val class_prefix: string -> string
    24   val register: class -> class list -> ((string * typ) * (string * typ)) list
    25     -> sort -> morphism -> morphism -> thm option -> thm option -> thm
    26     -> theory -> theory
    27 
    28   (*instances*)
    29   val instantiation: string list * (string * sort) list * sort -> theory -> local_theory
    30   val instantiation_instance: (local_theory -> local_theory)
    31     -> local_theory -> Proof.state
    32   val prove_instantiation_instance: (Proof.context -> tactic)
    33     -> local_theory -> local_theory
    34   val prove_instantiation_exit: (Proof.context -> tactic)
    35     -> local_theory -> theory
    36   val prove_instantiation_exit_result: (morphism -> 'a -> 'b)
    37     -> (Proof.context -> 'b -> tactic) -> 'a -> local_theory -> 'b * theory
    38   val read_multi_arity: theory -> xstring list * xstring list * xstring
    39     -> string list * (string * sort) list * sort
    40   val instantiation_cmd: xstring list * xstring list * xstring -> theory -> local_theory
    41   val instance_arity_cmd: xstring list * xstring list * xstring -> theory -> Proof.state
    42 
    43   (*subclasses*)
    44   val classrel: class * class -> theory -> Proof.state
    45   val classrel_cmd: xstring * xstring -> theory -> Proof.state
    46   val register_subclass: class * class -> morphism option -> Element.witness option
    47     -> morphism -> local_theory -> local_theory
    48 
    49   (*tactics*)
    50   val intro_classes_tac: Proof.context -> thm list -> tactic
    51   val default_intro_tac: Proof.context -> thm list -> tactic
    52 
    53   (*diagnostics*)
    54   val pretty_specification: theory -> class -> Pretty.T list
    55 end;
    56 
    57 structure Class: CLASS =
    58 struct
    59 
    60 (** class data **)
    61 
    62 datatype class_data = Class_Data of {
    63 
    64   (* static part *)
    65   consts: (string * string) list
    66     (*locale parameter ~> constant name*),
    67   base_sort: sort,
    68   base_morph: morphism
    69     (*static part of canonical morphism*),
    70   export_morph: morphism,
    71   assm_intro: thm option,
    72   of_class: thm,
    73   axiom: thm option,
    74 
    75   (* dynamic part *)
    76   defs: thm list,
    77   operations: (string * (class * (typ * term))) list
    78 
    79   (* n.b.
    80     params = logical parameters of class
    81     operations = operations participating in user-space type system
    82   *)
    83 };
    84 
    85 fun make_class_data ((consts, base_sort, base_morph, export_morph, assm_intro, of_class, axiom),
    86     (defs, operations)) =
    87   Class_Data {consts = consts, base_sort = base_sort,
    88     base_morph = base_morph, export_morph = export_morph, assm_intro = assm_intro,
    89     of_class = of_class, axiom = axiom, defs = defs, operations = operations};
    90 fun map_class_data f (Class_Data {consts, base_sort, base_morph, export_morph, assm_intro,
    91     of_class, axiom, defs, operations}) =
    92   make_class_data (f ((consts, base_sort, base_morph, export_morph, assm_intro, of_class, axiom),
    93     (defs, operations)));
    94 fun merge_class_data _ (Class_Data {consts = consts,
    95     base_sort = base_sort, base_morph = base_morph, export_morph = export_morph, assm_intro = assm_intro,
    96     of_class = of_class, axiom = axiom, defs = defs1, operations = operations1},
    97   Class_Data {consts = _, base_sort = _, base_morph = _, export_morph = _, assm_intro = _,
    98     of_class = _, axiom = _, defs = defs2, operations = operations2}) =
    99   make_class_data ((consts, base_sort, base_morph, export_morph, assm_intro, of_class, axiom),
   100     (Thm.merge_thms (defs1, defs2),
   101       AList.merge (op =) (K true) (operations1, operations2)));
   102 
   103 structure Class_Data = Theory_Data
   104 (
   105   type T = class_data Graph.T
   106   val empty = Graph.empty;
   107   val extend = I;
   108   val merge = Graph.join merge_class_data;
   109 );
   110 
   111 
   112 (* queries *)
   113 
   114 fun lookup_class_data thy class =
   115   (case try (Graph.get_node (Class_Data.get thy)) class of
   116     SOME (Class_Data data) => SOME data
   117   | NONE => NONE);
   118 
   119 fun the_class_data thy class =
   120   (case lookup_class_data thy class of
   121     NONE => error ("Undeclared class " ^ quote class)
   122   | SOME data => data);
   123 
   124 val is_class = is_some oo lookup_class_data;
   125 
   126 val ancestry = Graph.all_succs o Class_Data.get;
   127 val heritage = Graph.all_preds o Class_Data.get;
   128 
   129 fun these_params thy =
   130   let
   131     fun params class =
   132       let
   133         val const_typs = (#params o Axclass.get_info thy) class;
   134         val const_names = (#consts o the_class_data thy) class;
   135       in
   136         (map o apsnd)
   137           (fn c => (class, (c, (the o AList.lookup (op =) const_typs) c))) const_names
   138       end;
   139   in maps params o ancestry thy end;
   140 
   141 val base_sort = #base_sort oo the_class_data;
   142 
   143 fun rules thy class =
   144   let val {axiom, of_class, ...} = the_class_data thy class
   145   in (axiom, of_class) end;
   146 
   147 fun all_assm_intros thy =
   148   Graph.fold (fn (_, (Class_Data {assm_intro, ...}, _)) => fold (insert Thm.eq_thm)
   149     (the_list assm_intro)) (Class_Data.get thy) [];
   150 
   151 fun these_defs thy = maps (#defs o the_class_data thy) o ancestry thy;
   152 fun these_operations thy = maps (#operations o the_class_data thy) o ancestry thy;
   153 
   154 val base_morphism = #base_morph oo the_class_data;
   155 
   156 fun morphism thy class =
   157   (case Element.eq_morphism thy (these_defs thy [class]) of
   158     SOME eq_morph => base_morphism thy class $> eq_morph
   159   | NONE => base_morphism thy class);
   160 
   161 val export_morphism = #export_morph oo the_class_data;
   162 
   163 fun print_classes ctxt =
   164   let
   165     val thy = Proof_Context.theory_of ctxt;
   166     val algebra = Sign.classes_of thy;
   167 
   168     val class_space = Proof_Context.class_space ctxt;
   169     val type_space = Proof_Context.type_space ctxt;
   170     val const_space = Proof_Context.const_space ctxt;
   171 
   172     val arities =
   173       Symtab.empty
   174       |> Symtab.fold (fn (tyco, arities) => fold (fn (class, _) =>
   175            Symtab.map_default (class, []) (insert (op =) tyco)) arities)
   176              (Sorts.arities_of algebra);
   177 
   178     fun prt_supersort class =
   179       Syntax.pretty_sort ctxt (Sign.minimize_sort thy (Sign.super_classes thy class));
   180 
   181     fun prt_arity class tyco =
   182       let
   183         val Ss = Sorts.mg_domain algebra tyco [class];
   184       in Syntax.pretty_arity ctxt (tyco, Ss, [class]) end;
   185 
   186     fun prt_param (c, ty) =
   187       Pretty.block
   188        [Name_Space.pretty ctxt const_space c, Pretty.str " ::",
   189         Pretty.brk 1, Syntax.pretty_typ ctxt (Type.strip_sorts_dummy ty)];
   190 
   191     fun prt_entry class =
   192       Pretty.block
   193         ([Pretty.keyword1 "class", Pretty.brk 1,
   194           Name_Space.pretty ctxt class_space class, Pretty.str ":", Pretty.fbrk,
   195           Pretty.block [Pretty.str "supersort: ", prt_supersort class]] @
   196           (case try (Axclass.get_info thy) class of
   197             NONE => []
   198           | SOME {params, ...} =>
   199               [Pretty.fbrk, Pretty.big_list "parameters:" (map prt_param params)]) @
   200           (case Symtab.lookup arities class of
   201             NONE => []
   202           | SOME ars =>
   203               [Pretty.fbrk, Pretty.big_list "instances:"
   204                 (map (prt_arity class) (sort (Name_Space.extern_ord ctxt type_space) ars))]));
   205   in
   206     Sorts.all_classes algebra
   207     |> sort (Name_Space.extern_ord ctxt class_space)
   208     |> map prt_entry
   209     |> Pretty.writeln_chunks2
   210   end;
   211 
   212 
   213 (* updaters *)
   214 
   215 fun register class sups params base_sort base_morph export_morph
   216     some_axiom some_assm_intro of_class thy =
   217   let
   218     val operations = map (fn (v_ty as (_, ty), (c, _)) =>
   219       (c, (class, (ty, Free v_ty)))) params;
   220     val add_class = Graph.new_node (class,
   221         make_class_data (((map o apply2) fst params, base_sort,
   222           base_morph, export_morph, some_assm_intro, of_class, some_axiom), ([], operations)))
   223       #> fold (curry Graph.add_edge class) sups;
   224   in Class_Data.map add_class thy end;
   225 
   226 fun activate_defs class thms thy =
   227   (case Element.eq_morphism thy thms of
   228     SOME eq_morph => fold (fn cls => fn thy =>
   229       Context.theory_map (Locale.amend_registration (cls, base_morphism thy cls)
   230         (eq_morph, true) (export_morphism thy cls)) thy) (heritage thy [class]) thy
   231   | NONE => thy);
   232 
   233 fun register_operation class (c, t) thy =
   234   let
   235     val base_sort = base_sort thy class;
   236     val prep_typ = map_type_tfree
   237       (fn (v, sort) => if Name.aT = v
   238         then TFree (v, base_sort) else TVar ((v, 0), sort));
   239     val t' = map_types prep_typ t;
   240     val ty' = Term.fastype_of t';
   241   in
   242     thy
   243     |> (Class_Data.map o Graph.map_node class o map_class_data o apsnd o apsnd)
   244         (cons (c, (class, (ty', t'))))
   245   end;
   246 
   247 fun register_def class def_thm thy =
   248   let
   249     val sym_thm = Thm.symmetric def_thm
   250   in
   251     thy
   252     |> (Class_Data.map o Graph.map_node class o map_class_data o apsnd o apfst)
   253         (cons sym_thm)
   254     |> activate_defs class [sym_thm]
   255   end;
   256 
   257 
   258 (** classes and class target **)
   259 
   260 (* class context syntax *)
   261 
   262 fun these_unchecks thy = map (fn (c, (_, (ty, t))) => (t, Const (c, ty)))
   263   o these_operations thy;
   264 
   265 fun redeclare_const thy c =
   266   let val b = Long_Name.base_name c
   267   in Sign.intern_const thy b = c ? Variable.declare_const (b, c) end;
   268 
   269 fun synchronize_class_syntax sort base_sort ctxt =
   270   let
   271     val thy = Proof_Context.theory_of ctxt;
   272     val algebra = Sign.classes_of thy;
   273     val operations = these_operations thy sort;
   274     fun subst_class_typ sort = map_type_tfree (K (TVar ((Name.aT, 0), sort)));
   275     val primary_constraints =
   276       (map o apsnd) (subst_class_typ base_sort o fst o snd) operations;
   277     val secondary_constraints =
   278       (map o apsnd) (fn (class, (ty, _)) => subst_class_typ [class] ty) operations;
   279     fun improve (c, ty) =
   280       (case AList.lookup (op =) primary_constraints c of
   281         SOME ty' =>
   282           (case try (Type.raw_match (ty', ty)) Vartab.empty of
   283             SOME tyenv =>
   284               (case Vartab.lookup tyenv (Name.aT, 0) of
   285                 SOME (_, ty' as TVar (vi, sort)) =>
   286                   if Type_Infer.is_param vi andalso Sorts.sort_le algebra (base_sort, sort)
   287                   then SOME (ty', TFree (Name.aT, base_sort))
   288                   else NONE
   289               | _ => NONE)
   290           | NONE => NONE)
   291       | NONE => NONE);
   292     fun subst (c, _) = Option.map snd (AList.lookup (op =) operations c);
   293     val unchecks = these_unchecks thy sort;
   294   in
   295     ctxt
   296     |> fold (redeclare_const thy o fst) primary_constraints
   297     |> Overloading.map_improvable_syntax (K (((primary_constraints, secondary_constraints),
   298         (((improve, subst), true), unchecks)), false))
   299     |> Overloading.set_primary_constraints
   300   end;
   301 
   302 fun synchronize_class_syntax_target class lthy =
   303   lthy
   304   |> Local_Theory.map_contexts
   305       (K (synchronize_class_syntax [class] (base_sort (Proof_Context.theory_of lthy) class)));
   306 
   307 fun redeclare_operations thy sort =
   308   fold (redeclare_const thy o fst) (these_operations thy sort);
   309 
   310 fun begin sort base_sort ctxt =
   311   ctxt
   312   |> Variable.declare_term
   313       (Logic.mk_type (TFree (Name.aT, base_sort)))
   314   |> synchronize_class_syntax sort base_sort
   315   |> Overloading.activate_improvable_syntax;
   316 
   317 fun init class thy =
   318   thy
   319   |> Locale.init class
   320   |> begin [class] (base_sort thy class);
   321 
   322 
   323 (* class target *)
   324 
   325 val class_prefix = Logic.const_of_class o Long_Name.base_name;
   326 
   327 local
   328 
   329 fun guess_morphism_identity (b, rhs) phi1 phi2 =
   330   let
   331     (*FIXME proper concept to identify morphism instead of educated guess*)
   332     val name_of_binding = Name_Space.full_name Name_Space.global_naming;
   333     val n1 = (name_of_binding o Morphism.binding phi1) b;
   334     val n2 = (name_of_binding o Morphism.binding phi2) b;
   335     val rhs1 = Morphism.term phi1 rhs;
   336     val rhs2 = Morphism.term phi2 rhs;
   337   in n1 = n2 andalso Term.aconv_untyped (rhs1, rhs2) end;
   338 
   339 fun target_const class phi0 prmode ((b, _), rhs) =
   340   let
   341     val guess_identity = guess_morphism_identity (b, rhs) Morphism.identity;
   342     val guess_canonical = guess_morphism_identity (b, rhs) phi0;
   343   in
   344     Generic_Target.locale_target_const class
   345       (not o (guess_identity orf guess_canonical)) prmode ((b, NoSyn), rhs)
   346   end;
   347 
   348 fun dangling_params_for lthy class (type_params, term_params) =
   349   let
   350     val class_param_names =
   351       map fst (these_params (Proof_Context.theory_of lthy) [class]);
   352     val dangling_term_params =
   353       subtract (fn (v, Free (w, _)) => v = w | _ => false) class_param_names term_params;
   354   in (type_params, dangling_term_params) end;
   355 
   356 fun global_def (b, eq) thy =
   357   thy
   358   |> Thm.add_def_global false false (b, eq)
   359   |>> (Thm.varifyT_global o snd)
   360   |-> (fn def_thm => Global_Theory.store_thm (b, def_thm)
   361       #> snd
   362       #> pair def_thm);
   363 
   364 fun canonical_const class phi dangling_params ((b, mx), rhs) thy =
   365   let
   366     val b_def = Binding.suffix_name "_dict" b;
   367     val c = Sign.full_name thy b;
   368     val ty = map Term.fastype_of dangling_params ---> Term.fastype_of rhs;
   369     val def_eq = Logic.mk_equals (list_comb (Const (c, ty), dangling_params), rhs)
   370       |> map_types Type.strip_sorts;
   371   in
   372     thy
   373     |> Sign.declare_const_global ((b, Type.strip_sorts ty), mx)
   374     |> snd
   375     |> global_def (b_def, def_eq)
   376     |-> (fn def_thm => register_def class def_thm)
   377     |> null dangling_params ? register_operation class (c, rhs)
   378     |> Sign.add_const_constraint (c, SOME ty)
   379   end;
   380 
   381 fun canonical_abbrev class phi prmode dangling_term_params ((b, mx), rhs) thy =
   382   let
   383     val unchecks = these_unchecks thy [class];
   384     val rhs' = Pattern.rewrite_term thy unchecks [] rhs;
   385     val c' = Sign.full_name thy b;
   386     val ty' = map Term.fastype_of dangling_term_params ---> Term.fastype_of rhs';
   387     val ty'' = Morphism.typ phi ty';
   388     val rhs'' = map_types (Morphism.typ phi) (fold lambda dangling_term_params rhs');
   389   in
   390     thy
   391     |> Sign.add_abbrev (#1 prmode) (b, Logic.varify_types_global rhs'')
   392     |> snd
   393     |> Sign.notation true prmode [(Const (c', ty''), mx)]
   394     |> (null dangling_term_params andalso not (#1 prmode = Print_Mode.input))
   395       ? register_operation class (c', rhs')
   396     |> Sign.add_const_constraint (c', SOME ty')
   397   end;
   398 
   399 in
   400 
   401 fun const class ((b, mx), lhs) params lthy =
   402   let
   403     val phi = morphism (Proof_Context.theory_of lthy) class;
   404     val dangling_params = map (Morphism.term phi) (uncurry append (dangling_params_for lthy class params));
   405   in
   406     lthy
   407     |> target_const class phi Syntax.mode_default ((b, mx), lhs)
   408     |> Local_Theory.raw_theory (canonical_const class phi dangling_params
   409          ((Morphism.binding phi b, if null dangling_params then mx else NoSyn), Morphism.term phi lhs))
   410     |> Generic_Target.standard_const (fn (this, other) => other <> 0 andalso this <> other)
   411          Syntax.mode_default ((b, if null dangling_params then NoSyn else mx), lhs)
   412     |> synchronize_class_syntax_target class
   413   end;
   414 
   415 fun abbrev class prmode ((b, mx), lhs) rhs' params lthy =
   416   let
   417     val phi = morphism (Proof_Context.theory_of lthy) class;
   418     val dangling_term_params = map (Morphism.term phi) (snd (dangling_params_for lthy class params));
   419   in
   420     lthy
   421     |> target_const class phi prmode ((b, mx), lhs)
   422     |> Local_Theory.raw_theory (canonical_abbrev class phi prmode dangling_term_params
   423          ((Morphism.binding phi b, if null dangling_term_params then mx else NoSyn), rhs'))
   424     |> Generic_Target.standard_const (fn (this, other) => other <> 0 andalso this <> other)
   425          prmode ((b, if null dangling_term_params then NoSyn else mx), lhs)
   426     |> synchronize_class_syntax_target class
   427   end;
   428 
   429 end;
   430 
   431 
   432 (* subclasses *)
   433 
   434 fun register_subclass (sub, sup) some_dep_morph some_witn export lthy =
   435   let
   436     val thy = Proof_Context.theory_of lthy;
   437     val intros = (snd o rules thy) sup :: map_filter I
   438       [Option.map (Drule.export_without_context_open o Element.conclude_witness lthy) some_witn,
   439         (fst o rules thy) sub];
   440     val classrel =
   441       Goal.prove_sorry_global thy [] [] (Logic.mk_classrel (sub, sup))
   442         (fn {context = ctxt, ...} => EVERY (map (TRYALL o resolve_tac ctxt o single) intros));
   443     val diff_sort = Sign.complete_sort thy [sup]
   444       |> subtract (op =) (Sign.complete_sort thy [sub])
   445       |> filter (is_class thy);
   446     fun add_dependency some_wit = case some_dep_morph of
   447         SOME dep_morph => Generic_Target.locale_dependency sub
   448           (sup, dep_morph $> Element.satisfy_morphism (the_list some_witn)) NONE export
   449       | NONE => I;
   450   in
   451     lthy
   452     |> Local_Theory.raw_theory
   453       (Axclass.add_classrel classrel
   454       #> Class_Data.map (Graph.add_edge (sub, sup))
   455       #> activate_defs sub (these_defs thy diff_sort))
   456     |> add_dependency some_witn
   457     |> synchronize_class_syntax_target sub
   458   end;
   459 
   460 local
   461 
   462 fun gen_classrel mk_prop classrel thy =
   463   let
   464     fun after_qed results =
   465       Proof_Context.background_theory ((fold o fold) Axclass.add_classrel results);
   466   in
   467     thy
   468     |> Proof_Context.init_global
   469     |> Proof.theorem NONE after_qed [[(mk_prop thy classrel, [])]]
   470   end;
   471 
   472 in
   473 
   474 val classrel =
   475   gen_classrel (Logic.mk_classrel oo Axclass.cert_classrel);
   476 val classrel_cmd =
   477   gen_classrel (Logic.mk_classrel oo Axclass.read_classrel);
   478 
   479 end; (*local*)
   480 
   481 
   482 (** instantiation target **)
   483 
   484 (* bookkeeping *)
   485 
   486 datatype instantiation = Instantiation of {
   487   arities: string list * (string * sort) list * sort,
   488   params: ((string * string) * (string * typ)) list
   489     (*(instantiation parameter, type constructor), (local instantiation parameter, typ)*)
   490 }
   491 
   492 fun make_instantiation (arities, params) =
   493   Instantiation {arities = arities, params = params};
   494 
   495 val empty_instantiation = make_instantiation (([], [], []), []);
   496 
   497 structure Instantiation = Proof_Data
   498 (
   499   type T = instantiation;
   500   fun init _ = empty_instantiation;
   501 );
   502 
   503 val get_instantiation =
   504   (fn Instantiation data => data) o Instantiation.get o Local_Theory.target_of;
   505 
   506 fun map_instantiation f =
   507   (Local_Theory.target o Instantiation.map)
   508     (fn Instantiation {arities, params} => make_instantiation (f (arities, params)));
   509 
   510 fun the_instantiation lthy =
   511   (case get_instantiation lthy of
   512     {arities = ([], [], []), ...} => error "No instantiation target"
   513   | data => data);
   514 
   515 val instantiation_params = #params o get_instantiation;
   516 
   517 fun instantiation_param lthy b = instantiation_params lthy
   518   |> find_first (fn (_, (v, _)) => Binding.name_of b = v)
   519   |> Option.map (fst o fst);
   520 
   521 fun read_multi_arity thy (raw_tycos, raw_sorts, raw_sort) =
   522   let
   523     val ctxt = Proof_Context.init_global thy;
   524     val all_arities = map (fn raw_tyco => Proof_Context.read_arity ctxt
   525       (raw_tyco, raw_sorts, raw_sort)) raw_tycos;
   526     val tycos = map #1 all_arities;
   527     val (_, sorts, sort) = hd all_arities;
   528     val vs = Name.invent_names Name.context Name.aT sorts;
   529   in (tycos, vs, sort) end;
   530 
   531 
   532 (* syntax *)
   533 
   534 fun synchronize_inst_syntax ctxt =
   535   let
   536     val Instantiation {params, ...} = Instantiation.get ctxt;
   537 
   538     val lookup_inst_param = Axclass.lookup_inst_param
   539       (Sign.consts_of (Proof_Context.theory_of ctxt)) params;
   540     fun subst (c, ty) =
   541       (case lookup_inst_param (c, ty) of
   542         SOME (v_ty as (_, ty)) => SOME (ty, Free v_ty)
   543       | NONE => NONE);
   544     val unchecks =
   545       map (fn ((c, _), v_ty as (_, ty)) => (Free v_ty, Const (c, ty))) params;
   546   in
   547     ctxt
   548     |> Overloading.map_improvable_syntax
   549       (fn (((primary_constraints, _), (((improve, _), _), _)), _) =>
   550           (((primary_constraints, []), (((improve, subst), false), unchecks)), false))
   551   end;
   552 
   553 fun resort_terms ctxt algebra consts constraints ts =
   554   let
   555     fun matchings (Const (c_ty as (c, _))) =
   556           (case constraints c of
   557             NONE => I
   558           | SOME sorts =>
   559               fold2 (curry (Sorts.meet_sort algebra)) (Consts.typargs consts c_ty) sorts)
   560       | matchings _ = I;
   561     val tvartab = (fold o fold_aterms) matchings ts Vartab.empty
   562       handle Sorts.CLASS_ERROR e => error (Sorts.class_error (Context.pretty ctxt) e);
   563     val inst = map_type_tvar
   564       (fn (vi, sort) => TVar (vi, the_default sort (Vartab.lookup tvartab vi)));
   565   in if Vartab.is_empty tvartab then ts else (map o map_types) inst ts end;
   566 
   567 
   568 (* target *)
   569 
   570 fun define_overloaded (c, U) v (b_def, rhs) =
   571   Local_Theory.background_theory_result (Axclass.declare_overloaded (c, U)
   572   ##>> Axclass.define_overloaded b_def (c, rhs))
   573   ##> (map_instantiation o apsnd) (filter_out (fn (_, (v', _)) => v' = v))
   574   ##> Local_Theory.map_contexts (K synchronize_inst_syntax);
   575 
   576 fun foundation (((b, U), mx), (b_def, rhs)) params lthy =
   577   (case instantiation_param lthy b of
   578     SOME c =>
   579       if mx <> NoSyn then error ("Illegal mixfix syntax for overloaded constant " ^ quote c)
   580       else lthy |> define_overloaded (c, U) (Binding.name_of b) (b_def, rhs)
   581   | NONE => lthy |> Generic_Target.theory_foundation (((b, U), mx), (b_def, rhs)) params);
   582 
   583 fun pretty lthy =
   584   let
   585     val {arities = (tycos, vs, sort), params} = the_instantiation lthy;
   586     fun pr_arity tyco = Syntax.pretty_arity lthy (tyco, map snd vs, sort);
   587     fun pr_param ((c, _), (v, ty)) =
   588       Pretty.block (Pretty.breaks
   589         [Pretty.str v, Pretty.str "==", Proof_Context.pretty_const lthy c,
   590           Pretty.str "::", Syntax.pretty_typ lthy ty]);
   591   in
   592     [Pretty.block
   593       (Pretty.fbreaks (Pretty.keyword1 "instantiation" :: map pr_arity tycos @ map pr_param params))]
   594   end;
   595 
   596 fun conclude lthy =
   597   let
   598     val (tycos, vs, sort) = #arities (the_instantiation lthy);
   599     val thy = Proof_Context.theory_of lthy;
   600     val _ = tycos |> List.app (fn tyco =>
   601       if Sign.of_sort thy (Type (tyco, map TFree vs), sort) then ()
   602       else error ("Missing instance proof for type " ^ quote (Proof_Context.markup_type lthy tyco)));
   603   in lthy end;
   604 
   605 fun instantiation (tycos, vs, sort) thy =
   606   let
   607     val _ = if null tycos then error "At least one arity must be given" else ();
   608     val class_params = these_params thy (filter (can (Axclass.get_info thy)) sort);
   609     fun get_param tyco (param, (_, (c, ty))) =
   610       if can (Axclass.param_of_inst thy) (c, tyco)
   611       then NONE else SOME ((c, tyco),
   612         (param ^ "_" ^ Long_Name.base_name tyco, map_atyps (K (Type (tyco, map TFree vs))) ty));
   613     val params = map_product get_param tycos class_params |> map_filter I;
   614     val _ = if null params andalso forall (fn tyco => can (Sign.arity_sorts thy tyco) sort) tycos
   615       then error "No parameters and no pending instance proof obligations in instantiation."
   616       else ();
   617     val primary_constraints = map (apsnd
   618       (map_atyps (K (TVar ((Name.aT, 0), [])))) o snd o snd) class_params;
   619     val algebra = Sign.classes_of thy
   620       |> fold (fn tyco => Sorts.add_arities (Context.pretty_global thy)
   621             (tyco, map (fn class => (class, map snd vs)) sort)) tycos;
   622     val consts = Sign.consts_of thy;
   623     val improve_constraints = AList.lookup (op =)
   624       (map (fn (_, (class, (c, _))) => (c, [[class]])) class_params);
   625     fun resort_check ctxt ts = resort_terms ctxt algebra consts improve_constraints ts;
   626     val lookup_inst_param = Axclass.lookup_inst_param consts params;
   627     fun improve (c, ty) =
   628       (case lookup_inst_param (c, ty) of
   629         SOME (_, ty') => if Sign.typ_instance thy (ty', ty) then SOME (ty, ty') else NONE
   630       | NONE => NONE);
   631   in
   632     thy
   633     |> Sign.change_begin
   634     |> Proof_Context.init_global
   635     |> Instantiation.put (make_instantiation ((tycos, vs, sort), params))
   636     |> fold (Variable.declare_typ o TFree) vs
   637     |> fold (Variable.declare_names o Free o snd) params
   638     |> (Overloading.map_improvable_syntax o apfst)
   639          (K ((primary_constraints, []), (((improve, K NONE), false), [])))
   640     |> Overloading.activate_improvable_syntax
   641     |> Context.proof_map (Syntax_Phases.term_check 0 "resorting" resort_check)
   642     |> synchronize_inst_syntax
   643     |> Local_Theory.init (Sign.naming_of thy)
   644        {define = Generic_Target.define foundation,
   645         notes = Generic_Target.notes Generic_Target.theory_notes,
   646         abbrev = Generic_Target.abbrev Generic_Target.theory_abbrev,
   647         declaration = K Generic_Target.theory_declaration,
   648         subscription = Generic_Target.theory_registration,
   649         pretty = pretty,
   650         exit = conclude #> Local_Theory.target_of #> Sign.change_end_local}
   651   end;
   652 
   653 fun instantiation_cmd arities thy =
   654   instantiation (read_multi_arity thy arities) thy;
   655 
   656 fun gen_instantiation_instance do_proof after_qed lthy =
   657   let
   658     val (tycos, vs, sort) = (#arities o the_instantiation) lthy;
   659     val arities_proof = maps (fn tyco => Logic.mk_arities (tyco, map snd vs, sort)) tycos;
   660     fun after_qed' results =
   661       Local_Theory.background_theory (fold (Axclass.add_arity o Thm.varifyT_global) results)
   662       #> after_qed;
   663   in
   664     lthy
   665     |> do_proof after_qed' arities_proof
   666   end;
   667 
   668 val instantiation_instance = gen_instantiation_instance (fn after_qed => fn ts =>
   669   Proof.theorem NONE (after_qed o map the_single) (map (fn t => [(t, [])]) ts));
   670 
   671 fun prove_instantiation_instance tac = gen_instantiation_instance (fn after_qed =>
   672   fn ts => fn lthy => after_qed (map (fn t => Goal.prove lthy [] [] t
   673     (fn {context, ...} => tac context)) ts) lthy) I;
   674 
   675 fun prove_instantiation_exit tac = prove_instantiation_instance tac
   676   #> Local_Theory.exit_global;
   677 
   678 fun prove_instantiation_exit_result f tac x lthy =
   679   let
   680     val morph = Proof_Context.export_morphism lthy
   681       (Proof_Context.init_global (Proof_Context.theory_of lthy));
   682     val y = f morph x;
   683   in
   684     lthy
   685     |> prove_instantiation_exit (fn ctxt => tac ctxt y)
   686     |> pair y
   687   end;
   688 
   689 
   690 (* simplified instantiation interface with no class parameter *)
   691 
   692 fun instance_arity_cmd raw_arities thy =
   693   let
   694     val (tycos, vs, sort) = read_multi_arity thy raw_arities;
   695     val sorts = map snd vs;
   696     val arities = maps (fn tyco => Logic.mk_arities (tyco, sorts, sort)) tycos;
   697     fun after_qed results =
   698       Proof_Context.background_theory ((fold o fold) Axclass.add_arity results);
   699   in
   700     thy
   701     |> Proof_Context.init_global
   702     |> Proof.theorem NONE after_qed (map (fn t => [(t, [])]) arities)
   703   end;
   704 
   705 
   706 (** tactics and methods **)
   707 
   708 fun intro_classes_tac ctxt facts st =
   709   let
   710     val thy = Thm.theory_of_thm st;
   711     val classes = Sign.all_classes thy;
   712     val class_trivs = map (Thm.class_triv thy) classes;
   713     val class_intros = map_filter (try (#intro o Axclass.get_info thy)) classes;
   714     val assm_intros = all_assm_intros thy;
   715   in
   716     Method.intros_tac ctxt (class_trivs @ class_intros @ assm_intros) facts st
   717   end;
   718 
   719 fun default_intro_tac ctxt [] =
   720       COND Thm.no_prems no_tac
   721         (intro_classes_tac ctxt [] ORELSE Locale.intro_locales_tac true ctxt [])
   722   | default_intro_tac _ _ = no_tac;
   723 
   724 fun default_tac rules ctxt facts =
   725   HEADGOAL (Method.some_rule_tac ctxt rules facts) ORELSE
   726     default_intro_tac ctxt facts;
   727 
   728 val _ = Theory.setup
   729  (Method.setup @{binding intro_classes} (Scan.succeed (METHOD o intro_classes_tac))
   730     "back-chain introduction rules of classes" #>
   731   Method.setup @{binding default} (Attrib.thms >> (METHOD oo default_tac))
   732     "apply some intro/elim rule");
   733 
   734 
   735 
   736 (** diagnostics **)
   737 
   738 fun pretty_specification thy class =
   739   if is_class thy class then
   740     let
   741       val class_ctxt = init class thy;
   742       val prt_class = Name_Space.pretty class_ctxt (Proof_Context.class_space class_ctxt);
   743 
   744       val super_classes = Sign.minimize_sort thy (Sign.super_classes thy class);
   745 
   746       val fix_args =
   747         #params (Axclass.get_info thy class)
   748         |> map (fn (c, T) => (Binding.name (Long_Name.base_name c), SOME T, NoSyn));
   749       val fixes = if null fix_args then [] else [Element.Fixes fix_args];
   750       val assumes = Locale.hyp_spec_of thy class;
   751 
   752       val header =
   753         [Pretty.keyword1 "class", Pretty.brk 1, prt_class class, Pretty.str " =", Pretty.brk 1] @
   754         Pretty.separate " +" (map prt_class super_classes) @
   755         (if null super_classes then [] else [Pretty.str " +"]);
   756       val body =
   757         if null fixes andalso null assumes then []
   758         else
   759           maps (Element.pretty_ctxt_no_attribs class_ctxt) (fixes @ assumes)
   760           |> maps (fn prt => [Pretty.fbrk, prt]);
   761     in if null body then [] else [Pretty.block (header @ body)] end
   762   else [];
   763 
   764 end;