src/HOL/Tools/coinduction.ML
changeset 61844 007d3b34080f
parent 61841 4d3527b94f2a
child 63709 d68d10fdec78
equal deleted inserted replaced
61843:1803599838a6 61844:007d3b34080f
     6 Coinduction method that avoids some boilerplate compared to coinduct.
     6 Coinduction method that avoids some boilerplate compared to coinduct.
     7 *)
     7 *)
     8 
     8 
     9 signature COINDUCTION =
     9 signature COINDUCTION =
    10 sig
    10 sig
    11   val coinduction_tac: term list -> thm option -> thm list -> int -> context_tactic
    11   val coinduction_context_tactic: term list -> thm option -> thm list -> int -> context_tactic
       
    12   val coinduction_tac: Proof.context -> term list -> thm option -> thm list -> int -> tactic
    12 end;
    13 end;
    13 
    14 
    14 structure Coinduction : COINDUCTION =
    15 structure Coinduction : COINDUCTION =
    15 struct
    16 struct
    16 
    17 
    35     val n = nth (Thm.prems_of st) (i - 1) |> Logic.strip_assums_hyp |> length;
    36     val n = nth (Thm.prems_of st) (i - 1) |> Logic.strip_assums_hyp |> length;
    36   in
    37   in
    37     (THEN_ALL_NEW_SKIP skip tac (REPEAT_DETERM_N n o eresolve0_tac [thin_rl])) i st
    38     (THEN_ALL_NEW_SKIP skip tac (REPEAT_DETERM_N n o eresolve0_tac [thin_rl])) i st
    38   end;
    39   end;
    39 
    40 
    40 fun coinduction_tac raw_vars opt_raw_thm prems =
    41 fun coinduction_context_tactic raw_vars opt_raw_thm prems =
    41   CONTEXT_SUBGOAL (fn (goal, i) => fn (ctxt, st) =>
    42   CONTEXT_SUBGOAL (fn (goal, i) => fn (ctxt, st) =>
    42     let
    43     let
    43       val lhs_of_eq = HOLogic.dest_Trueprop #> HOLogic.dest_eq #> fst;
    44       val lhs_of_eq = HOLogic.dest_Trueprop #> HOLogic.dest_eq #> fst;
    44       fun find_coinduct t =
    45       fun find_coinduct t =
    45         Induct.find_coinductP ctxt t @
    46         Induct.find_coinductP ctxt t @
   115         K (prune_params_tac ctxt)) i) st
   116         K (prune_params_tac ctxt)) i) st
   116       |> Seq.maps (fn st' =>
   117       |> Seq.maps (fn st' =>
   117         CONTEXT_CASES (Rule_Cases.make_common ctxt (Thm.prop_of st') cases) all_tac (ctxt, st'))
   118         CONTEXT_CASES (Rule_Cases.make_common ctxt (Thm.prop_of st') cases) all_tac (ctxt, st'))
   118     end);
   119     end);
   119 
   120 
       
   121 fun coinduction_tac ctxt x1 x2 x3 x4 =
       
   122   Method.NO_CONTEXT_TACTIC ctxt (coinduction_context_tactic x1 x2 x3 x4);
       
   123 
       
   124 
   120 local
   125 local
   121 
   126 
   122 val ruleN = "rule"
   127 val ruleN = "rule"
   123 val arbitraryN = "arbitrary"
   128 val arbitraryN = "arbitrary"
   124 fun single_rule [rule] = rule
   129 fun single_rule [rule] = rule
   151 val _ =
   156 val _ =
   152   Theory.setup
   157   Theory.setup
   153     (Method.setup @{binding coinduction}
   158     (Method.setup @{binding coinduction}
   154       (arbitrary -- Scan.option coinduct_rule >>
   159       (arbitrary -- Scan.option coinduct_rule >>
   155         (fn (arbitrary, opt_rule) => fn _ => fn facts =>
   160         (fn (arbitrary, opt_rule) => fn _ => fn facts =>
   156           Seq.DETERM (coinduction_tac arbitrary opt_rule facts 1)))
   161           Seq.DETERM (coinduction_context_tactic arbitrary opt_rule facts 1)))
   157       "coinduction on types or predicates/sets");
   162       "coinduction on types or predicates/sets");
   158 
   163 
   159 end;
   164 end;
   160 
   165 
   161 end;
   166 end;