generate raw induction rule as instance of generic rule with careful treatment of currying
authorkrauss
Tue, 31 May 2011 11:16:52 +0200
changeset 43083 df41a5762c3d
parent 43082 8d0c44de9773
child 43084 946c8e171ffd
generate raw induction rule as instance of generic rule with careful treatment of currying
src/HOL/Tools/Function/partial_function.ML
--- a/src/HOL/Tools/Function/partial_function.ML	Tue May 31 11:16:34 2011 +0200
+++ b/src/HOL/Tools/Function/partial_function.ML	Tue May 31 11:16:52 2011 +0200
@@ -160,6 +160,44 @@
 val curry_uncurry_ss = HOL_basic_ss addsimps
   [@{thm Product_Type.curry_split}, @{thm Product_Type.split_curry}]
 
+val split_conv_ss = HOL_basic_ss addsimps
+  [@{thm Product_Type.split_conv}];
+
+fun mk_curried_induct args ctxt ccurry cuncurry rule =
+  let
+    val cert = Thm.cterm_of (Proof_Context.theory_of ctxt)
+    val ([P], ctxt') = Variable.variant_fixes ["P"] ctxt
+
+    val split_paired_all_conv =
+      Conv.every_conv (replicate (length args - 1) (Conv.rewr_conv @{thm split_paired_all}))
+
+    val split_params_conv = 
+      Conv.params_conv ~1 (fn ctxt' =>
+        Conv.implies_conv split_paired_all_conv Conv.all_conv)
+
+    val inst_rule =
+      cterm_instantiate' [SOME cuncurry, NONE, SOME ccurry] rule
+
+    val plain_resultT = 
+      Thm.prop_of inst_rule |> Logic.strip_imp_concl |> HOLogic.dest_Trueprop
+      |> Term.head_of |> Term.dest_Var |> snd |> range_type |> domain_type
+    val PT = map (snd o dest_Free) args ---> plain_resultT --> HOLogic.boolT
+    val x_inst = cert (foldl1 HOLogic.mk_prod args)
+    val P_inst = cert (uncurry_n (length args) (Free (P, PT)))
+
+    val inst_rule' = inst_rule
+      |> Tactic.rule_by_tactic ctxt
+        (Simplifier.simp_tac curry_uncurry_ss 4
+         THEN Simplifier.simp_tac curry_uncurry_ss 3
+         THEN CONVERSION (split_params_conv ctxt
+           then_conv (Conv.forall_conv (K split_paired_all_conv) ctxt)) 3)
+      |> Drule.instantiate' [] [NONE, NONE, SOME P_inst, SOME x_inst]
+      |> Simplifier.full_simplify split_conv_ss
+      |> singleton (Variable.export ctxt' ctxt)
+  in
+    inst_rule'
+  end;
+    
 
 (*** partial_function definition ***)
 
@@ -171,7 +209,7 @@
     val Setup_Data {fixp, mono, fixp_eq, fixp_induct} = setup_data;
 
     val ((fixes, [(eq_abinding, eqn)]), _) = prep fixes_raw [eqn_raw] lthy;
-    val ((_, plain_eqn), _) = Variable.focus eqn lthy;
+    val ((_, plain_eqn), args_ctxt) = Variable.focus eqn lthy;
 
     val ((f_binding, fT), mixfix) = the_single fixes;
     val fname = Binding.name_of f_binding;
@@ -179,6 +217,7 @@
     val cert = cterm_of (Proof_Context.theory_of lthy);
     val (lhs, rhs) = HOLogic.dest_eq (HOLogic.dest_Trueprop plain_eqn);
     val (head, args) = strip_comb lhs;
+    val argnames = map (fst o dest_Free) args;
     val F = fold_rev lambda (head :: args) rhs;
 
     val arity = length args;
@@ -216,6 +255,13 @@
         OF [mono_thm, f_def])
       |> Tactic.rule_by_tactic lthy (Simplifier.simp_tac curry_uncurry_ss 1);
 
+    val mk_raw_induct =
+      mk_curried_induct args args_ctxt (cert curry) (cert uncurry)
+      #> singleton (Variable.export args_ctxt lthy)
+      #> (fn thm => Drule.instantiate' [] [SOME (cert F)] thm OF [mono_thm, f_def])
+      #> Drule.rename_bvars' (map SOME (fname :: argnames @ argnames))
+
+    val raw_induct = Option.map mk_raw_induct fixp_induct
     val rec_rule = let open Conv in
       Goal.prove lthy' (map (fst o dest_Free) args) [] eqn (fn _ =>
         CONVERSION ((arg_conv o arg1_conv o head_conv o rewr_conv) (mk_meta_eq unfold)) 1
@@ -226,6 +272,8 @@
     |-> (fn (_, rec') =>
       Spec_Rules.add Spec_Rules.Equational ([f], rec')
       #> Local_Theory.note ((Binding.qualify true fname (Binding.name "simps"), []), rec') #> snd)
+    |> (case raw_induct of NONE => I | SOME thm =>
+         Local_Theory.note ((Binding.qualify true fname (Binding.name "raw_induct"), []), [thm]) #> snd)
   end;
 
 val add_partial_function = gen_add_partial_function Specification.check_spec;