src/Tools/induct.ML
changeset 59940 087d81f5213e
parent 59936 b8ffc3dc9e24
child 59970 e9f73d87d904
equal deleted inserted replaced
59939:7d46aa03696e 59940:087d81f5213e
    86     thm list -> int -> cases_tactic
    86     thm list -> int -> cases_tactic
    87   val gen_induct_setup: binding ->
    87   val gen_induct_setup: binding ->
    88    (Proof.context -> bool -> (binding option * (term * bool)) option list list ->
    88    (Proof.context -> bool -> (binding option * (term * bool)) option list list ->
    89     (string * typ) list list -> term option list -> thm list option ->
    89     (string * typ) list list -> term option list -> thm list option ->
    90     thm list -> int -> cases_tactic) ->
    90     thm list -> int -> cases_tactic) ->
    91    theory -> theory
    91    local_theory -> local_theory
    92 end;
    92 end;
    93 
    93 
    94 functor Induct(Induct_Args: INDUCT_ARGS): INDUCT =
    94 functor Induct(Induct_Args: INDUCT_ARGS): INDUCT =
    95 struct
    95 struct
    96 
    96 
   361   Scan.lift Args.del >> K del;
   361   Scan.lift Args.del >> K del;
   362 
   362 
   363 in
   363 in
   364 
   364 
   365 val _ =
   365 val _ =
   366   Theory.setup
   366   Theory.local_setup
   367    (Attrib.setup @{binding cases} (attrib cases_type cases_pred cases_del)
   367    (Attrib.local_setup @{binding cases} (attrib cases_type cases_pred cases_del)
   368       "declaration of cases rule" #>
   368       "declaration of cases rule" #>
   369     Attrib.setup @{binding induct} (attrib induct_type induct_pred induct_del)
   369     Attrib.local_setup @{binding induct} (attrib induct_type induct_pred induct_del)
   370       "declaration of induction rule" #>
   370       "declaration of induction rule" #>
   371     Attrib.setup @{binding coinduct} (attrib coinduct_type coinduct_pred coinduct_del)
   371     Attrib.local_setup @{binding coinduct} (attrib coinduct_type coinduct_pred coinduct_del)
   372       "declaration of coinduction rule" #>
   372       "declaration of coinduction rule" #>
   373     Attrib.setup @{binding induct_simp} (Attrib.add_del induct_simp_add induct_simp_del)
   373     Attrib.local_setup @{binding induct_simp} (Attrib.add_del induct_simp_add induct_simp_del)
   374       "declaration of rules for simplifying induction or cases rules");
   374       "declaration of rules for simplifying induction or cases rules");
   375 
   375 
   376 end;
   376 end;
   377 
   377 
   378 
   378 
   735 
   735 
   736 fun gen_induct_tac mod_cases ctxt simp def_insts arbitrary taking opt_rule facts =
   736 fun gen_induct_tac mod_cases ctxt simp def_insts arbitrary taking opt_rule facts =
   737   SUBGOAL_CASES (fn (_, i, st) =>
   737   SUBGOAL_CASES (fn (_, i, st) =>
   738     let
   738     let
   739       val thy = Proof_Context.theory_of ctxt;
   739       val thy = Proof_Context.theory_of ctxt;
   740   
   740 
   741       val ((insts, defs), defs_ctxt) = fold_map add_defs def_insts ctxt |>> split_list;
   741       val ((insts, defs), defs_ctxt) = fold_map add_defs def_insts ctxt |>> split_list;
   742       val atomized_defs = map (map (Conv.fconv_rule (atomize_cterm defs_ctxt))) defs;
   742       val atomized_defs = map (map (Conv.fconv_rule (atomize_cterm defs_ctxt))) defs;
   743   
   743 
   744       fun inst_rule (concls, r) =
   744       fun inst_rule (concls, r) =
   745         (if null insts then `Rule_Cases.get r
   745         (if null insts then `Rule_Cases.get r
   746          else (align_left "Rule has fewer conclusions than arguments given"
   746          else (align_left "Rule has fewer conclusions than arguments given"
   747             (map Logic.strip_imp_concl (Logic.dest_conjunctions (Thm.concl_of r))) insts
   747             (map Logic.strip_imp_concl (Logic.dest_conjunctions (Thm.concl_of r))) insts
   748           |> maps (prep_inst ctxt align_right (atomize_term thy))
   748           |> maps (prep_inst ctxt align_right (atomize_term thy))
   749           |> Drule.cterm_instantiate) r |> pair (Rule_Cases.get r))
   749           |> Drule.cterm_instantiate) r |> pair (Rule_Cases.get r))
   750         |> mod_cases thy
   750         |> mod_cases thy
   751         |> (fn ((cases, consumes), th) => (((cases, concls), consumes), th));
   751         |> (fn ((cases, consumes), th) => (((cases, concls), consumes), th));
   752   
   752 
   753       val ruleq =
   753       val ruleq =
   754         (case opt_rule of
   754         (case opt_rule of
   755           SOME rs => Seq.single (inst_rule (Rule_Cases.strict_mutual_rule ctxt rs))
   755           SOME rs => Seq.single (inst_rule (Rule_Cases.strict_mutual_rule ctxt rs))
   756         | NONE =>
   756         | NONE =>
   757             (get_inductP ctxt facts @
   757             (get_inductP ctxt facts @
   758               map (special_rename_params defs_ctxt insts) (get_inductT ctxt insts))
   758               map (special_rename_params defs_ctxt insts) (get_inductT ctxt insts))
   759             |> map_filter (Rule_Cases.mutual_rule ctxt)
   759             |> map_filter (Rule_Cases.mutual_rule ctxt)
   760             |> tap (trace_rules ctxt inductN o map #2)
   760             |> tap (trace_rules ctxt inductN o map #2)
   761             |> Seq.of_list |> Seq.maps (Seq.try inst_rule));
   761             |> Seq.of_list |> Seq.maps (Seq.try inst_rule));
   762   
   762 
   763       fun rule_cases ctxt rule cases =
   763       fun rule_cases ctxt rule cases =
   764         let
   764         let
   765           val rule' = Rule_Cases.internalize_params rule;
   765           val rule' = Rule_Cases.internalize_params rule;
   766           val rule'' = rule' |> simp ? simplified_rule ctxt;
   766           val rule'' = rule' |> simp ? simplified_rule ctxt;
   767           val nonames = map (fn ((cn, _), cls) => ((cn, []), cls));
   767           val nonames = map (fn ((cn, _), cls) => ((cn, []), cls));
   908 val taking = Scan.optional (Scan.lift (Args.$$$ takingN -- Args.colon) |--
   908 val taking = Scan.optional (Scan.lift (Args.$$$ takingN -- Args.colon) |--
   909   Scan.repeat1 (unless_more_args inst)) [];
   909   Scan.repeat1 (unless_more_args inst)) [];
   910 
   910 
   911 in
   911 in
   912 
   912 
   913 val _ =
       
   914   Theory.setup
       
   915     (Method.setup @{binding cases}
       
   916       (Scan.lift (Args.mode no_simpN) --
       
   917         (Parse.and_list' (Scan.repeat (unless_more_args inst)) -- Scan.option cases_rule) >>
       
   918         (fn (no_simp, (insts, opt_rule)) => fn ctxt =>
       
   919           METHOD_CASES (fn facts => Seq.DETERM (HEADGOAL
       
   920             (cases_tac ctxt (not no_simp) insts opt_rule facts)))))
       
   921       "case analysis on types or predicates/sets");
       
   922 
       
   923 fun gen_induct_setup binding tac =
   913 fun gen_induct_setup binding tac =
   924   Method.setup binding
   914   Method.local_setup binding
   925     (Scan.lift (Args.mode no_simpN) --
   915     (Scan.lift (Args.mode no_simpN) --
   926       (Parse.and_list' (Scan.repeat (unless_more_args def_inst)) --
   916       (Parse.and_list' (Scan.repeat (unless_more_args def_inst)) --
   927         (arbitrary -- taking -- Scan.option induct_rule)) >>
   917         (arbitrary -- taking -- Scan.option induct_rule)) >>
   928       (fn (no_simp, (insts, ((arbitrary, taking), opt_rule))) => fn ctxt => fn facts =>
   918       (fn (no_simp, (insts, ((arbitrary, taking), opt_rule))) => fn ctxt => fn facts =>
   929         Seq.DETERM (HEADGOAL (tac ctxt (not no_simp) insts arbitrary taking opt_rule facts))))
   919         Seq.DETERM (HEADGOAL (tac ctxt (not no_simp) insts arbitrary taking opt_rule facts))))
   930     "induction on types or predicates/sets";
   920     "induction on types or predicates/sets";
   931 
   921 
   932 val _ = Theory.setup (gen_induct_setup @{binding induct} induct_tac);
       
   933 
       
   934 val _ =
   922 val _ =
   935   Theory.setup
   923   Theory.local_setup
   936     (Method.setup @{binding coinduct}
   924     (Method.local_setup @{binding cases}
       
   925       (Scan.lift (Args.mode no_simpN) --
       
   926         (Parse.and_list' (Scan.repeat (unless_more_args inst)) -- Scan.option cases_rule) >>
       
   927         (fn (no_simp, (insts, opt_rule)) => fn ctxt =>
       
   928           METHOD_CASES (fn facts => Seq.DETERM (HEADGOAL
       
   929             (cases_tac ctxt (not no_simp) insts opt_rule facts)))))
       
   930       "case analysis on types or predicates/sets" #>
       
   931     gen_induct_setup @{binding induct} induct_tac #>
       
   932      Method.local_setup @{binding coinduct}
   937       (Scan.repeat (unless_more_args inst) -- taking -- Scan.option coinduct_rule >>
   933       (Scan.repeat (unless_more_args inst) -- taking -- Scan.option coinduct_rule >>
   938         (fn ((insts, taking), opt_rule) => fn ctxt => fn facts =>
   934         (fn ((insts, taking), opt_rule) => fn ctxt => fn facts =>
   939           Seq.DETERM (HEADGOAL (coinduct_tac ctxt insts taking opt_rule facts))))
   935           Seq.DETERM (HEADGOAL (coinduct_tac ctxt insts taking opt_rule facts))))
   940       "coinduction on types or predicates/sets");
   936       "coinduction on types or predicates/sets");
   941 
   937