src/HOL/Tools/Transfer/transfer_bnf.ML
changeset 57866 f4ba736040fa
child 57880 7c3b6b799b94
equal deleted inserted replaced
57865:2ae16e3d8b6d 57866:f4ba736040fa
       
     1 (*  Title:      HOL/Tools/Transfer/transfer_bnf.ML
       
     2     Author:     Ondrej Kuncar, TU Muenchen
       
     3 
       
     4 Setup for Transfer for types that are BNF.
       
     5 *)
       
     6 
       
     7 signature TRANSFER_BNF =
       
     8 sig
       
     9   val base_name_of_bnf: BNF_Def.bnf -> binding
       
    10   val type_name_of_bnf: BNF_Def.bnf -> string
       
    11   val lookup_defined_pred_data: Proof.context -> string -> Transfer.pred_data
       
    12   val map_local_theory: (local_theory -> local_theory) -> theory -> theory
       
    13   val bnf_only_type_ctr: (BNF_Def.bnf -> 'a -> 'a) -> BNF_Def.bnf -> 'a -> 'a
       
    14 end
       
    15 
       
    16 structure Transfer_BNF : TRANSFER_BNF =
       
    17 struct
       
    18 
       
    19 open BNF_Util
       
    20 open BNF_Def
       
    21 open BNF_FP_Def_Sugar
       
    22 
       
    23 (* util functions *)
       
    24 
       
    25 fun base_name_of_bnf bnf = Binding.name (Binding.name_of (name_of_bnf bnf))
       
    26 fun mk_Frees_free x Ts ctxt = Variable.variant_frees ctxt [] (mk_names (length Ts) x ~~ Ts) |> map Free
       
    27 
       
    28 fun mk_Domainp P =
       
    29   let
       
    30     val PT = fastype_of P
       
    31     val argT = hd (binder_types PT)
       
    32   in
       
    33     Const (@{const_name Domainp}, PT --> argT --> HOLogic.boolT) $ P
       
    34   end
       
    35 
       
    36 fun mk_pred pred_def args T =
       
    37   let
       
    38     val pred_name = pred_def |> prop_of |> HOLogic.dest_Trueprop |> fst o HOLogic.dest_eq 
       
    39       |> head_of |> fst o dest_Const
       
    40     val argsT = map fastype_of args
       
    41   in
       
    42     list_comb (Const (pred_name, argsT ---> (T --> HOLogic.boolT)), args)
       
    43   end
       
    44 
       
    45 fun mk_eq_onp arg = 
       
    46   let
       
    47     val argT = domain_type (fastype_of arg)
       
    48   in
       
    49     Const (@{const_name eq_onp}, (argT --> HOLogic.boolT) --> argT --> argT --> HOLogic.boolT)
       
    50       $ arg
       
    51   end
       
    52 
       
    53 fun subst_conv thm =
       
    54   Conv.top_sweep_conv (K (Conv.rewr_conv (safe_mk_meta_eq thm))) @{context}
       
    55 
       
    56 fun type_name_of_bnf bnf = T_of_bnf bnf |> dest_Type |> fst
       
    57 
       
    58 fun is_Type (Type _) = true
       
    59   | is_Type _ = false
       
    60 
       
    61 fun map_local_theory f = Named_Target.theory_init #> f #> Local_Theory.exit_global
       
    62 
       
    63 fun bnf_only_type_ctr f bnf = if is_Type (T_of_bnf bnf) then f bnf else I
       
    64 
       
    65 fun bnf_of_fp_sugar (fp_sugar:fp_sugar) = nth (#bnfs (#fp_res fp_sugar)) (#fp_res_index fp_sugar)
       
    66 
       
    67 fun fp_sugar_only_type_ctr f fp_sugar = 
       
    68   if is_Type (T_of_bnf (bnf_of_fp_sugar fp_sugar)) then f fp_sugar else I
       
    69 
       
    70 (* relation constraints - bi_total & co. *)
       
    71 
       
    72 fun mk_relation_constraint name arg =
       
    73   (Const (name, fastype_of arg --> HOLogic.boolT)) $ arg
       
    74 
       
    75 fun side_constraint_tac bnf constr_defs ctxt i = 
       
    76   let
       
    77     val thms = constr_defs @ map mk_sym [rel_eq_of_bnf bnf, rel_conversep_of_bnf bnf,
       
    78       rel_OO_of_bnf bnf]
       
    79   in                
       
    80     (SELECT_GOAL (Local_Defs.unfold_tac ctxt thms) THEN' rtac (rel_mono_of_bnf bnf)
       
    81       THEN_ALL_NEW atac) i
       
    82   end
       
    83 
       
    84 fun bi_constraint_tac constr_iff sided_constr_intros ctxt i = 
       
    85   (SELECT_GOAL (Local_Defs.unfold_tac ctxt [constr_iff]) THEN' 
       
    86     CONJ_WRAP' (fn thm => rtac thm THEN_ALL_NEW (REPEAT_DETERM o etac conjE THEN' atac)) sided_constr_intros) i
       
    87 
       
    88 fun generate_relation_constraint_goal ctxt bnf constraint_def =
       
    89   let
       
    90     val constr_name = constraint_def |> prop_of |> HOLogic.dest_Trueprop |> fst o HOLogic.dest_eq
       
    91       |> head_of |> fst o dest_Const
       
    92     val live = live_of_bnf bnf
       
    93     val (((As, Bs), Ds), ctxt) = ctxt
       
    94       |> mk_TFrees live
       
    95       ||>> mk_TFrees live
       
    96       ||>> mk_TFrees (dead_of_bnf bnf)
       
    97       
       
    98     val relator = mk_rel_of_bnf Ds As Bs bnf
       
    99     val relsT = map2 mk_pred2T As Bs
       
   100     val (args, ctxt) = Ctr_Sugar_Util.mk_Frees "R" relsT ctxt
       
   101     val concl = HOLogic.mk_Trueprop (mk_relation_constraint constr_name (list_comb (relator, args)))
       
   102     val assms = map (HOLogic.mk_Trueprop o (mk_relation_constraint constr_name)) args
       
   103     val goal = Logic.list_implies (assms, concl)
       
   104   in
       
   105     (goal, ctxt)
       
   106   end
       
   107 
       
   108 fun prove_relation_side_constraint ctxt bnf constraint_def =
       
   109   let
       
   110     val old_ctxt = ctxt
       
   111     val (goal, ctxt) = generate_relation_constraint_goal ctxt bnf constraint_def
       
   112     val thm = Goal.prove ctxt [] [] goal 
       
   113       (fn {context = ctxt, prems = _} => side_constraint_tac bnf [constraint_def] ctxt 1)
       
   114   in
       
   115     Drule.zero_var_indexes (singleton (Variable.export ctxt old_ctxt) thm)
       
   116   end
       
   117 
       
   118 fun prove_relation_bi_constraint ctxt bnf constraint_def side_constraints =
       
   119   let
       
   120     val old_ctxt = ctxt
       
   121     val (goal, ctxt) = generate_relation_constraint_goal ctxt bnf constraint_def
       
   122     val thm = Goal.prove ctxt [] [] goal 
       
   123       (fn {context = ctxt, prems = _} => bi_constraint_tac constraint_def side_constraints ctxt 1)
       
   124   in
       
   125     Drule.zero_var_indexes (singleton (Variable.export ctxt old_ctxt) thm)
       
   126   end
       
   127 
       
   128 val defs = [("left_total_rel", @{thm left_total_alt_def}), ("right_total_rel", @{thm right_total_alt_def}),
       
   129   ("left_unique_rel", @{thm left_unique_alt_def}), ("right_unique_rel", @{thm right_unique_alt_def})]
       
   130 
       
   131 fun prove_relation_constraints bnf lthy =
       
   132   let
       
   133     val transfer_attr = @{attributes [transfer_rule]}
       
   134     val Tname = base_name_of_bnf bnf
       
   135     fun qualify suffix = Binding.qualified true suffix Tname
       
   136     
       
   137     val defs = map (apsnd (prove_relation_side_constraint lthy bnf)) defs
       
   138     val bi_total = prove_relation_bi_constraint lthy bnf @{thm bi_total_alt_def} 
       
   139       [snd (nth defs 0), snd (nth defs 1)]
       
   140     val bi_unique = prove_relation_bi_constraint lthy bnf @{thm bi_unique_alt_def} 
       
   141       [snd (nth defs 2), snd (nth defs 3)]
       
   142     val defs = ("bi_total_rel", bi_total) :: ("bi_unique_rel", bi_unique) :: defs
       
   143     val notes = maps (fn (name, thm) => [((qualify name, []), [([thm], transfer_attr)])]) defs
       
   144   in
       
   145     notes
       
   146   end
       
   147 
       
   148 (* relator_eq *)
       
   149 
       
   150 fun relator_eq bnf =
       
   151   [((Binding.empty, []), [([rel_eq_of_bnf bnf], @{attributes [relator_eq]})])]
       
   152 
       
   153 (* predicator definition and Domainp and eq_onp theorem *)
       
   154 
       
   155 fun define_pred bnf lthy =
       
   156   let
       
   157     fun mk_pred_name c = Binding.prefix_name "pred_" c
       
   158     val live = live_of_bnf bnf
       
   159     val Tname = base_name_of_bnf bnf
       
   160     val ((As, Ds), lthy) = lthy
       
   161       |> mk_TFrees live
       
   162       ||>> mk_TFrees (dead_of_bnf bnf)
       
   163     val T = mk_T_of_bnf Ds As bnf
       
   164     val sets = mk_sets_of_bnf (replicate live Ds) (replicate live As) bnf
       
   165     val argTs = map mk_pred1T As
       
   166     val args = mk_Frees_free "P" argTs lthy
       
   167     val conjs = map (fn (set, arg) => mk_Ball (set $ Bound 0) arg) (sets ~~ args)
       
   168     val rhs = Abs ("x", T, foldr1 HOLogic.mk_conj conjs)
       
   169     val pred_name = mk_pred_name Tname
       
   170     val headT = argTs ---> (T --> HOLogic.boolT)
       
   171     val head = Free (Binding.name_of pred_name, headT)
       
   172     val lhs = list_comb (head, args)
       
   173     val def = HOLogic.mk_Trueprop (HOLogic.mk_eq (lhs, rhs))
       
   174     val ((_, (_, pred_def)), lthy) = Specification.definition ((SOME (pred_name, SOME headT, NoSyn)), 
       
   175       ((Binding.empty, []), def)) lthy
       
   176   in
       
   177     (pred_def, lthy)
       
   178   end
       
   179 
       
   180 fun Domainp_tac bnf pred_def ctxt i =
       
   181   let
       
   182     val n = live_of_bnf bnf
       
   183     val set_map's = set_map_of_bnf bnf
       
   184   in
       
   185     EVERY' [rtac ext, SELECT_GOAL (Local_Defs.unfold_tac ctxt [@{thm Domainp.simps}, 
       
   186         in_rel_of_bnf bnf, pred_def]), rtac iffI,
       
   187         REPEAT_DETERM o eresolve_tac [exE, conjE, CollectE], hyp_subst_tac ctxt,
       
   188         CONJ_WRAP' (fn set_map => EVERY' [rtac ballI, dtac (set_map RS equalityD1 RS set_mp),
       
   189           etac imageE, dtac set_rev_mp, atac, REPEAT_DETERM o eresolve_tac [CollectE, @{thm case_prodE}],
       
   190           hyp_subst_tac ctxt, rtac @{thm iffD2[OF arg_cong2[of _ _ _ _ Domainp, OF refl fst_conv]]},
       
   191           etac @{thm DomainPI}]) set_map's, 
       
   192         REPEAT_DETERM o etac conjE, REPEAT_DETERM o resolve_tac [exI, (refl RS conjI), rotate_prems 1 conjI], 
       
   193         rtac refl, rtac (box_equals OF [map_cong0_of_bnf bnf, map_comp_of_bnf bnf RS sym,
       
   194           map_id_of_bnf bnf]),
       
   195         REPEAT_DETERM_N n o (EVERY' [rtac @{thm box_equals[OF _ sym[OF o_apply] sym[OF id_apply]]},
       
   196           rtac @{thm fst_conv}]), rtac CollectI,
       
   197         CONJ_WRAP' (fn set_map => EVERY' [rtac (set_map RS @{thm ord_eq_le_trans}), 
       
   198           REPEAT_DETERM o resolve_tac [@{thm image_subsetI}, CollectI, @{thm case_prodI}],
       
   199           dtac (rotate_prems 1 bspec), atac, etac @{thm DomainpE}, etac @{thm someI}]) set_map's
       
   200       ] i
       
   201   end
       
   202 
       
   203 fun prove_Domainp_rel ctxt bnf pred_def =
       
   204   let
       
   205     val live = live_of_bnf bnf
       
   206     val old_ctxt = ctxt
       
   207     val (((As, Bs), Ds), ctxt) = ctxt
       
   208       |> mk_TFrees live
       
   209       ||>> mk_TFrees live
       
   210       ||>> mk_TFrees (dead_of_bnf bnf)
       
   211 
       
   212     val relator = mk_rel_of_bnf Ds As Bs bnf
       
   213     val relsT = map2 mk_pred2T As Bs
       
   214     val T = mk_T_of_bnf Ds As bnf
       
   215     val (args, ctxt) = Ctr_Sugar_Util.mk_Frees "R" relsT ctxt
       
   216     val lhs = mk_Domainp (list_comb (relator, args))
       
   217     val rhs = mk_pred pred_def (map mk_Domainp args) T
       
   218     val goal = HOLogic.mk_eq (lhs, rhs) |> HOLogic.mk_Trueprop
       
   219     val thm = Goal.prove ctxt [] [] goal 
       
   220       (fn {context = ctxt, prems = _} => Domainp_tac bnf pred_def ctxt 1)
       
   221   in
       
   222     Drule.zero_var_indexes (singleton (Variable.export ctxt old_ctxt) thm)
       
   223   end
       
   224 
       
   225 fun pred_eq_onp_tac bnf pred_def ctxt i =
       
   226   (SELECT_GOAL (Local_Defs.unfold_tac ctxt [@{thm eq_onp_Grp}, 
       
   227     @{thm Ball_Collect}, pred_def]) THEN' CONVERSION (subst_conv (map_id0_of_bnf bnf RS sym))
       
   228   THEN' rtac (rel_Grp_of_bnf bnf)) i
       
   229 
       
   230 fun prove_rel_eq_onp ctxt bnf pred_def =
       
   231   let
       
   232     val live = live_of_bnf bnf
       
   233     val old_ctxt = ctxt
       
   234     val ((As, Ds), ctxt) = ctxt
       
   235       |> mk_TFrees live
       
   236       ||>> mk_TFrees (dead_of_bnf bnf)
       
   237     val T = mk_T_of_bnf Ds As bnf
       
   238     val argTs = map mk_pred1T As
       
   239     val (args, ctxt) = mk_Frees "P" argTs ctxt
       
   240     val relator = mk_rel_of_bnf Ds As As bnf
       
   241     val lhs = list_comb (relator, map mk_eq_onp args)
       
   242     val rhs = mk_eq_onp (mk_pred pred_def args T)
       
   243     val goal = HOLogic.mk_eq (lhs, rhs) |> HOLogic.mk_Trueprop
       
   244     val thm = Goal.prove ctxt [] [] goal 
       
   245       (fn {context = ctxt, prems = _} => pred_eq_onp_tac bnf pred_def ctxt 1)
       
   246   in
       
   247     Drule.zero_var_indexes (singleton (Variable.export ctxt old_ctxt) thm)
       
   248   end
       
   249 
       
   250 fun predicator bnf lthy =
       
   251   let
       
   252     val (pred_def, lthy) = define_pred bnf lthy
       
   253     val pred_def = Morphism.thm (Local_Theory.target_morphism lthy) pred_def
       
   254     val Domainp_rel = prove_Domainp_rel lthy bnf pred_def
       
   255     val rel_eq_onp = prove_rel_eq_onp lthy bnf pred_def
       
   256     fun qualify defname suffix = Binding.qualified true suffix defname
       
   257     val Domainp_rel_thm_name = qualify (base_name_of_bnf bnf) "Domainp_rel"
       
   258     val rel_eq_onp_thm_name = qualify (base_name_of_bnf bnf) "rel_eq_onp"
       
   259     val pred_data = {rel_eq_onp = rel_eq_onp}
       
   260     val type_name = type_name_of_bnf bnf
       
   261     val relator_domain_attr = @{attributes [relator_domain]}
       
   262     val notes = [((Domainp_rel_thm_name, []), [([Domainp_rel], relator_domain_attr)]),
       
   263       ((rel_eq_onp_thm_name, []), [([rel_eq_onp], [])])]
       
   264     val lthy = Local_Theory.declaration {syntax = false, pervasive = true}
       
   265       (fn phi => Transfer.update_pred_data type_name (Transfer.morph_pred_data phi pred_data)) lthy
       
   266   in
       
   267     (notes, lthy)
       
   268   end
       
   269 
       
   270 (* BNF interpretation *)
       
   271 
       
   272 fun transfer_bnf_interpretation bnf lthy =
       
   273   let
       
   274     val constr_notes = if dead_of_bnf bnf > 0 then []
       
   275       else prove_relation_constraints bnf lthy
       
   276     val relator_eq_notes = if dead_of_bnf bnf > 0 then [] 
       
   277       else relator_eq bnf
       
   278     val (pred_notes, lthy) = predicator bnf lthy
       
   279   in
       
   280     snd (Local_Theory.notes (constr_notes @ relator_eq_notes @ pred_notes) lthy)
       
   281   end
       
   282 
       
   283 val _ = Context.>> (Context.map_theory (bnf_interpretation
       
   284   (bnf_only_type_ctr (fn bnf => map_local_theory (transfer_bnf_interpretation bnf)))))
       
   285 
       
   286 (* simplification rules for the predicator *)
       
   287 
       
   288 fun lookup_defined_pred_data lthy name =
       
   289   case (Transfer.lookup_pred_data lthy name) of
       
   290     SOME data => data
       
   291     | NONE => (error "lookup_pred_data: something went utterly wrong")
       
   292 
       
   293 fun prove_pred_inject lthy (fp_sugar:fp_sugar) =
       
   294   let
       
   295     val involved_types = distinct op= (
       
   296         map type_name_of_bnf (#nested_bnfs fp_sugar) 
       
   297       @ map type_name_of_bnf (#nesting_bnfs fp_sugar)
       
   298       @ map type_name_of_bnf (#bnfs (#fp_res fp_sugar)))
       
   299     val eq_onps = map (Transfer.rel_eq_onp o lookup_defined_pred_data lthy) involved_types
       
   300     val live = live_of_bnf (bnf_of_fp_sugar fp_sugar)
       
   301     val old_lthy = lthy
       
   302     val (As, lthy) = mk_TFrees live lthy
       
   303     val predTs = map mk_pred1T As
       
   304     val (preds, lthy) = mk_Frees "P" predTs lthy
       
   305     val args = map mk_eq_onp preds
       
   306     val cTs = map (SOME o certifyT lthy) (maps (replicate 2) As)
       
   307     val cts = map (SOME o certify lthy) args
       
   308     fun get_rhs thm = thm |> concl_of |> HOLogic.dest_Trueprop |> HOLogic.dest_eq |> snd
       
   309     fun is_eqn thm = can get_rhs thm
       
   310     fun rel2pred_massage thm =
       
   311       let
       
   312         fun pred_eq_onp_conj 0 = error "not defined"
       
   313           | pred_eq_onp_conj 1 = @{thm eq_onp_same_args}
       
   314           | pred_eq_onp_conj n = 
       
   315             let
       
   316               val conj_cong = @{thm arg_cong2[of _ _ _ _ "op \<and>"]}
       
   317               val start = @{thm eq_onp_same_args} RS conj_cong
       
   318             in
       
   319               @{thm eq_onp_same_args} RS (funpow (n - 2) (fn thm => start RS thm) start)
       
   320             end
       
   321         val n = if is_eqn thm then thm |> get_rhs |> HOLogic.dest_conj |> length else 0
       
   322       in
       
   323         thm
       
   324         |> Drule.instantiate' cTs cts
       
   325         |> Local_Defs.unfold lthy eq_onps
       
   326         |> (fn thm => if n > 0 then @{thm box_equals} 
       
   327               OF [thm, @{thm eq_onp_same_args}, pred_eq_onp_conj n]
       
   328             else thm RS (@{thm eq_onp_same_args} RS iffD1))
       
   329       end
       
   330     val rel_injects = #rel_injects fp_sugar
       
   331   in
       
   332     rel_injects
       
   333     |> map rel2pred_massage
       
   334     |> Variable.export lthy old_lthy
       
   335     |> map Drule.zero_var_indexes
       
   336   end
       
   337 
       
   338 (* fp_sugar interpretation *)
       
   339 
       
   340 fun transfer_fp_sugar_interpretation fp_sugar lthy =
       
   341   let
       
   342     val pred_injects = prove_pred_inject lthy fp_sugar
       
   343     fun qualify defname suffix = Binding.qualified true suffix defname
       
   344     val pred_inject_thm_name = qualify (base_name_of_bnf (bnf_of_fp_sugar fp_sugar)) "pred_inject"
       
   345     val simp_attrs = @{attributes [simp]}
       
   346   in
       
   347     snd (Local_Theory.note ((pred_inject_thm_name, simp_attrs), pred_injects) lthy)
       
   348   end
       
   349 
       
   350 val _ = Context.>> (Context.map_theory (fp_sugar_interpretation
       
   351   (fp_sugar_only_type_ctr (fn fp_sugar => map_local_theory (transfer_fp_sugar_interpretation fp_sugar)))))
       
   352 
       
   353 end