src/HOL/Tools/Lifting/lifting_setup.ML
changeset 60225 eb4e322734bf
parent 59936 b8ffc3dc9e24
child 60226 ec23f2a97ba4
equal deleted inserted replaced
60224:e759afe46a8c 60225:eb4e322734bf
     6 
     6 
     7 signature LIFTING_SETUP =
     7 signature LIFTING_SETUP =
     8 sig
     8 sig
     9   exception SETUP_LIFTING_INFR of string
     9   exception SETUP_LIFTING_INFR of string
    10 
    10 
    11   val setup_by_quotient: thm -> thm option -> thm option -> local_theory -> local_theory
    11   type config = { notes: bool };
    12 
    12   val default_config: config;
    13   val setup_by_typedef_thm: thm -> local_theory -> local_theory
    13 
       
    14   val setup_by_quotient: config -> thm -> thm option -> thm option -> local_theory -> 
       
    15     binding * local_theory
       
    16 
       
    17   val setup_by_typedef_thm: config -> thm -> local_theory -> binding * local_theory
    14 
    18 
    15   val lifting_restore: Lifting_Info.quotient -> Context.generic -> Context.generic
    19   val lifting_restore: Lifting_Info.quotient -> Context.generic -> Context.generic
    16 end
    20 end
    17 
    21 
    18 structure Lifting_Setup: LIFTING_SETUP =
    22 structure Lifting_Setup: LIFTING_SETUP =
    22 
    26 
    23 infix 0 MRSL
    27 infix 0 MRSL
    24 
    28 
    25 exception SETUP_LIFTING_INFR of string
    29 exception SETUP_LIFTING_INFR of string
    26 
    30 
    27 fun define_crel rep_fun lthy =
    31 (* Config *)
       
    32 
       
    33 type config = { notes: bool };
       
    34 val default_config = { notes = true };
       
    35 
       
    36 fun define_crel config rep_fun lthy =
    28   let
    37   let
    29     val (qty, rty) = (dest_funT o fastype_of) rep_fun
    38     val (qty, rty) = (dest_funT o fastype_of) rep_fun
    30     val rep_fun_graph = (HOLogic.eq_const rty) $ Bound 1 $ (rep_fun $ Bound 0)
    39     val rep_fun_graph = (HOLogic.eq_const rty) $ Bound 1 $ (rep_fun $ Bound 0)
    31     val def_term = Abs ("x", rty, Abs ("y", qty, rep_fun_graph))
    40     val def_term = Abs ("x", rty, Abs ("y", qty, rep_fun_graph))
    32     val qty_name = (Binding.name o Long_Name.base_name o fst o dest_Type) qty
    41     val qty_name = (Binding.name o Long_Name.base_name o fst o dest_Type) qty
    33     val crel_name = Binding.prefix_name "cr_" qty_name
    42     val crel_name = Binding.prefix_name "cr_" qty_name
    34     val (fixed_def_term, lthy') = yield_singleton (Variable.importT_terms) def_term lthy
    43     val (fixed_def_term, lthy) = yield_singleton (Variable.importT_terms) def_term lthy
    35     val ((_, (_ , def_thm)), lthy'') =
    44     val ((_, (_ , def_thm)), lthy) = if #notes config then
    36       Local_Theory.define ((crel_name, NoSyn), ((Thm.def_binding crel_name, []), fixed_def_term)) lthy'
    45         Local_Theory.define ((crel_name, NoSyn), ((Thm.def_binding crel_name, []), fixed_def_term)) lthy
    37   in
    46       else 
    38     (def_thm, lthy'')
    47         Local_Theory.define ((Binding.concealed crel_name, NoSyn), ((Binding.empty, []), fixed_def_term)) lthy
       
    48   in  
       
    49     (def_thm, lthy)
    39   end
    50   end
    40 
    51 
    41 fun print_define_pcrel_warning msg = 
    52 fun print_define_pcrel_warning msg = 
    42   let
    53   let
    43     val warning_msg = cat_lines 
    54     val warning_msg = cat_lines 
    46          [Pretty.str "Reason:", Pretty.brk 2, msg]))]
    57          [Pretty.str "Reason:", Pretty.brk 2, msg]))]
    47   in
    58   in
    48     warning warning_msg
    59     warning warning_msg
    49   end
    60   end
    50 
    61 
    51 fun define_pcrel crel lthy =
    62 fun define_pcrel config crel lthy =
    52   let
    63   let
    53     val (fixed_crel, lthy) = yield_singleton Variable.importT_terms crel lthy
    64     val (fixed_crel, lthy) = yield_singleton Variable.importT_terms crel lthy
    54     val [rty', qty] = (binder_types o fastype_of) fixed_crel
    65     val [rty', qty] = (binder_types o fastype_of) fixed_crel
    55     val (param_rel, args) = Lifting_Term.generate_parametrized_relator lthy rty'
    66     val (param_rel, args) = Lifting_Term.generate_parametrized_relator lthy rty'
    56     val rty_raw = (domain_type o range_type o fastype_of) param_rel
    67     val rty_raw = (domain_type o range_type o fastype_of) param_rel
    65     val rty = (domain_type o fastype_of) param_rel_fixed
    76     val rty = (domain_type o fastype_of) param_rel_fixed
    66     val relcomp_op = Const (@{const_name "relcompp"}, 
    77     val relcomp_op = Const (@{const_name "relcompp"}, 
    67           (rty --> rty' --> HOLogic.boolT) --> 
    78           (rty --> rty' --> HOLogic.boolT) --> 
    68           (rty' --> qty --> HOLogic.boolT) --> 
    79           (rty' --> qty --> HOLogic.boolT) --> 
    69           rty --> qty --> HOLogic.boolT)
    80           rty --> qty --> HOLogic.boolT)
    70     val relator_type = foldr1 (op -->) ((map type_of args_fixed) @ [rty, qty, HOLogic.boolT])
       
    71     val qty_name = (fst o dest_Type) qty
    81     val qty_name = (fst o dest_Type) qty
    72     val pcrel_name = Binding.prefix_name "pcr_" ((Binding.name o Long_Name.base_name) qty_name)
    82     val pcrel_name = Binding.prefix_name "pcr_" ((Binding.name o Long_Name.base_name) qty_name)
       
    83     val relator_type = foldr1 (op -->) ((map type_of args_fixed) @ [rty, qty, HOLogic.boolT])
    73     val lhs = Library.foldl (op $) ((Free (Binding.name_of pcrel_name, relator_type)), args_fixed)
    84     val lhs = Library.foldl (op $) ((Free (Binding.name_of pcrel_name, relator_type)), args_fixed)
    74     val rhs = relcomp_op $ param_rel_fixed $ fixed_crel
    85     val rhs = relcomp_op $ param_rel_fixed $ fixed_crel
    75     val definition_term = Logic.mk_equals (lhs, rhs)
    86     val definition_term = Logic.mk_equals (lhs, rhs)
    76     val ((_, (_, def_thm)), lthy) = Specification.definition ((SOME (pcrel_name, SOME relator_type, NoSyn)), 
    87     fun note_def lthy =
    77       ((Binding.empty, []), definition_term)) lthy
    88       Specification.definition ((SOME (pcrel_name, SOME relator_type, NoSyn)), 
       
    89         ((Binding.empty, []), definition_term)) lthy |>> (snd #> snd);
       
    90     fun raw_def lthy =
       
    91       let
       
    92         val ((_, rhs), prove) = Local_Defs.derived_def lthy true definition_term;
       
    93         val ((_, (_, raw_th)), lthy) = lthy
       
    94           |> Local_Theory.define ((Binding.concealed pcrel_name, NoSyn), ((Binding.empty, []), rhs));
       
    95         val th = prove lthy raw_th;
       
    96       in
       
    97         (th, lthy)
       
    98       end
       
    99     val (def_thm, lthy) = if #notes config then note_def lthy else raw_def lthy
    78   in
   100   in
    79     (SOME def_thm, lthy)
   101     (SOME def_thm, lthy)
    80   end
   102   end
    81   handle Lifting_Term.PARAM_QUOT_THM (_, msg) => (print_define_pcrel_warning msg; (NONE, lthy))
   103   handle Lifting_Term.PARAM_QUOT_THM (_, msg) => (print_define_pcrel_warning msg; (NONE, lthy))
    82 
   104 
    94          "Most probably a relator_eq rule for one of the involved types is missing."]
   116          "Most probably a relator_eq rule for one of the involved types is missing."]
    95     in
   117     in
    96       error error_msg
   118       error error_msg
    97     end
   119     end
    98 in
   120 in
    99   fun define_pcr_cr_eq lthy pcr_rel_def =
   121   fun define_pcr_cr_eq config lthy pcr_rel_def =
   100     let
   122     let
   101       val lhs = (Thm.term_of o Thm.lhs_of) pcr_rel_def
   123       val lhs = (Thm.term_of o Thm.lhs_of) pcr_rel_def
   102       val qty_name = (Binding.name o Long_Name.base_name o fst o dest_Type o List.last o binder_types o fastype_of) lhs
   124       val qty_name = (Binding.name o Long_Name.base_name o fst o dest_Type o List.last o binder_types o fastype_of) lhs
   103       val args = (snd o strip_comb) lhs
   125       val args = (snd o strip_comb) lhs
   104       
   126       
   125           val thm = 
   147           val thm = 
   126             pcr_cr_eq
   148             pcr_cr_eq
   127             |> Conv.fconv_rule (Conv.arg_conv (Conv.rewr_conv eq_OO_meta))
   149             |> Conv.fconv_rule (Conv.arg_conv (Conv.rewr_conv eq_OO_meta))
   128             |> mk_HOL_eq
   150             |> mk_HOL_eq
   129             |> singleton (Variable.export lthy orig_lthy)
   151             |> singleton (Variable.export lthy orig_lthy)
   130           val ((_, [thm]), lthy) =
   152           val lthy = (#notes config ? (Local_Theory.note 
   131             Local_Theory.note ((Binding.qualified true "pcr_cr_eq" qty_name, []), [thm]) lthy
   153               ((Binding.qualified true "pcr_cr_eq" qty_name, []), [thm]) #> snd)) lthy
   132         in
   154         in
   133           (thm, lthy)
   155           (thm, lthy)
   134         end
   156         end
   135       | Const (@{const_name "relcompp"}, _) $ t $ _ => print_generate_pcr_cr_eq_error lthy t
   157       | Const (@{const_name "relcompp"}, _) $ t $ _ => print_generate_pcr_cr_eq_error lthy t
   136       | _ => error "generate_pcr_cr_eq: implementation error"
   158       | _ => error "generate_pcr_cr_eq: implementation error"
   227   in
   249   in
   228     lthy 
   250     lthy 
   229       |> Local_Theory.declaration {syntax = false, pervasive = true}
   251       |> Local_Theory.declaration {syntax = false, pervasive = true}
   230            (fn phi => Lifting_Info.init_restore_data bundle_name (phi_qinfo phi))
   252            (fn phi => Lifting_Info.init_restore_data bundle_name (phi_qinfo phi))
   231       |> Bundle.bundle ((binding, [restore_lifting_att])) []
   253       |> Bundle.bundle ((binding, [restore_lifting_att])) []
   232   end
   254       |> pair binding
   233 
   255   end
   234 fun setup_lifting_infr quot_thm opt_reflp_thm lthy =
   256 
       
   257 fun setup_lifting_infr config quot_thm opt_reflp_thm lthy =
   235   let
   258   let
   236     val _ = quot_thm_sanity_check lthy quot_thm
   259     val _ = quot_thm_sanity_check lthy quot_thm
   237     val (_, qty) = quot_thm_rty_qty quot_thm
   260     val (_, qty) = quot_thm_rty_qty quot_thm
   238     val (pcrel_def, lthy) = define_pcrel (quot_thm_crel quot_thm) lthy
   261     val (pcrel_def, lthy) = define_pcrel config (quot_thm_crel quot_thm) lthy
   239     (**)
   262     (**)
   240     val pcrel_def = Option.map (Morphism.thm (Local_Theory.target_morphism lthy)) pcrel_def
   263     val pcrel_def = Option.map (Morphism.thm (Local_Theory.target_morphism lthy)) pcrel_def
   241     (**)
   264     (**)
   242     val (pcr_cr_eq, lthy) = case pcrel_def of
   265     val (pcr_cr_eq, lthy) = case pcrel_def of
   243       SOME pcrel_def => apfst SOME (define_pcr_cr_eq lthy pcrel_def)
   266       SOME pcrel_def => apfst SOME (define_pcr_cr_eq config lthy pcrel_def)
   244       | NONE => (NONE, lthy)
   267       | NONE => (NONE, lthy)
   245     val pcr_info = case pcrel_def of
   268     val pcr_info = case pcrel_def of
   246       SOME pcrel_def => SOME { pcrel_def = pcrel_def, pcr_cr_eq = the pcr_cr_eq }
   269       SOME pcrel_def => SOME { pcrel_def = pcrel_def, pcr_cr_eq = the pcr_cr_eq }
   247       | NONE => NONE
   270       | NONE => NONE
   248     val quotients = { quot_thm = quot_thm, pcr_info = pcr_info }
   271     val quotients = { quot_thm = quot_thm, pcr_info = pcr_info }
   442           |> reduce_Domainp ctxt (Transfer.get_relator_domain ctxt)
   465           |> reduce_Domainp ctxt (Transfer.get_relator_domain ctxt)
   443       val pcr_Domainp = 
   466       val pcr_Domainp = 
   444         (dom_thm RS @{thm pcr_Domainp})
   467         (dom_thm RS @{thm pcr_Domainp})
   445           |> fold_Domainp_pcrel pcrel_def
   468           |> fold_Domainp_pcrel pcrel_def
   446       val thms =
   469       val thms =
   447         [("domain",                 pcr_Domainp),
   470         [("domain",                 [pcr_Domainp], @{attributes [transfer_domain_rule]}),
   448          ("domain_par",             pcr_Domainp_par),
   471          ("domain_par",             [pcr_Domainp_par], @{attributes [transfer_domain_rule]}),
   449          ("domain_par_left_total",  pcr_Domainp_par_left_total),
   472          ("domain_par_left_total",  [pcr_Domainp_par_left_total], @{attributes [transfer_domain_rule]}),
   450          ("domain_eq",              pcr_Domainp_eq)]
   473          ("domain_eq",              [pcr_Domainp_eq], @{attributes [transfer_domain_rule]})]
   451     in
   474     in
   452       thms
   475       thms
   453     end
   476     end
   454 
   477 
   455   fun parametrize_total_domain left_total pcrel_def ctxt =
   478   fun parametrize_total_domain left_total pcrel_def ctxt =
   457       val thm =
   480       val thm =
   458         (left_total RS @{thm pcr_Domainp_total})
   481         (left_total RS @{thm pcr_Domainp_total})
   459           |> fold_Domainp_pcrel pcrel_def 
   482           |> fold_Domainp_pcrel pcrel_def 
   460           |> reduce_Domainp ctxt (Transfer.get_relator_domain ctxt)
   483           |> reduce_Domainp ctxt (Transfer.get_relator_domain ctxt)
   461     in
   484     in
   462       [("domain", thm)]
   485       [("domain", [thm], @{attributes [transfer_domain_rule]})]
   463     end
   486     end
   464 
   487 
   465 end
   488 end
   466 
   489 
   467 fun get_pcrel_info ctxt qty_full_name =  
   490 fun get_pcrel_info ctxt qty_full_name =  
   468   #pcr_info (the (Lifting_Info.lookup_quotients ctxt qty_full_name))
   491   #pcr_info (the (Lifting_Info.lookup_quotients ctxt qty_full_name))
   469 
   492 
   470 fun get_Domainp_thm quot_thm =
   493 fun get_Domainp_thm quot_thm =
   471    the (get_first (try(curry op RS quot_thm)) [@{thm eq_onp_to_Domainp}, @{thm Quotient_to_Domainp}])
   494    the (get_first (try(curry op RS quot_thm)) [@{thm eq_onp_to_Domainp}, @{thm Quotient_to_Domainp}])
       
   495 
       
   496 fun notes names thms = 
       
   497   let
       
   498     val notes =
       
   499         if names then map (fn (name, thms, attrs) => ((name, []), [(thms, attrs)])) thms
       
   500         else map_filter (fn (_, thms, attrs) => if null attrs then NONE 
       
   501           else SOME ((Binding.empty, []), [(thms, attrs)])) thms
       
   502   in
       
   503     Local_Theory.notes notes #> snd
       
   504   end
       
   505 
       
   506 fun map_thms map_name map_thm thms = 
       
   507   map (fn (name, thms, attr) => (map_name name, map map_thm thms, attr)) thms
   472 
   508 
   473 (*
   509 (*
   474   Sets up the Lifting package by a quotient theorem.
   510   Sets up the Lifting package by a quotient theorem.
   475 
   511 
   476   quot_thm - a quotient theorem (Quotient R Abs Rep T)
   512   quot_thm - a quotient theorem (Quotient R Abs Rep T)
   477   opt_reflp_thm - a theorem saying that a relation from quot_thm is reflexive
   513   opt_reflp_thm - a theorem saying that a relation from quot_thm is reflexive
   478     (in the form "reflp R")
   514     (in the form "reflp R")
   479   opt_par_thm - a parametricity theorem for R
   515   opt_par_thm - a parametricity theorem for R
   480 *)
   516 *)
   481 
   517 
   482 fun setup_by_quotient quot_thm opt_reflp_thm opt_par_thm lthy =
   518 fun setup_by_quotient config quot_thm opt_reflp_thm opt_par_thm lthy =
   483   let
   519   let
   484     (**)
   520     (**)
   485     val quot_thm = Morphism.thm (Local_Theory.target_morphism lthy) quot_thm
   521     val quot_thm = Morphism.thm (Local_Theory.target_morphism lthy) quot_thm
   486     (**)
   522     (**)
   487     val transfer_attr = Attrib.internal (K Transfer.transfer_add)
       
   488     val transfer_domain_attr = Attrib.internal (K Transfer.transfer_domain_add)
       
   489     val (rty, qty) = quot_thm_rty_qty quot_thm
   523     val (rty, qty) = quot_thm_rty_qty quot_thm
   490     val induct_attr = Attrib.internal (K (Induct.induct_type (fst (dest_Type qty))))
   524     val induct_attr = Attrib.internal (K (Induct.induct_type (fst (dest_Type qty))))
   491     val qty_full_name = (fst o dest_Type) qty
   525     val qty_full_name = (fst o dest_Type) qty
   492     val qty_name = (Binding.name o Long_Name.base_name) qty_full_name
   526     val qty_name = (Binding.name o Long_Name.base_name) qty_full_name
   493     fun qualify suffix = Binding.qualified true suffix qty_name
   527     fun qualify suffix = Binding.qualified true suffix qty_name
   494     val lthy = case opt_reflp_thm of
   528     val notes1 = case opt_reflp_thm of
   495       SOME reflp_thm =>
   529       SOME reflp_thm =>
   496         let 
   530         let 
   497           val thms =
   531           val thms =
   498             [("abs_induct",     @{thm Quotient_total_abs_induct}, [induct_attr]),
   532             [("abs_induct",     @{thms Quotient_total_abs_induct}, [induct_attr]),
   499              ("abs_eq_iff",     @{thm Quotient_total_abs_eq_iff}, []           )]
   533              ("abs_eq_iff",     @{thms Quotient_total_abs_eq_iff}, []           )]
   500         in
   534         in
   501           lthy
   535           map_thms qualify (fn thm => [quot_thm, reflp_thm] MRSL thm) thms
   502             |> fold (fn (name, thm, attr) => (snd oo Local_Theory.note) ((qualify name, attr), 
       
   503               [[quot_thm, reflp_thm] MRSL thm])) thms
       
   504         end
   536         end
   505       | NONE =>
   537       | NONE =>
   506         let
   538         let
   507           val thms = 
   539           val thms = 
   508             [("abs_induct",     @{thm Quotient_abs_induct},       [induct_attr])]
   540             [("abs_induct",     @{thms Quotient_abs_induct},       [induct_attr])]
   509         in
   541         in
   510           fold (fn (name, thm, attr) => (snd oo Local_Theory.note) ((qualify name, attr), 
   542           map_thms qualify (fn thm => quot_thm RS thm) thms
   511             [quot_thm RS thm])) thms lthy
       
   512         end
   543         end
   513     val dom_thm = get_Domainp_thm quot_thm
   544     val dom_thm = get_Domainp_thm quot_thm
   514 
   545 
   515     fun setup_transfer_rules_nonpar lthy =
   546     fun setup_transfer_rules_nonpar notes =
   516       let
   547       let
   517         val lthy =
   548         val notes1 =
   518           case opt_reflp_thm of
   549           case opt_reflp_thm of
   519             SOME reflp_thm =>
   550             SOME reflp_thm =>
   520               let 
   551               let 
   521                 val thms =
   552                 val thms =
   522                   [("id_abs_transfer",@{thm Quotient_id_abs_transfer}),
   553                   [("id_abs_transfer",@{thms Quotient_id_abs_transfer}, @{attributes [transfer_rule]}),
   523                    ("left_total",     @{thm Quotient_left_total}     ),
   554                    ("left_total",     @{thms Quotient_left_total},      @{attributes [transfer_rule]}),
   524                    ("bi_total",       @{thm Quotient_bi_total})]
   555                    ("bi_total",       @{thms Quotient_bi_total},        @{attributes [transfer_rule]})]
   525               in
   556               in
   526                 fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   557                 map_thms qualify (fn thm => [quot_thm, reflp_thm] MRSL thm) thms
   527                     [[quot_thm, reflp_thm] MRSL thm])) thms lthy
       
   528               end
   558               end
   529             | NONE =>
   559             | NONE => map_thms qualify I [("domain", [dom_thm], @{attributes [transfer_domain_rule]})]
   530               lthy
   560 
   531               |> (snd oo Local_Theory.note) ((qualify "domain", [transfer_domain_attr]), [dom_thm])
   561         val notes2 = map_thms qualify (fn thm => quot_thm RS thm)
   532 
   562           [("rel_eq_transfer", @{thms Quotient_rel_eq_transfer}, @{attributes [transfer_rule]}),
   533         val thms = 
   563            ("right_unique",    @{thms Quotient_right_unique},    @{attributes [transfer_rule]}), 
   534           [("rel_eq_transfer", @{thm Quotient_rel_eq_transfer}),
   564            ("right_total",     @{thms Quotient_right_total},     @{attributes [transfer_rule]})]
   535            ("right_unique",    @{thm Quotient_right_unique}   ), 
   565       in
   536            ("right_total",     @{thm Quotient_right_total}    )]
   566          notes2 @ notes1 @ notes
   537       in
       
   538         fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
       
   539           [quot_thm RS thm])) thms lthy
       
   540       end
   567       end
   541 
   568 
   542     fun generate_parametric_rel_eq lthy transfer_rule opt_param_thm =
   569     fun generate_parametric_rel_eq lthy transfer_rule opt_param_thm =
   543       option_fold transfer_rule (Lifting_Def.generate_parametric_transfer_rule lthy transfer_rule) opt_param_thm
   570       option_fold transfer_rule (Lifting_Def.generate_parametric_transfer_rule lthy transfer_rule) opt_param_thm
   544       handle Lifting_Term.MERGE_TRANSFER_REL msg => 
   571       handle Lifting_Term.MERGE_TRANSFER_REL msg => 
   549                [Pretty.str "Reason:", Pretty.brk 2, msg]))]
   576                [Pretty.str "Reason:", Pretty.brk 2, msg]))]
   550         in
   577         in
   551           error error_msg
   578           error error_msg
   552         end
   579         end
   553 
   580 
   554     fun setup_transfer_rules_par lthy =
   581     fun setup_transfer_rules_par lthy notes =
   555       let
   582       let
   556         val pcrel_info = (the (get_pcrel_info lthy qty_full_name))
   583         val pcrel_info = (the (get_pcrel_info lthy qty_full_name))
   557         val pcrel_def = #pcrel_def pcrel_info
   584         val pcrel_def = #pcrel_def pcrel_info
   558         val lthy =
   585         val notes1 =
   559           case opt_reflp_thm of
   586           case opt_reflp_thm of
   560             SOME reflp_thm =>
   587             SOME reflp_thm =>
   561               let
   588               let
   562                 val left_total = ([quot_thm, reflp_thm] MRSL @{thm Quotient_left_total})
   589                 val left_total = ([quot_thm, reflp_thm] MRSL @{thm Quotient_left_total})
   563                 val bi_total = ([quot_thm, reflp_thm] MRSL @{thm Quotient_bi_total})
   590                 val bi_total = ([quot_thm, reflp_thm] MRSL @{thm Quotient_bi_total})
   566                   (Lifting_Term.parametrize_transfer_rule lthy
   593                   (Lifting_Term.parametrize_transfer_rule lthy
   567                     ([quot_thm, reflp_thm] MRSL @{thm Quotient_id_abs_transfer}))
   594                     ([quot_thm, reflp_thm] MRSL @{thm Quotient_id_abs_transfer}))
   568                 val left_total = parametrize_class_constraint lthy pcrel_def left_total
   595                 val left_total = parametrize_class_constraint lthy pcrel_def left_total
   569                 val bi_total = parametrize_class_constraint lthy pcrel_def bi_total
   596                 val bi_total = parametrize_class_constraint lthy pcrel_def bi_total
   570                 val thms = 
   597                 val thms = 
   571                   [("id_abs_transfer",id_abs_transfer),
   598                   [("id_abs_transfer", [id_abs_transfer], @{attributes [transfer_rule]}),
   572                    ("left_total",     left_total     ),  
   599                    ("left_total",      [left_total],      @{attributes [transfer_rule]}),  
   573                    ("bi_total",       bi_total       )]
   600                    ("bi_total",        [bi_total],        @{attributes [transfer_rule]})]
   574               in
   601               in
   575                 lthy
   602                 map_thms qualify I thms @ map_thms qualify I domain_thms
   576                 |> fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
       
   577                      [thm])) thms
       
   578                 |> fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_domain_attr]), 
       
   579                      [thm])) domain_thms
       
   580               end
   603               end
   581             | NONE =>
   604             | NONE =>
   582               let
   605               let
   583                 val thms = parametrize_domain dom_thm pcrel_info lthy
   606                 val thms = parametrize_domain dom_thm pcrel_info lthy
   584               in
   607               in
   585                 fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_domain_attr]), 
   608                 map_thms qualify I thms
   586                   [thm])) thms lthy
       
   587               end
   609               end
   588 
   610 
   589         val rel_eq_transfer = generate_parametric_rel_eq lthy 
   611         val rel_eq_transfer = generate_parametric_rel_eq lthy 
   590           (Lifting_Term.parametrize_transfer_rule lthy (quot_thm RS @{thm Quotient_rel_eq_transfer}))
   612           (Lifting_Term.parametrize_transfer_rule lthy (quot_thm RS @{thm Quotient_rel_eq_transfer}))
   591             opt_par_thm
   613             opt_par_thm
   592         val right_unique = parametrize_class_constraint lthy pcrel_def 
   614         val right_unique = parametrize_class_constraint lthy pcrel_def 
   593             (quot_thm RS @{thm Quotient_right_unique})
   615             (quot_thm RS @{thm Quotient_right_unique})
   594         val right_total = parametrize_class_constraint lthy pcrel_def 
   616         val right_total = parametrize_class_constraint lthy pcrel_def 
   595             (quot_thm RS @{thm Quotient_right_total})
   617             (quot_thm RS @{thm Quotient_right_total})
   596         val thms = 
   618         val notes2 = map_thms qualify I
   597           [("rel_eq_transfer", rel_eq_transfer),
   619           [("rel_eq_transfer", [rel_eq_transfer], @{attributes [transfer_rule]}),
   598            ("right_unique",    right_unique   ), 
   620            ("right_unique",    [right_unique],    @{attributes [transfer_rule]}), 
   599            ("right_total",     right_total    )]      
   621            ("right_total",     [right_total],     @{attributes [transfer_rule]})]      
   600       in
   622       in
   601         fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   623         notes2 @ notes1 @ notes
   602           [thm])) thms lthy
   624       end
   603       end
   625 
   604 
   626     fun setup_rules lthy = 
   605     fun setup_transfer_rules lthy = 
   627       let
   606       if is_some (get_pcrel_info lthy qty_full_name) then setup_transfer_rules_par lthy
   628         val thms =  if is_some (get_pcrel_info lthy qty_full_name) 
   607                                                      else setup_transfer_rules_nonpar lthy
   629           then setup_transfer_rules_par lthy notes1 else setup_transfer_rules_nonpar notes1
       
   630       in
       
   631         notes (#notes config) thms lthy
       
   632       end
   608   in
   633   in
   609     lthy
   634     lthy
   610       |> setup_lifting_infr quot_thm opt_reflp_thm
   635       |> setup_lifting_infr config quot_thm opt_reflp_thm
   611       |> setup_transfer_rules
   636       ||> setup_rules
   612   end
   637   end
   613 
   638 
   614 (*
   639 (*
   615   Sets up the Lifting package by a typedef theorem.
   640   Sets up the Lifting package by a typedef theorem.
   616 
   641 
   617   gen_code - flag if an abstract type given by typedef_thm should be registred 
   642   gen_code - flag if an abstract type given by typedef_thm should be registred 
   618     as an abstract type in the code generator
   643     as an abstract type in the code generator
   619   typedef_thm - a typedef theorem (type_definition Rep Abs S)
   644   typedef_thm - a typedef theorem (type_definition Rep Abs S)
   620 *)
   645 *)
   621 
   646 
   622 fun setup_by_typedef_thm typedef_thm lthy =
   647 fun setup_by_typedef_thm config typedef_thm lthy =
   623   let
   648   let
   624     val transfer_attr = Attrib.internal (K Transfer.transfer_add)
       
   625     val transfer_domain_attr = Attrib.internal (K Transfer.transfer_domain_add)
       
   626     val (_ $ rep_fun $ _ $ typedef_set) = (HOLogic.dest_Trueprop o Thm.prop_of) typedef_thm
   649     val (_ $ rep_fun $ _ $ typedef_set) = (HOLogic.dest_Trueprop o Thm.prop_of) typedef_thm
   627     val (T_def, lthy) = define_crel rep_fun lthy
   650     val (T_def, lthy) = define_crel config rep_fun lthy
   628     (**)
   651     (**)
   629     val T_def = Morphism.thm (Local_Theory.target_morphism lthy) T_def
   652     val T_def = Morphism.thm (Local_Theory.target_morphism lthy) T_def
   630     (**)    
   653     (**)    
   631     val quot_thm = case typedef_set of
   654     val quot_thm = case typedef_set of
   632       Const (@{const_name top}, _) => 
   655       Const (@{const_name top}, _) => 
   644         Const (@{const_name top}, _) => 
   667         Const (@{const_name top}, _) => 
   645           SOME ((typedef_thm RS @{thm UNIV_typedef_to_equivp}) RS @{thm equivp_reflp2})
   668           SOME ((typedef_thm RS @{thm UNIV_typedef_to_equivp}) RS @{thm equivp_reflp2})
   646         | _ =>  NONE
   669         | _ =>  NONE
   647     val dom_thm = get_Domainp_thm quot_thm
   670     val dom_thm = get_Domainp_thm quot_thm
   648 
   671 
   649     fun setup_transfer_rules_nonpar lthy =
   672     fun setup_transfer_rules_nonpar notes =
   650       let
   673       let
   651         val lthy =
   674         val notes1 =
   652           case opt_reflp_thm of
   675           case opt_reflp_thm of
   653             SOME reflp_thm =>
   676             SOME reflp_thm =>
   654               let 
   677               let 
   655                 val thms =
   678                 val thms =
   656                   [("id_abs_transfer",@{thm Quotient_id_abs_transfer}),
   679                   [("id_abs_transfer",@{thms Quotient_id_abs_transfer}, @{attributes [transfer_rule]}),
   657                    ("left_total",     @{thm Quotient_left_total}     ),
   680                    ("left_total",     @{thms Quotient_left_total},      @{attributes [transfer_rule]}),
   658                    ("bi_total",     @{thm Quotient_bi_total}         )]
   681                    ("bi_total",       @{thms Quotient_bi_total},        @{attributes [transfer_rule]})]
   659               in
   682               in
   660                 fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   683                 map_thms qualify (fn thm => [quot_thm, reflp_thm] MRSL thm) thms
   661                     [[quot_thm, reflp_thm] MRSL thm])) thms lthy
       
   662               end
   684               end
   663             | NONE =>
   685             | NONE =>
   664               lthy
   686               map_thms qualify I [("domain", [dom_thm], @{attributes [transfer_domain_rule]})]
   665               |> (snd oo Local_Theory.note) ((qualify "domain", [transfer_domain_attr]), [dom_thm])
       
   666         val thms = 
   687         val thms = 
   667           [("rep_transfer", @{thm typedef_rep_transfer}),
   688           [("rep_transfer", @{thms typedef_rep_transfer}, @{attributes [transfer_rule]}),
   668            ("left_unique",  @{thm typedef_left_unique} ),
   689            ("left_unique",  @{thms typedef_left_unique},  @{attributes [transfer_rule]}),
   669            ("right_unique", @{thm typedef_right_unique}), 
   690            ("right_unique", @{thms typedef_right_unique}, @{attributes [transfer_rule]}), 
   670            ("right_total",  @{thm typedef_right_total} ),
   691            ("right_total",  @{thms typedef_right_total},  @{attributes [transfer_rule]}),
   671            ("bi_unique",    @{thm typedef_bi_unique}   )]
   692            ("bi_unique",    @{thms typedef_bi_unique},    @{attributes [transfer_rule]})]
   672       in
   693       in                                               
   673         fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   694         map_thms qualify (fn thm => [typedef_thm, T_def] MRSL thm) thms @ notes1 @ notes
   674           [[typedef_thm, T_def] MRSL thm])) thms lthy
   695       end
   675       end
   696 
   676 
   697     fun setup_transfer_rules_par lthy notes =
   677     fun setup_transfer_rules_par lthy =
       
   678       let
   698       let
   679         val pcrel_info = (the (get_pcrel_info lthy qty_full_name))
   699         val pcrel_info = (the (get_pcrel_info lthy qty_full_name))
   680         val pcrel_def = #pcrel_def pcrel_info
   700         val pcrel_def = #pcrel_def pcrel_info
   681 
   701 
   682         val lthy =
   702         val notes1 =
   683           case opt_reflp_thm of
   703           case opt_reflp_thm of
   684             SOME reflp_thm =>
   704             SOME reflp_thm =>
   685               let
   705               let
   686                 val left_total = ([quot_thm, reflp_thm] MRSL @{thm Quotient_left_total})
   706                 val left_total = ([quot_thm, reflp_thm] MRSL @{thm Quotient_left_total})
   687                 val bi_total = ([quot_thm, reflp_thm] MRSL @{thm Quotient_bi_total})
   707                 val bi_total = ([quot_thm, reflp_thm] MRSL @{thm Quotient_bi_total})
   690                 val bi_total = parametrize_class_constraint lthy pcrel_def bi_total
   710                 val bi_total = parametrize_class_constraint lthy pcrel_def bi_total
   691                 val id_abs_transfer = generate_parametric_id lthy rty
   711                 val id_abs_transfer = generate_parametric_id lthy rty
   692                   (Lifting_Term.parametrize_transfer_rule lthy
   712                   (Lifting_Term.parametrize_transfer_rule lthy
   693                     ([quot_thm, reflp_thm] MRSL @{thm Quotient_id_abs_transfer}))
   713                     ([quot_thm, reflp_thm] MRSL @{thm Quotient_id_abs_transfer}))
   694                 val thms = 
   714                 val thms = 
   695                   [("left_total",     left_total     ),
   715                   [("left_total",     [left_total],      @{attributes [transfer_rule]}),
   696                    ("bi_total",       bi_total       ),
   716                    ("bi_total",       [bi_total],        @{attributes [transfer_rule]}),
   697                    ("id_abs_transfer",id_abs_transfer)]              
   717                    ("id_abs_transfer",[id_abs_transfer], @{attributes [transfer_rule]})]              
   698               in
   718               in
   699                 lthy
   719                 map_thms qualify I thms @ map_thms qualify I domain_thms
   700                 |> fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
       
   701                      [thm])) thms
       
   702                 |> fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_domain_attr]), 
       
   703                      [thm])) domain_thms
       
   704               end
   720               end
   705             | NONE =>
   721             | NONE =>
   706               let
   722               let
   707                 val thms = parametrize_domain dom_thm pcrel_info lthy
   723                 val thms = parametrize_domain dom_thm pcrel_info lthy
   708               in
   724               in
   709                 fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_domain_attr]), 
   725                 map_thms qualify I thms
   710                   [thm])) thms lthy
       
   711               end
   726               end
   712               
   727               
   713         val thms = 
   728         val notes2 = map_thms qualify (fn thm => generate_parametric_id lthy rty 
   714           ("rep_transfer", generate_parametric_id lthy rty 
   729             (Lifting_Term.parametrize_transfer_rule lthy ([typedef_thm, T_def] MRSL thm)))
   715             (Lifting_Term.parametrize_transfer_rule lthy ([typedef_thm, T_def] MRSL @{thm typedef_rep_transfer})))
   730           [("rep_transfer", @{thms typedef_rep_transfer}, @{attributes [transfer_rule]})];
   716           ::
   731         val notes3 =
   717           (map_snd (fn thm => parametrize_class_constraint lthy pcrel_def ([typedef_thm, T_def] MRSL thm))
   732           map_thms qualify
   718           [("left_unique",  @{thm typedef_left_unique} ),
   733           (fn thm => parametrize_class_constraint lthy pcrel_def ([typedef_thm, T_def] MRSL thm))
   719            ("right_unique", @{thm typedef_right_unique}),
   734           [("left_unique",  @{thms typedef_left_unique}, @{attributes [transfer_rule]}),
   720            ("bi_unique",    @{thm typedef_bi_unique} ),
   735            ("right_unique", @{thms typedef_right_unique},@{attributes [transfer_rule]}),
   721            ("right_total",  @{thm typedef_right_total} )])
   736            ("bi_unique",    @{thms typedef_bi_unique},   @{attributes [transfer_rule]}),
   722       in
   737            ("right_total",  @{thms typedef_right_total}, @{attributes [transfer_rule]})]
   723         fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   738       in
   724           [thm])) thms lthy
   739         notes3 @ notes2 @ notes1 @ notes
   725       end
   740       end
   726 
   741 
   727     fun setup_transfer_rules lthy = 
   742     val notes1 = [(Binding.prefix_name "Quotient_" qty_name, [quot_thm], [])]
   728       if is_some (get_pcrel_info lthy qty_full_name) then setup_transfer_rules_par lthy
   743 
   729                                                      else setup_transfer_rules_nonpar lthy
   744     fun setup_rules lthy = 
   730 
   745       let
       
   746         val thms =  if is_some (get_pcrel_info lthy qty_full_name) 
       
   747           then setup_transfer_rules_par lthy notes1 else setup_transfer_rules_nonpar notes1
       
   748       in
       
   749         notes (#notes config) thms lthy
       
   750       end
   731   in
   751   in
   732     lthy
   752     lthy
   733       |> (snd oo Local_Theory.note) ((Binding.prefix_name "Quotient_" qty_name, []), 
   753       |> setup_lifting_infr config quot_thm opt_reflp_thm
   734             [quot_thm])
   754       ||> setup_rules
   735       |> setup_lifting_infr quot_thm opt_reflp_thm
       
   736       |> setup_transfer_rules
       
   737   end
   755   end
   738 
   756 
   739 fun setup_lifting_cmd xthm opt_reflp_xthm opt_par_xthm lthy =
   757 fun setup_lifting_cmd xthm opt_reflp_xthm opt_par_xthm lthy =
   740   let 
   758   let 
   741     val input_thm = singleton (Attrib.eval_thms lthy) xthm
   759     val input_thm = singleton (Attrib.eval_thms lthy) xthm
   753       end
   771       end
   754       
   772       
   755     fun check_qty qty = if not (is_Type qty) 
   773     fun check_qty qty = if not (is_Type qty) 
   756           then error "The abstract type must be a type constructor."
   774           then error "The abstract type must be a type constructor."
   757           else ()
   775           else ()
   758 
   776     val config = { notes = true }       
       
   777    
   759     fun setup_quotient () = 
   778     fun setup_quotient () = 
   760       let
   779       let
   761         val opt_reflp_thm = Option.map (singleton (Attrib.eval_thms lthy)) opt_reflp_xthm
   780         val opt_reflp_thm = Option.map (singleton (Attrib.eval_thms lthy)) opt_reflp_xthm
   762         val _ = if is_some opt_reflp_thm then sanity_check_reflp_thm (the opt_reflp_thm) else ()
   781         val _ = if is_some opt_reflp_thm then sanity_check_reflp_thm (the opt_reflp_thm) else ()
   763         val opt_par_thm = Option.map (singleton (Attrib.eval_thms lthy)) opt_par_xthm
   782         val opt_par_thm = Option.map (singleton (Attrib.eval_thms lthy)) opt_par_xthm
   764         val _ = check_qty (snd (quot_thm_rty_qty input_thm))
   783         val _ = check_qty (snd (quot_thm_rty_qty input_thm))
   765       in
   784       in
   766         setup_by_quotient input_thm opt_reflp_thm opt_par_thm lthy
   785         setup_by_quotient config input_thm opt_reflp_thm opt_par_thm lthy |> snd
   767       end
   786       end
   768 
   787 
   769     fun setup_typedef () = 
   788     fun setup_typedef () = 
   770       let
   789       let
   771         val qty = (range_type o fastype_of o hd o get_args 2) input_term
   790         val qty = (range_type o fastype_of o hd o get_args 2) input_term
   774         case opt_reflp_xthm of
   793         case opt_reflp_xthm of
   775           SOME _ => error "The reflexivity theorem cannot be specified if the type_definition theorem is used."
   794           SOME _ => error "The reflexivity theorem cannot be specified if the type_definition theorem is used."
   776           | NONE => (
   795           | NONE => (
   777             case opt_par_xthm of
   796             case opt_par_xthm of
   778               SOME _ => error "The parametricity theorem cannot be specified if the type_definition theorem is used."
   797               SOME _ => error "The parametricity theorem cannot be specified if the type_definition theorem is used."
   779               | NONE => setup_by_typedef_thm input_thm lthy
   798               | NONE => setup_by_typedef_thm config input_thm lthy |> snd
   780           )
   799           )
   781       end
   800       end
   782   in
   801   in
   783     case input_term of
   802     case input_term of
   784       (Const (@{const_name Quotient}, _) $ _ $ _ $ _ $ _) => setup_quotient ()
   803       (Const (@{const_name Quotient}, _) $ _ $ _ $ _ $ _) => setup_quotient ()