src/HOL/Tools/Function/partial_function.ML
changeset 61113 86049d52155c
parent 60784 4f590c08fd5d
child 61121 efe8b18306b7
equal deleted inserted replaced
61112:e966c311e9a7 61113:86049d52155c
     5 *)
     5 *)
     6 
     6 
     7 signature PARTIAL_FUNCTION =
     7 signature PARTIAL_FUNCTION =
     8 sig
     8 sig
     9   val init: string -> term -> term -> thm -> thm -> thm option -> declaration
     9   val init: string -> term -> term -> thm -> thm -> thm option -> declaration
    10 
       
    11   val mono_tac: Proof.context -> int -> tactic
    10   val mono_tac: Proof.context -> int -> tactic
    12 
       
    13   val add_partial_function: string -> (binding * typ option * mixfix) list ->
    11   val add_partial_function: string -> (binding * typ option * mixfix) list ->
    14     Attrib.binding * term -> local_theory -> local_theory
    12     Attrib.binding * term -> local_theory -> local_theory
    15 
       
    16   val add_partial_function_cmd: string -> (binding * string option * mixfix) list ->
    13   val add_partial_function_cmd: string -> (binding * string option * mixfix) list ->
    17     Attrib.binding * string -> local_theory -> local_theory
    14     Attrib.binding * string -> local_theory -> local_theory
    18 end;
    15 end;
    19 
    16 
    20 
       
    21 structure Partial_Function: PARTIAL_FUNCTION =
    17 structure Partial_Function: PARTIAL_FUNCTION =
    22 struct
    18 struct
    23 
    19 
    24 (*** Context Data ***)
    20 (*** Context Data ***)
    25 
    21 
    26 datatype setup_data = Setup_Data of 
    22 datatype setup_data = Setup_Data of
    27  {fixp: term,
    23  {fixp: term,
    28   mono: term,
    24   mono: term,
    29   fixp_eq: thm,
    25   fixp_eq: thm,
    30   fixp_induct: thm,
    26   fixp_induct: thm,
    31   fixp_induct_user: thm option};
    27   fixp_induct_user: thm option};
       
    28 
       
    29 fun transform_setup_data phi (Setup_Data {fixp, mono, fixp_eq, fixp_induct, fixp_induct_user}) =
       
    30   let
       
    31     val term = Morphism.term phi;
       
    32     val thm = Morphism.thm phi;
       
    33   in
       
    34     Setup_Data
       
    35      {fixp = term fixp, mono = term mono, fixp_eq = thm fixp_eq,
       
    36       fixp_induct = thm fixp_induct, fixp_induct_user = Option.map thm fixp_induct_user}
       
    37   end;
    32 
    38 
    33 structure Modes = Generic_Data
    39 structure Modes = Generic_Data
    34 (
    40 (
    35   type T = setup_data Symtab.table;
    41   type T = setup_data Symtab.table;
    36   val empty = Symtab.empty;
    42   val empty = Symtab.empty;
    38   fun merge data = Symtab.merge (K true) data;
    44   fun merge data = Symtab.merge (K true) data;
    39 )
    45 )
    40 
    46 
    41 fun init mode fixp mono fixp_eq fixp_induct fixp_induct_user phi =
    47 fun init mode fixp mono fixp_eq fixp_induct fixp_induct_user phi =
    42   let
    48   let
    43     val term = Morphism.term phi;
    49     val data' =
    44     val thm = Morphism.thm phi;
    50       Setup_Data
    45     val data' = Setup_Data 
    51        {fixp = fixp, mono = mono, fixp_eq = fixp_eq,
    46       {fixp=term fixp, mono=term mono, fixp_eq=thm fixp_eq,
    52         fixp_induct = fixp_induct, fixp_induct_user = fixp_induct_user}
    47        fixp_induct=thm fixp_induct, fixp_induct_user=Option.map thm fixp_induct_user};
    53       |> transform_setup_data (phi $> Morphism.trim_context_morphism);
    48   in
    54   in Modes.map (Symtab.update (mode, data')) end;
    49     Modes.map (Symtab.update (mode, data'))
       
    50   end
       
    51 
    55 
    52 val known_modes = Symtab.keys o Modes.get o Context.Proof;
    56 val known_modes = Symtab.keys o Modes.get o Context.Proof;
    53 val lookup_mode = Symtab.lookup o Modes.get o Context.Proof;
    57 
       
    58 fun lookup_mode ctxt =
       
    59   Symtab.lookup (Modes.get (Context.Proof ctxt))
       
    60   #> Option.map (transform_setup_data (Morphism.transfer_morphism (Proof_Context.theory_of ctxt)));
    54 
    61 
    55 
    62 
    56 (*** Automated monotonicity proofs ***)
    63 (*** Automated monotonicity proofs ***)
    57 
    64 
    58 fun strip_cases ctac = ctac #> Seq.map snd;
    65 fun strip_cases ctac = ctac #> Seq.map snd;
   157   curry induction predicate *)
   164   curry induction predicate *)
   158 fun specialize_fixp_induct ctxt args fT fT_uc F curry uncurry mono_thm f_def rule =
   165 fun specialize_fixp_induct ctxt args fT fT_uc F curry uncurry mono_thm f_def rule =
   159   let
   166   let
   160     val ([P], ctxt') = Variable.variant_fixes ["P"] ctxt
   167     val ([P], ctxt') = Variable.variant_fixes ["P"] ctxt
   161     val P_inst = Abs ("f", fT_uc, Free (P, fT --> HOLogic.boolT) $ (curry $ Bound 0))
   168     val P_inst = Abs ("f", fT_uc, Free (P, fT --> HOLogic.boolT) $ (curry $ Bound 0))
   162   in 
   169   in
   163     (* FIXME ctxt vs. ctxt' (!?) *)
   170     (* FIXME ctxt vs. ctxt' (!?) *)
   164     rule
   171     rule
   165     |> infer_instantiate' ctxt
   172     |> infer_instantiate' ctxt
   166       ((map o Option.map) (Thm.cterm_of ctxt) [SOME uncurry, NONE, SOME curry, NONE, SOME P_inst])
   173       ((map o Option.map) (Thm.cterm_of ctxt) [SOME uncurry, NONE, SOME curry, NONE, SOME P_inst])
   167     |> Tactic.rule_by_tactic ctxt
   174     |> Tactic.rule_by_tactic ctxt
   180     val ([P], ctxt') = Variable.variant_fixes ["P"] ctxt
   187     val ([P], ctxt') = Variable.variant_fixes ["P"] ctxt
   181 
   188 
   182     val split_paired_all_conv =
   189     val split_paired_all_conv =
   183       Conv.every_conv (replicate (length args - 1) (Conv.rewr_conv @{thm split_paired_all}))
   190       Conv.every_conv (replicate (length args - 1) (Conv.rewr_conv @{thm split_paired_all}))
   184 
   191 
   185     val split_params_conv = 
   192     val split_params_conv =
   186       Conv.params_conv ~1 (fn ctxt' =>
   193       Conv.params_conv ~1 (fn ctxt' =>
   187         Conv.implies_conv split_paired_all_conv Conv.all_conv)
   194         Conv.implies_conv split_paired_all_conv Conv.all_conv)
   188 
   195 
   189     val (P_var, x_var) =
   196     val (P_var, x_var) =
   190        Thm.prop_of inst_rule |> Logic.strip_imp_concl |> HOLogic.dest_Trueprop
   197        Thm.prop_of inst_rule |> Logic.strip_imp_concl |> HOLogic.dest_Trueprop
   205       |> Simplifier.full_simplify (put_simpset split_conv_ss ctxt)
   212       |> Simplifier.full_simplify (put_simpset split_conv_ss ctxt)
   206       |> singleton (Variable.export ctxt' ctxt)
   213       |> singleton (Variable.export ctxt' ctxt)
   207   in
   214   in
   208     inst_rule'
   215     inst_rule'
   209   end;
   216   end;
   210     
   217 
   211 
   218 
   212 (*** partial_function definition ***)
   219 (*** partial_function definition ***)
   213 
   220 
   214 fun gen_add_partial_function prep mode fixes_raw eqn_raw lthy =
   221 fun gen_add_partial_function prep mode fixes_raw eqn_raw lthy =
   215   let
   222   let
   262     val unfold =
   269     val unfold =
   263       (infer_instantiate' lthy' (map (SOME o Thm.cterm_of lthy') [uncurry, F, curry]) fixp_eq
   270       (infer_instantiate' lthy' (map (SOME o Thm.cterm_of lthy') [uncurry, F, curry]) fixp_eq
   264         OF [inst_mono_thm, f_def])
   271         OF [inst_mono_thm, f_def])
   265       |> Tactic.rule_by_tactic lthy' (Simplifier.simp_tac (put_simpset curry_uncurry_ss lthy') 1);
   272       |> Tactic.rule_by_tactic lthy' (Simplifier.simp_tac (put_simpset curry_uncurry_ss lthy') 1);
   266 
   273 
   267     val specialized_fixp_induct = 
   274     val specialized_fixp_induct =
   268       specialize_fixp_induct lthy' args fT fT_uc F curry uncurry inst_mono_thm f_def fixp_induct
   275       specialize_fixp_induct lthy' args fT fT_uc F curry uncurry inst_mono_thm f_def fixp_induct
   269       |> Drule.rename_bvars' (map SOME (fname :: fname :: argnames));
   276       |> Drule.rename_bvars' (map SOME (fname :: fname :: argnames));
   270 
   277 
   271     val mk_raw_induct =
   278     val mk_raw_induct =
   272       infer_instantiate' args_ctxt
   279       infer_instantiate' args_ctxt
   286     lthy'
   293     lthy'
   287     |> Local_Theory.note (eq_abinding, [rec_rule])
   294     |> Local_Theory.note (eq_abinding, [rec_rule])
   288     |-> (fn (_, rec') =>
   295     |-> (fn (_, rec') =>
   289       Spec_Rules.add Spec_Rules.Equational ([f], rec')
   296       Spec_Rules.add Spec_Rules.Equational ([f], rec')
   290       #> Local_Theory.note ((Binding.qualify true fname (Binding.name "simps"), []), rec') #> snd)
   297       #> Local_Theory.note ((Binding.qualify true fname (Binding.name "simps"), []), rec') #> snd)
   291     |> (Local_Theory.note ((Binding.qualify true fname (Binding.name "mono"), []), [mono_thm]) #> snd) 
   298     |> (Local_Theory.note ((Binding.qualify true fname (Binding.name "mono"), []), [mono_thm]) #> snd)
   292     |> (case raw_induct of NONE => I | SOME thm =>
   299     |> (case raw_induct of NONE => I | SOME thm =>
   293          Local_Theory.note ((Binding.qualify true fname (Binding.name "raw_induct"), []), [thm]) #> snd)
   300          Local_Theory.note ((Binding.qualify true fname (Binding.name "raw_induct"), []), [thm]) #> snd)
   294     |> (Local_Theory.note ((Binding.qualify true fname (Binding.name "fixp_induct"), []), [specialized_fixp_induct]) #> snd) 
   301     |> (Local_Theory.note ((Binding.qualify true fname (Binding.name "fixp_induct"), []), [specialized_fixp_induct]) #> snd)
   295   end;
   302   end;
   296 
   303 
   297 val add_partial_function = gen_add_partial_function Specification.check_spec;
   304 val add_partial_function = gen_add_partial_function Specification.check_spec;
   298 val add_partial_function_cmd = gen_add_partial_function Specification.read_spec;
   305 val add_partial_function_cmd = gen_add_partial_function Specification.read_spec;
   299 
   306 
   302 val _ =
   309 val _ =
   303   Outer_Syntax.local_theory @{command_keyword partial_function} "define partial function"
   310   Outer_Syntax.local_theory @{command_keyword partial_function} "define partial function"
   304     ((mode -- (Parse.fixes -- (Parse.where_ |-- Parse_Spec.spec)))
   311     ((mode -- (Parse.fixes -- (Parse.where_ |-- Parse_Spec.spec)))
   305       >> (fn (mode, (fixes, spec)) => add_partial_function_cmd mode fixes spec));
   312       >> (fn (mode, (fixes, spec)) => add_partial_function_cmd mode fixes spec));
   306 
   313 
   307 end
   314 end;