src/Pure/Isar/class.ML
author wenzelm
Wed Jun 22 16:04:03 2016 +0200 (2016-06-22 ago)
changeset 63347 e344dc82f6c2
parent 62939 ef8d840f39fb
child 66337 a849ce33923d
permissions -rw-r--r--
report class parameters within instantiation;
     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 -> (string * (class * ((typ * term) * bool))) list
    16   val print_classes: Proof.context -> unit
    17   val init: class -> theory -> Proof.context
    18   val begin: class list -> sort -> Proof.context -> Proof.context
    19   val const: class -> (binding * mixfix) * term -> term list * term list ->
    20     local_theory -> local_theory
    21   val abbrev: class -> Syntax.mode -> (binding * mixfix) * term -> local_theory ->
    22     (term * term) * local_theory
    23   val redeclare_operations: theory -> sort -> Proof.context -> Proof.context
    24   val class_prefix: string -> string
    25   val register: class -> class list -> ((string * typ) * (string * typ)) list ->
    26     sort -> morphism -> morphism -> thm option -> thm option -> thm -> 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 standard_intro_classes_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) * bool))) 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 pretty_param ctxt (c, ty) =
   164   Pretty.block
   165    [Name_Space.pretty ctxt (Proof_Context.const_space ctxt) c, Pretty.str " ::",
   166     Pretty.brk 1, Syntax.pretty_typ ctxt ty];
   167 
   168 fun print_classes ctxt =
   169   let
   170     val thy = Proof_Context.theory_of ctxt;
   171     val algebra = Sign.classes_of thy;
   172 
   173     val class_space = Proof_Context.class_space ctxt;
   174     val type_space = Proof_Context.type_space ctxt;
   175 
   176     val arities =
   177       Symtab.empty
   178       |> Symtab.fold (fn (tyco, arities) => fold (fn (class, _) =>
   179            Symtab.map_default (class, []) (insert (op =) tyco)) arities)
   180              (Sorts.arities_of algebra);
   181 
   182     fun prt_supersort class =
   183       Syntax.pretty_sort ctxt (Sign.minimize_sort thy (Sign.super_classes thy class));
   184 
   185     fun prt_arity class tyco =
   186       let
   187         val Ss = Sorts.mg_domain algebra tyco [class];
   188       in Syntax.pretty_arity ctxt (tyco, Ss, [class]) end;
   189 
   190     fun prt_param (c, ty) = pretty_param ctxt (c, Type.strip_sorts_dummy ty);
   191 
   192     fun prt_entry class =
   193       Pretty.block
   194         ([Pretty.keyword1 "class", Pretty.brk 1,
   195           Name_Space.pretty ctxt class_space class, Pretty.str ":", Pretty.fbrk,
   196           Pretty.block [Pretty.str "supersort: ", prt_supersort class]] @
   197           (case try (Axclass.get_info thy) class of
   198             NONE => []
   199           | SOME {params, ...} =>
   200               [Pretty.fbrk, Pretty.big_list "parameters:" (map prt_param params)]) @
   201           (case Symtab.lookup arities class of
   202             NONE => []
   203           | SOME ars =>
   204               [Pretty.fbrk, Pretty.big_list "instances:"
   205                 (map (prt_arity class) (sort (Name_Space.extern_ord ctxt type_space) ars))]));
   206   in
   207     Sorts.all_classes algebra
   208     |> sort (Name_Space.extern_ord ctxt class_space)
   209     |> map prt_entry
   210     |> Pretty.writeln_chunks2
   211   end;
   212 
   213 
   214 (* updaters *)
   215 
   216 fun register class sups params base_sort base_morph export_morph
   217     some_axiom some_assm_intro of_class thy =
   218   let
   219     val operations = map (fn (v_ty as (_, ty), (c, _)) =>
   220       (c, (class, ((ty, Free v_ty), false)))) params;
   221     val add_class = Graph.new_node (class,
   222         make_class_data (((map o apply2) fst params, base_sort,
   223           base_morph, export_morph, Option.map Thm.trim_context some_assm_intro,
   224           Thm.trim_context of_class, Option.map Thm.trim_context some_axiom), ([], operations)))
   225       #> fold (curry Graph.add_edge class) sups;
   226   in Class_Data.map add_class thy end;
   227 
   228 fun activate_defs class thms thy =
   229   (case Element.eq_morphism thy thms of
   230     SOME eq_morph => fold (fn cls => fn thy =>
   231       Context.theory_map (Locale.amend_registration (cls, base_morphism thy cls)
   232         (eq_morph, true) (export_morphism thy cls)) thy) (heritage thy [class]) thy
   233   | NONE => thy);
   234 
   235 fun register_operation class (c, t) input_only thy =
   236   let
   237     val base_sort = base_sort thy class;
   238     val prep_typ = map_type_tfree
   239       (fn (v, sort) => if Name.aT = v
   240         then TFree (v, base_sort) else TVar ((v, 0), sort));
   241     val t' = map_types prep_typ t;
   242     val ty' = Term.fastype_of t';
   243   in
   244     thy
   245     |> (Class_Data.map o Graph.map_node class o map_class_data o apsnd o apsnd)
   246         (cons (c, (class, ((ty', t'), input_only))))
   247   end;
   248 
   249 fun register_def class def_thm thy =
   250   let
   251     val sym_thm = Thm.trim_context (Thm.symmetric def_thm)
   252   in
   253     thy
   254     |> (Class_Data.map o Graph.map_node class o map_class_data o apsnd o apfst)
   255         (cons sym_thm)
   256     |> activate_defs class [sym_thm]
   257   end;
   258 
   259 
   260 (** classes and class target **)
   261 
   262 (* class context syntax *)
   263 
   264 fun make_rewrite t c_ty =
   265   let
   266     val (vs, t') = strip_abs t;
   267     val vts = map snd vs
   268       |> Name.invent_names Name.context Name.uu
   269       |> map (fn (v, T) => Var ((v, 0), T));
   270   in (betapplys (t, vts), betapplys (Const c_ty, vts)) end;
   271 
   272 fun these_unchecks thy =
   273   these_operations thy
   274   #> map_filter (fn (c, (_, ((ty, t), input_only))) =>
   275     if input_only then NONE else SOME (make_rewrite t (c, ty)));
   276 
   277 fun these_unchecks_reversed thy =
   278   these_operations thy
   279   #> map (fn (c, (_, ((ty, t), _))) => (Const (c, ty), t));
   280 
   281 fun redeclare_const thy c =
   282   let val b = Long_Name.base_name c
   283   in Sign.intern_const thy b = c ? Variable.declare_const (b, c) end;
   284 
   285 fun synchronize_class_syntax sort base_sort ctxt =
   286   let
   287     val thy = Proof_Context.theory_of ctxt;
   288     val algebra = Sign.classes_of thy;
   289     val operations = these_operations thy sort;
   290     fun subst_class_typ sort = map_type_tfree (K (TVar ((Name.aT, 0), sort)));
   291     val primary_constraints =
   292       (map o apsnd) (subst_class_typ base_sort o fst o fst o snd) operations;
   293     val secondary_constraints =
   294       (map o apsnd) (fn (class, ((ty, _), _)) => subst_class_typ [class] ty) operations;
   295     fun improve (c, ty) =
   296       (case AList.lookup (op =) primary_constraints c of
   297         SOME ty' =>
   298           (case try (Type.raw_match (ty', ty)) Vartab.empty of
   299             SOME tyenv =>
   300               (case Vartab.lookup tyenv (Name.aT, 0) of
   301                 SOME (_, ty' as TVar (vi, sort)) =>
   302                   if Type_Infer.is_param vi andalso Sorts.sort_le algebra (base_sort, sort)
   303                   then SOME (ty', TFree (Name.aT, base_sort))
   304                   else NONE
   305               | _ => NONE)
   306           | NONE => NONE)
   307       | NONE => NONE);
   308     fun subst (c, _) = Option.map (fst o snd) (AList.lookup (op =) operations c);
   309     val unchecks = these_unchecks thy sort;
   310   in
   311     ctxt
   312     |> fold (redeclare_const thy o fst) primary_constraints
   313     |> Overloading.map_improvable_syntax (K {primary_constraints = primary_constraints,
   314       secondary_constraints = secondary_constraints, improve = improve, subst = subst,
   315       no_subst_in_abbrev_mode = true, unchecks = unchecks})
   316     |> Overloading.set_primary_constraints
   317   end;
   318 
   319 fun synchronize_class_syntax_target class lthy =
   320   lthy
   321   |> Local_Theory.map_contexts
   322       (K (synchronize_class_syntax [class] (base_sort (Proof_Context.theory_of lthy) class)));
   323 
   324 fun redeclare_operations thy sort =
   325   fold (redeclare_const thy o fst) (these_operations thy sort);
   326 
   327 fun begin sort base_sort ctxt =
   328   ctxt
   329   |> Variable.declare_term
   330       (Logic.mk_type (TFree (Name.aT, base_sort)))
   331   |> synchronize_class_syntax sort base_sort
   332   |> Overloading.activate_improvable_syntax;
   333 
   334 fun init class thy =
   335   thy
   336   |> Locale.init class
   337   |> begin [class] (base_sort thy class);
   338 
   339 
   340 (* class target *)
   341 
   342 val class_prefix = Logic.const_of_class o Long_Name.base_name;
   343 
   344 fun guess_morphism_identity (b, rhs) phi1 phi2 =
   345   let
   346     (*FIXME proper concept to identify morphism instead of educated guess*)
   347     val name_of_binding = Name_Space.full_name Name_Space.global_naming;
   348     val n1 = (name_of_binding o Morphism.binding phi1) b;
   349     val n2 = (name_of_binding o Morphism.binding phi2) b;
   350     val rhs1 = Morphism.term phi1 rhs;
   351     val rhs2 = Morphism.term phi2 rhs;
   352   in n1 = n2 andalso Term.aconv_untyped (rhs1, rhs2) end;
   353 
   354 fun target_const class phi0 prmode (b, rhs) lthy =
   355   let
   356     val export = Variable.export_morphism lthy (Local_Theory.target_of lthy);
   357     val guess_identity = guess_morphism_identity (b, rhs) export;
   358     val guess_canonical = guess_morphism_identity (b, rhs) (export $> phi0);
   359   in
   360     lthy
   361     |> Generic_Target.locale_target_const class
   362       (not o (guess_identity orf guess_canonical)) prmode ((b, NoSyn), rhs)
   363   end;
   364 
   365 local
   366 
   367 fun dangling_params_for lthy class (type_params, term_params) =
   368   let
   369     val class_param_names =
   370       map fst (these_params (Proof_Context.theory_of lthy) [class]);
   371     val dangling_term_params =
   372       subtract (fn (v, Free (w, _)) => v = w | _ => false) class_param_names term_params;
   373   in (type_params, dangling_term_params) end;
   374 
   375 fun global_def (b, eq) thy =
   376   thy
   377   |> Thm.add_def_global false false (b, eq)
   378   |>> (Thm.varifyT_global o snd)
   379   |-> (fn def_thm => Global_Theory.store_thm (b, def_thm)
   380       #> snd
   381       #> pair def_thm);
   382 
   383 fun canonical_const class phi dangling_params ((b, mx), rhs) thy =
   384   let
   385     val b_def = Binding.suffix_name "_dict" b;
   386     val c = Sign.full_name thy b;
   387     val ty = map Term.fastype_of dangling_params ---> Term.fastype_of rhs;
   388     val def_eq = Logic.mk_equals (list_comb (Const (c, ty), dangling_params), rhs)
   389       |> map_types Type.strip_sorts;
   390   in
   391     thy
   392     |> Sign.declare_const_global ((b, Type.strip_sorts ty), mx)
   393     |> snd
   394     |> global_def (b_def, def_eq)
   395     |-> (fn def_thm => register_def class def_thm)
   396     |> null dangling_params ? register_operation class (c, rhs) false
   397     |> Sign.add_const_constraint (c, SOME ty)
   398   end;
   399 
   400 in
   401 
   402 fun const class ((b, mx), lhs) params lthy =
   403   let
   404     val phi = morphism (Proof_Context.theory_of lthy) class;
   405     val dangling_params = map (Morphism.term phi) (uncurry append (dangling_params_for lthy class params));
   406   in
   407     lthy
   408     |> target_const class phi Syntax.mode_default (b, lhs)
   409     |> Local_Theory.raw_theory (canonical_const class phi dangling_params
   410          ((Morphism.binding phi b, if null dangling_params then mx else NoSyn), Morphism.term phi lhs))
   411     |> Generic_Target.standard_const (fn (this, other) => other <> 0 andalso this <> other)
   412          Syntax.mode_default ((b, if null dangling_params then NoSyn else mx), lhs)
   413     |> synchronize_class_syntax_target class
   414   end;
   415 
   416 end;
   417 
   418 local
   419 
   420 fun canonical_abbrev class phi prmode with_syntax ((b, mx), rhs) thy =
   421   let
   422     val c = Sign.full_name thy b;
   423     val constrain = map_atyps (fn T as TFree (v, _) =>
   424       if v = Name.aT then TFree (v, [class]) else T | T => T);
   425     val rhs' = map_types constrain rhs;
   426   in
   427     thy
   428     |> Sign.add_abbrev (#1 prmode) (b, Logic.varify_types_global rhs')
   429     |> snd
   430     |> with_syntax ? Sign.notation true prmode [(Const (c, fastype_of rhs), mx)]
   431     |> with_syntax ? register_operation class (c, rhs)
   432         (#1 prmode = Print_Mode.input)
   433     |> Sign.add_const_constraint (c, SOME (fastype_of rhs'))
   434   end;
   435 
   436 fun canonical_abbrev_target class phi prmode ((b, mx), rhs) lthy =
   437   let
   438     val thy = Proof_Context.theory_of lthy;
   439     val preprocess = perhaps (try (Pattern.rewrite_term_top thy (these_unchecks thy [class]) []));
   440     val (global_rhs, (extra_tfrees, (type_params, term_params))) =
   441       Generic_Target.export_abbrev lthy preprocess rhs;
   442     val mx' = Generic_Target.check_mixfix_global (b, null term_params) mx;
   443   in
   444     lthy
   445     |> Local_Theory.raw_theory (canonical_abbrev class phi prmode (null term_params)
   446         ((Morphism.binding phi b, mx'), Logic.unvarify_types_global global_rhs))
   447   end;
   448 
   449 fun further_abbrev_target class phi prmode (b, mx) rhs params =
   450   Generic_Target.background_abbrev (b, rhs) (snd params)
   451   #-> (fn (lhs, _) => target_const class phi prmode (b, lhs)
   452     #> Generic_Target.standard_const (fn (this, other) => other <> 0 andalso this <> other) prmode ((b, mx), lhs))
   453 
   454 in
   455 
   456 fun abbrev class prmode ((b, mx), rhs) lthy =
   457   let
   458     val thy = Proof_Context.theory_of lthy;
   459     val phi = morphism thy class;
   460     val rhs_generic =
   461       perhaps (try (Pattern.rewrite_term_top thy (these_unchecks_reversed thy [class]) [])) rhs;
   462   in
   463     lthy
   464     |> canonical_abbrev_target class phi prmode ((b, mx), rhs)
   465     |> Generic_Target.abbrev (further_abbrev_target class phi) prmode ((b, mx), rhs_generic)
   466     ||> synchronize_class_syntax_target class
   467   end;
   468 
   469 end;
   470 
   471 
   472 (* subclasses *)
   473 
   474 fun register_subclass (sub, sup) some_dep_morph some_witn export lthy =
   475   let
   476     val thy = Proof_Context.theory_of lthy;
   477     val intros = (snd o rules thy) sup :: map_filter I
   478       [Option.map (Drule.export_without_context_open o Element.conclude_witness lthy) some_witn,
   479         (fst o rules thy) sub];
   480     val classrel =
   481       Goal.prove_sorry_global thy [] [] (Logic.mk_classrel (sub, sup))
   482         (fn {context = ctxt, ...} => EVERY (map (TRYALL o resolve_tac ctxt o single) intros));
   483     val diff_sort = Sign.complete_sort thy [sup]
   484       |> subtract (op =) (Sign.complete_sort thy [sub])
   485       |> filter (is_class thy);
   486     fun add_dependency some_wit = case some_dep_morph of
   487         SOME dep_morph => Generic_Target.locale_dependency sub
   488           (sup, dep_morph $> Element.satisfy_morphism (the_list some_witn)) NONE export
   489       | NONE => I;
   490   in
   491     lthy
   492     |> Local_Theory.raw_theory
   493       (Axclass.add_classrel classrel
   494       #> Class_Data.map (Graph.add_edge (sub, sup))
   495       #> activate_defs sub (these_defs thy diff_sort))
   496     |> add_dependency some_witn
   497     |> synchronize_class_syntax_target sub
   498   end;
   499 
   500 local
   501 
   502 fun gen_classrel mk_prop classrel thy =
   503   let
   504     fun after_qed results =
   505       Proof_Context.background_theory ((fold o fold) Axclass.add_classrel results);
   506   in
   507     thy
   508     |> Proof_Context.init_global
   509     |> Proof.theorem NONE after_qed [[(mk_prop thy classrel, [])]]
   510   end;
   511 
   512 in
   513 
   514 val classrel =
   515   gen_classrel (Logic.mk_classrel oo Axclass.cert_classrel);
   516 val classrel_cmd =
   517   gen_classrel (Logic.mk_classrel oo Axclass.read_classrel);
   518 
   519 end; (*local*)
   520 
   521 
   522 (** instantiation target **)
   523 
   524 (* bookkeeping *)
   525 
   526 datatype instantiation = Instantiation of {
   527   arities: string list * (string * sort) list * sort,
   528   params: ((string * string) * (string * typ)) list
   529     (*(instantiation parameter, type constructor), (local instantiation parameter, typ)*)
   530 }
   531 
   532 fun make_instantiation (arities, params) =
   533   Instantiation {arities = arities, params = params};
   534 
   535 val empty_instantiation = make_instantiation (([], [], []), []);
   536 
   537 structure Instantiation = Proof_Data
   538 (
   539   type T = instantiation;
   540   fun init _ = empty_instantiation;
   541 );
   542 
   543 val get_instantiation =
   544   (fn Instantiation data => data) o Instantiation.get o Local_Theory.target_of;
   545 
   546 fun map_instantiation f =
   547   (Local_Theory.target o Instantiation.map)
   548     (fn Instantiation {arities, params} => make_instantiation (f (arities, params)));
   549 
   550 fun the_instantiation lthy =
   551   (case get_instantiation lthy of
   552     {arities = ([], [], []), ...} => error "No instantiation target"
   553   | data => data);
   554 
   555 val instantiation_params = #params o get_instantiation;
   556 
   557 fun instantiation_param lthy b = instantiation_params lthy
   558   |> find_first (fn (_, (v, _)) => Binding.name_of b = v)
   559   |> Option.map (fst o fst);
   560 
   561 fun read_multi_arity thy (raw_tycos, raw_sorts, raw_sort) =
   562   let
   563     val ctxt = Proof_Context.init_global thy;
   564     val all_arities = map (fn raw_tyco => Proof_Context.read_arity ctxt
   565       (raw_tyco, raw_sorts, raw_sort)) raw_tycos;
   566     val tycos = map #1 all_arities;
   567     val (_, sorts, sort) = hd all_arities;
   568     val vs = Name.invent_names Name.context Name.aT sorts;
   569   in (tycos, vs, sort) end;
   570 
   571 
   572 (* syntax *)
   573 
   574 fun synchronize_inst_syntax ctxt =
   575   let
   576     val Instantiation {params, ...} = Instantiation.get ctxt;
   577 
   578     val lookup_inst_param = Axclass.lookup_inst_param
   579       (Sign.consts_of (Proof_Context.theory_of ctxt)) params;
   580     fun subst (c, ty) =
   581       (case lookup_inst_param (c, ty) of
   582         SOME (v_ty as (_, ty)) => SOME (ty, Free v_ty)
   583       | NONE => NONE);
   584     val unchecks =
   585       map (fn ((c, _), v_ty as (_, ty)) => (Free v_ty, Const (c, ty))) params;
   586   in
   587     ctxt
   588     |> Overloading.map_improvable_syntax (fn {primary_constraints, improve, ...} =>
   589       {primary_constraints = primary_constraints, secondary_constraints = [],
   590         improve = improve, subst = subst, no_subst_in_abbrev_mode = false,
   591         unchecks = unchecks})
   592   end;
   593 
   594 fun resort_terms ctxt algebra consts constraints ts =
   595   let
   596     fun matchings (Const (c_ty as (c, _))) =
   597           (case constraints c of
   598             NONE => I
   599           | SOME sorts =>
   600               fold2 (curry (Sorts.meet_sort algebra)) (Consts.typargs consts c_ty) sorts)
   601       | matchings _ = I;
   602     val tvartab = (fold o fold_aterms) matchings ts Vartab.empty
   603       handle Sorts.CLASS_ERROR e => error (Sorts.class_error (Context.Proof ctxt) e);
   604     val inst = map_type_tvar
   605       (fn (vi, sort) => TVar (vi, the_default sort (Vartab.lookup tvartab vi)));
   606   in if Vartab.is_empty tvartab then ts else (map o map_types) inst ts end;
   607 
   608 
   609 (* target *)
   610 
   611 fun define_overloaded (c, U) b (b_def, rhs) lthy =
   612   let
   613     val name = Binding.name_of b;
   614     val pos = Binding.pos_of b;
   615     val _ =
   616       if Context_Position.is_reported lthy pos then
   617         Position.report_text pos Markup.class_parameter
   618           (Pretty.string_of
   619             (Pretty.block [Pretty.keyword1 "class", Pretty.brk 1,
   620                 Pretty.str "parameter", Pretty.brk 1, pretty_param lthy (c, U)]))
   621       else ();
   622   in
   623     lthy |> Local_Theory.background_theory_result
   624       (Axclass.declare_overloaded (c, U) ##>> Axclass.define_overloaded b_def (c, rhs))
   625     ||> (map_instantiation o apsnd) (filter_out (fn (_, (v', _)) => v' = name))
   626     ||> Local_Theory.map_contexts (K synchronize_inst_syntax)
   627   end;
   628 
   629 fun foundation (((b, U), mx), (b_def, rhs)) params lthy =
   630   (case instantiation_param lthy b of
   631     SOME c =>
   632       if Mixfix.is_empty mx then lthy |> define_overloaded (c, U) b (b_def, rhs)
   633       else error ("Illegal mixfix syntax for overloaded constant " ^ quote c)
   634   | NONE => lthy |> Generic_Target.theory_target_foundation (((b, U), mx), (b_def, rhs)) params);
   635 
   636 fun pretty lthy =
   637   let
   638     val {arities = (tycos, vs, sort), params} = the_instantiation lthy;
   639     fun pr_arity tyco = Syntax.pretty_arity lthy (tyco, map snd vs, sort);
   640     fun pr_param ((c, _), (v, ty)) =
   641       Pretty.block (Pretty.breaks
   642         [Pretty.str v, Pretty.str "==", Proof_Context.pretty_const lthy c,
   643           Pretty.str "::", Syntax.pretty_typ lthy ty]);
   644   in
   645     [Pretty.block
   646       (Pretty.fbreaks (Pretty.keyword1 "instantiation" :: map pr_arity tycos @ map pr_param params))]
   647   end;
   648 
   649 fun conclude lthy =
   650   let
   651     val (tycos, vs, sort) = #arities (the_instantiation lthy);
   652     val thy = Proof_Context.theory_of lthy;
   653     val _ = tycos |> List.app (fn tyco =>
   654       if Sign.of_sort thy (Type (tyco, map TFree vs), sort) then ()
   655       else error ("Missing instance proof for type " ^ quote (Proof_Context.markup_type lthy tyco)));
   656   in lthy end;
   657 
   658 fun instantiation (tycos, vs, sort) thy =
   659   let
   660     val _ = if null tycos then error "At least one arity must be given" else ();
   661     val class_params = these_params thy (filter (can (Axclass.get_info thy)) sort);
   662     fun get_param tyco (param, (_, (c, ty))) =
   663       if can (Axclass.param_of_inst thy) (c, tyco)
   664       then NONE else SOME ((c, tyco),
   665         (param ^ "_" ^ Long_Name.base_name tyco, map_atyps (K (Type (tyco, map TFree vs))) ty));
   666     val params = map_product get_param tycos class_params |> map_filter I;
   667     val _ = if null params andalso forall (fn tyco => can (Sign.arity_sorts thy tyco) sort) tycos
   668       then error "No parameters and no pending instance proof obligations in instantiation."
   669       else ();
   670     val primary_constraints = map (apsnd
   671       (map_atyps (K (TVar ((Name.aT, 0), [])))) o snd o snd) class_params;
   672     val algebra = Sign.classes_of thy
   673       |> fold (fn tyco => Sorts.add_arities (Context.Theory thy)
   674             (tyco, map (fn class => (class, map snd vs)) sort)) tycos;
   675     val consts = Sign.consts_of thy;
   676     val improve_constraints = AList.lookup (op =)
   677       (map (fn (_, (class, (c, _))) => (c, [[class]])) class_params);
   678     fun resort_check ctxt ts = resort_terms ctxt algebra consts improve_constraints ts;
   679     val lookup_inst_param = Axclass.lookup_inst_param consts params;
   680     fun improve (c, ty) =
   681       (case lookup_inst_param (c, ty) of
   682         SOME (_, ty') => if Sign.typ_instance thy (ty', ty) then SOME (ty, ty') else NONE
   683       | NONE => NONE);
   684   in
   685     thy
   686     |> Sign.change_begin
   687     |> Proof_Context.init_global
   688     |> Instantiation.put (make_instantiation ((tycos, vs, sort), params))
   689     |> fold (Variable.declare_typ o TFree) vs
   690     |> fold (Variable.declare_names o Free o snd) params
   691     |> (Overloading.map_improvable_syntax) (K {primary_constraints = primary_constraints,
   692       secondary_constraints = [], improve = improve, subst = K NONE,
   693       no_subst_in_abbrev_mode = false, unchecks = []})
   694     |> Overloading.activate_improvable_syntax
   695     |> Context.proof_map (Syntax_Phases.term_check 0 "resorting" resort_check)
   696     |> synchronize_inst_syntax
   697     |> Local_Theory.init (Sign.naming_of thy)
   698        {define = Generic_Target.define foundation,
   699         notes = Generic_Target.notes Generic_Target.theory_target_notes,
   700         abbrev = Generic_Target.abbrev Generic_Target.theory_target_abbrev,
   701         declaration = K Generic_Target.theory_declaration,
   702         theory_registration = Generic_Target.theory_registration,
   703         locale_dependency = fn _ => error "Not possible in instantiation target",
   704         pretty = pretty,
   705         exit = conclude #> Local_Theory.target_of #> Sign.change_end_local}
   706   end;
   707 
   708 fun instantiation_cmd arities thy =
   709   instantiation (read_multi_arity thy arities) thy;
   710 
   711 fun gen_instantiation_instance do_proof after_qed lthy =
   712   let
   713     val (tycos, vs, sort) = (#arities o the_instantiation) lthy;
   714     val arities_proof = maps (fn tyco => Logic.mk_arities (tyco, map snd vs, sort)) tycos;
   715     fun after_qed' results =
   716       Local_Theory.background_theory (fold (Axclass.add_arity o Thm.varifyT_global) results)
   717       #> after_qed;
   718   in
   719     lthy
   720     |> do_proof after_qed' arities_proof
   721   end;
   722 
   723 val instantiation_instance = gen_instantiation_instance (fn after_qed => fn ts =>
   724   Proof.theorem NONE (after_qed o map the_single) (map (fn t => [(t, [])]) ts));
   725 
   726 fun prove_instantiation_instance tac = gen_instantiation_instance (fn after_qed =>
   727   fn ts => fn lthy => after_qed (map (fn t => Goal.prove lthy [] [] t
   728     (fn {context, ...} => tac context)) ts) lthy) I;
   729 
   730 fun prove_instantiation_exit tac = prove_instantiation_instance tac
   731   #> Local_Theory.exit_global;
   732 
   733 fun prove_instantiation_exit_result f tac x lthy =
   734   let
   735     val morph = Proof_Context.export_morphism lthy
   736       (Proof_Context.init_global (Proof_Context.theory_of lthy));
   737     val y = f morph x;
   738   in
   739     lthy
   740     |> prove_instantiation_exit (fn ctxt => tac ctxt y)
   741     |> pair y
   742   end;
   743 
   744 
   745 (* simplified instantiation interface with no class parameter *)
   746 
   747 fun instance_arity_cmd raw_arities thy =
   748   let
   749     val (tycos, vs, sort) = read_multi_arity thy raw_arities;
   750     val sorts = map snd vs;
   751     val arities = maps (fn tyco => Logic.mk_arities (tyco, sorts, sort)) tycos;
   752     fun after_qed results =
   753       Proof_Context.background_theory ((fold o fold) Axclass.add_arity results);
   754   in
   755     thy
   756     |> Proof_Context.init_global
   757     |> Proof.theorem NONE after_qed (map (fn t => [(t, [])]) arities)
   758   end;
   759 
   760 
   761 
   762 (** tactics and methods **)
   763 
   764 fun intro_classes_tac ctxt facts st =
   765   let
   766     val thy = Proof_Context.theory_of ctxt;
   767     val classes = Sign.all_classes thy;
   768     val class_trivs = map (Thm.class_triv thy) classes;
   769     val class_intros = map_filter (try (#intro o Axclass.get_info thy)) classes;
   770     val assm_intros = all_assm_intros thy;
   771   in
   772     Method.intros_tac ctxt (class_trivs @ class_intros @ assm_intros) facts st
   773   end;
   774 
   775 fun standard_intro_classes_tac ctxt facts st =
   776   if null facts andalso not (Thm.no_prems st) then
   777     (intro_classes_tac ctxt [] ORELSE Locale.intro_locales_tac true ctxt []) st
   778   else no_tac st;
   779 
   780 fun standard_tac ctxt facts =
   781   HEADGOAL (Method.some_rule_tac ctxt [] facts) ORELSE
   782   standard_intro_classes_tac ctxt facts;
   783 
   784 val _ = Theory.setup
   785  (Method.setup @{binding intro_classes} (Scan.succeed (METHOD o intro_classes_tac))
   786     "back-chain introduction rules of classes" #>
   787   Method.setup @{binding standard} (Scan.succeed (METHOD o standard_tac))
   788     "standard proof step: Pure intro/elim rule or class introduction");
   789 
   790 
   791 
   792 (** diagnostics **)
   793 
   794 fun pretty_specification thy class =
   795   if is_class thy class then
   796     let
   797       val class_ctxt = init class thy;
   798       val prt_class = Name_Space.pretty class_ctxt (Proof_Context.class_space class_ctxt);
   799 
   800       val super_classes = Sign.minimize_sort thy (Sign.super_classes thy class);
   801 
   802       val fix_args =
   803         #params (Axclass.get_info thy class)
   804         |> map (fn (c, T) => (Binding.name (Long_Name.base_name c), SOME T, NoSyn));
   805       val fixes = if null fix_args then [] else [Element.Fixes fix_args];
   806       val assumes = Locale.hyp_spec_of thy class;
   807 
   808       val header =
   809         [Pretty.keyword1 "class", Pretty.brk 1, prt_class class, Pretty.str " =", Pretty.brk 1] @
   810         Pretty.separate " +" (map prt_class super_classes) @
   811         (if null super_classes then [] else [Pretty.str " +"]);
   812       val body =
   813         if null fixes andalso null assumes then []
   814         else
   815           maps (Element.pretty_ctxt_no_attribs class_ctxt) (fixes @ assumes)
   816           |> maps (fn prt => [Pretty.fbrk, prt]);
   817     in if null body then [] else [Pretty.block (header @ body)] end
   818   else [];
   819 
   820 end;