src/HOL/Tools/BNF/bnf_lift.ML
changeset 71494 cbe0b6b0bed8
parent 71469 d7ef73df3d15
child 71558 1cf958713cf7
equal deleted inserted replaced
71493:4c3eedc8e0f7 71494:cbe0b6b0bed8
    22     (((lift_bnf_option list * (binding option * (string * string option)) list) *
    22     (((lift_bnf_option list * (binding option * (string * string option)) list) *
    23       string) * (Facts.ref * Token.src list) option) * (binding * binding * binding) ->
    23       string) * (Facts.ref * Token.src list) option) * (binding * binding * binding) ->
    24       local_theory -> local_theory
    24       local_theory -> local_theory
    25   val lift_bnf:
    25   val lift_bnf:
    26     ((((lift_bnf_option list * (binding option * (string * sort option)) list) *
    26     ((((lift_bnf_option list * (binding option * (string * sort option)) list) *
    27       string) * term list option) * thm option) * (binding * binding * binding) ->
    27       string) * term list option) * thm list option) * (binding * binding * binding) ->
    28       ({context: Proof.context, prems: thm list} -> tactic) list ->
    28       ({context: Proof.context, prems: thm list} -> tactic) list ->
    29       local_theory -> local_theory
    29       local_theory -> local_theory
    30   val lift_bnf_cmd:
    30   val lift_bnf_cmd:
    31      ((((lift_bnf_option list * (binding option * (string * string option)) list) *
    31      ((((lift_bnf_option list * (binding option * (string * string option)) list) *
    32        string) * string list) * (Facts.ref * Token.src list) option) *
    32        string) * string list) * (Facts.ref * Token.src list) list option) *
    33        (binding * binding * binding) -> local_theory -> Proof.state
    33        (binding * binding * binding) -> local_theory -> Proof.state
    34 end
    34 end
    35 
    35 
    36 structure BNF_Lift : BNF_LIFT =
    36 structure BNF_Lift : BNF_LIFT =
    37 struct
    37 struct
    45 datatype lift_bnf_option =
    45 datatype lift_bnf_option =
    46   Plugins_Option of Proof.context -> Plugin_Name.filter
    46   Plugins_Option of Proof.context -> Plugin_Name.filter
    47 | No_Warn_Wits
    47 | No_Warn_Wits
    48 | No_Warn_Transfer;
    48 | No_Warn_Transfer;
    49 
    49 
    50 datatype lift_thm = Typedef of thm | Quotient of thm
    50 datatype equiv_thm = Typedef | Quotient of thm
    51 
    51 
    52 (** Util **)
    52 (** Util **)
    53 
    53 
    54 fun last2 [x, y] = ([], (x, y))
    54 fun last2 [x, y] = ([], (x, y))
    55   | last2 (x :: xs) = last2 xs |>> (fn y => x :: y)
    55   | last2 (x :: xs) = last2 xs |>> (fn y => x :: y)
   325 fun mk_transfer_thms quiet bnf_F bnf_G name consts thm Tss defs lthy = let
   325 fun mk_transfer_thms quiet bnf_F bnf_G name consts thm Tss defs lthy = let
   326 
   326 
   327     fun mk_crel_def quot_thm =
   327     fun mk_crel_def quot_thm =
   328       (case thm of
   328       (case thm of
   329         Quotient equiv => @{thm Quotient_crel_quotient} OF [quot_thm, equiv]
   329         Quotient equiv => @{thm Quotient_crel_quotient} OF [quot_thm, equiv]
   330       | Typedef _ => hd ([quot_thm] RL @{thms Quotient_crel_typedef Quotient_crel_typecopy}));
   330       | Typedef => hd ([quot_thm] RL @{thms Quotient_crel_typedef Quotient_crel_typecopy}));
   331     fun no_quotient _ = [Pretty.para ("No quotient theorem has been registered for " ^
   331     fun no_quotient _ = [Pretty.para ("No quotient theorem has been registered for " ^
   332         Binding.name_of (name_of_bnf bnf_G) ^ "."),
   332         Binding.name_of (name_of_bnf bnf_G) ^ "."),
   333       Pretty.para "Use setup_lifting to register a quotient or type definition theorem."];
   333       Pretty.para "Use setup_lifting to register a quotient or type definition theorem."];
   334     fun wrong_quotient T lthy = [Pretty.para ("A wrong quotient theorem has been registered for " ^
   334     fun wrong_quotient T lthy = [Pretty.para ("A wrong quotient theorem has been registered for " ^
   335         Binding.name_of (name_of_bnf bnf_G) ^ "."),
   335         Binding.name_of (name_of_bnf bnf_G) ^ "."),
   684 
   684 
   685             val unfold_morphism = Morphism.thm_morphism "BNF" (unfold_thms lthy defs);
   685             val unfold_morphism = Morphism.thm_morphism "BNF" (unfold_thms lthy defs);
   686             val (bnf_G, lthy) = morph_bnf_defs unfold_morphism bnf_G
   686             val (bnf_G, lthy) = morph_bnf_defs unfold_morphism bnf_G
   687               |> (fn bnf => note_bnf_defs bnf lthy);
   687               |> (fn bnf => note_bnf_defs bnf lthy);
   688 
   688 
   689             val setup_lifting_thm = Typedef thm;
       
   690             val quiet = exists (fn No_Warn_Transfer => true | _ => false) opts;
   689             val quiet = exists (fn No_Warn_Transfer => true | _ => false) opts;
   691 
   690 
   692             val transfer_consts = mk_typedef_transfer_tacs bnf_F bnf_G
   691             val transfer_consts = mk_typedef_transfer_tacs bnf_F bnf_G
   693               {map_closed=map_closed_thm,typedef=thm} old_defs map_raw rel_raw pred_raw sets_F;
   692               {map_closed=map_closed_thm,typedef=thm} old_defs map_raw rel_raw pred_raw sets_F;
   694           in
   693           in
   695             lthy |> BNF_Def.register_bnf plugins AbsT_name bnf_G |>
   694             lthy |> BNF_Def.register_bnf plugins AbsT_name bnf_G |>
   696               mk_transfer_thms quiet bnf_F bnf_G AbsT_name transfer_consts setup_lifting_thm
   695               mk_transfer_thms quiet bnf_F bnf_G AbsT_name transfer_consts Typedef
   697               {abs=typ_subst_atomic (alphas ~~ alphas') AbsT, rep=RepT, Ds0=map TFree Ds0,
   696               {abs=typ_subst_atomic (alphas ~~ alphas') AbsT, rep=RepT, Ds0=map TFree Ds0,
   698                deads = deads, alphas=alphas, betas=alphas', gammas=betas, deltas=betas'} defs
   697                deads = deads, alphas=alphas, betas=alphas', gammas=betas, deltas=betas'} defs
   699           end
   698           end
   700       | after_qed _ _ = raise Match;
   699       | after_qed _ _ = raise Match;
   701   in
   700   in
   830       sets={raws=sets_raw,tacs=map2 set_transfer_q (#sets old_defs) set_F'_thmss},
   829       sets={raws=sets_raw,tacs=map2 set_transfer_q (#sets old_defs) set_F'_thmss},
   831       pred=NONE}
   830       pred=NONE}
   832   end;
   831   end;
   833 
   832 
   834 
   833 
   835 fun quotient_bnf (equiv_thm, quot_thm) _ wits specs map_b rel_b pred_b opts lthy =
   834 fun quotient_bnf (equiv_thm, quot_thm) wits specs map_b rel_b pred_b opts lthy =
   836   let
   835   let
   837     (* extract rep_G and abs_G *)
   836     (* extract rep_G and abs_G *)
   838     val (equiv_rel, abs_G, rep_G) = strip3 quot_thm;
   837     val (equiv_rel, abs_G, rep_G) = strip3 quot_thm;
   839     val (repT, absT) = dest_funT (fastype_of abs_G); (* ("?'a F", "?'a G") *)
   838     val (repT, absT) = dest_funT (fastype_of abs_G); (* ("?'a F", "?'a G") *)
   840     val absT_name = fst (dest_Type absT);
   839     val absT_name = fst (dest_Type absT);
  1966 (** main commands **)
  1965 (** main commands **)
  1967 
  1966 
  1968 local
  1967 local
  1969 
  1968 
  1970 fun prepare_common prepare_name prepare_sort prepare_term prepare_thm
  1969 fun prepare_common prepare_name prepare_sort prepare_term prepare_thm
  1971     (((((plugins, raw_specs), raw_absT_name), raw_wits), xthm_opt), (map_b, rel_b, pred_b)) lthy =
  1970     (((((plugins, raw_specs), raw_absT_name), raw_wits), xthms_opt), (map_b, rel_b, pred_b)) lthy =
  1972   let
  1971   let
  1973     val absT_name = prepare_name lthy raw_absT_name;
  1972     val absT_name = prepare_name lthy raw_absT_name;
  1974 
  1973 
  1975     val input_thm =
  1974     fun bad_input input =
  1976       (case xthm_opt of
  1975       Pretty.chunks [Pretty.para ("Expected theorem(s) of either form:"),
  1977         SOME xthm => prepare_thm lthy xthm
  1976       Pretty.item [Pretty.enum "," "" "" [Syntax.pretty_term lthy @{term "Quotient R Abs Rep T"},
  1978       | NONE => Typedef.get_info lthy absT_name |> hd |> snd |> #type_definition);
  1977         Syntax.pretty_term lthy @{term "reflp R"}]],
       
  1978       Pretty.item [Syntax.pretty_term lthy @{term "Quotient R Abs Rep T"}],
       
  1979       Pretty.item [Syntax.pretty_term lthy @{term "type_definition Rep Abs A"}],
       
  1980       Pretty.para ("Got"), Pretty.enum "," "" "" (map (Thm.pretty_thm lthy) input)]
       
  1981       |> Pretty.string_of
       
  1982       |> error;
       
  1983 
       
  1984     fun no_refl qthm =
       
  1985       Pretty.chunks [Pretty.para ("Could not find a reflexivity rule for the Quotient theorem:"),
       
  1986       Pretty.item [Thm.pretty_thm lthy qthm],
       
  1987       Pretty.para ("Try supplying a reflexivity theorem manually or registering it in setup_lifting.")]
       
  1988       |> Pretty.string_of
       
  1989       |> error;
       
  1990 
       
  1991     fun find_equiv_thm_via_Quotient qthm =
       
  1992       let
       
  1993         val refl_thms = Lifting_Info.get_reflexivity_rules lthy
       
  1994          |> map (unfold_thms lthy @{thms reflp_eq[symmetric]});
       
  1995       in
       
  1996         (case refl_thms RL [qthm RS @{thm Quotient_reflp_imp_equivp}] of
       
  1997           [] => no_refl qthm
       
  1998         | thm :: _ => thm)
       
  1999       end;
       
  2000 
       
  2001     val (lift_thm, equiv_thm) =
       
  2002       (case Option.map (prepare_thm lthy) xthms_opt of
       
  2003         SOME (thms as [qthm, _]) =>
       
  2004           (case try (fn thms => @{thm Quotient_reflp_imp_equivp} OF thms) thms of
       
  2005             SOME equiv_thm => (qthm RS @{thm Quotient_Quotient3}, Quotient equiv_thm)
       
  2006           | NONE => bad_input thms)
       
  2007       | SOME [thm] =>
       
  2008           (case try (fn thm => thm RS @{thm Quotient_Quotient3}) thm of
       
  2009             SOME qthm => (qthm, Quotient (find_equiv_thm_via_Quotient thm))
       
  2010           | NONE => if can (fn thm => thm RS @{thm type_definition.Rep}) thm
       
  2011               then (thm, Typedef)
       
  2012               else bad_input [thm])
       
  2013       | NONE => (case Lifting_Info.lookup_quotients lthy absT_name of
       
  2014             SOME {quot_thm = qthm, ...} =>
       
  2015               let
       
  2016                 val qthm = Thm.transfer' lthy qthm;
       
  2017               in
       
  2018                 case [qthm] RL @{thms Quotient_eq_onp_typedef Quotient_eq_onp_type_copy} of
       
  2019                   thm :: _ => (thm, Typedef)
       
  2020                 | _ => (qthm RS @{thm Quotient_Quotient3},
       
  2021                    Quotient (find_equiv_thm_via_Quotient qthm))
       
  2022               end
       
  2023           | NONE => (Typedef.get_info lthy absT_name |> hd |> snd |> #type_definition, Typedef))
       
  2024       | SOME thms => bad_input thms);
  1979     val wits = (Option.map o map) (prepare_term lthy) raw_wits;
  2025     val wits = (Option.map o map) (prepare_term lthy) raw_wits;
  1980     val specs =
  2026     val specs =
  1981       map (apsnd (apsnd (the_default @{sort type} o Option.map (prepare_sort lthy)))) raw_specs;
  2027       map (apsnd (apsnd (the_default @{sort type} o Option.map (prepare_sort lthy)))) raw_specs;
  1982 
  2028 
  1983     val which_bnf = (case (xthm_opt, Quotient_Info.lookup_quotients lthy absT_name) of
  2029     val which_bnf = (case equiv_thm of
  1984         (NONE, SOME qs) => quotient_bnf (#equiv_thm qs, #quot_thm qs)
  2030         Quotient thm => quotient_bnf (thm, lift_thm)
  1985       | (SOME _, _) =>
  2031       | Typedef => typedef_bnf lift_thm);
  1986           if can (fn thm => thm RS @{thm bnf_lift_Quotient_equivp}) input_thm
       
  1987           then quotient_bnf (input_thm RS conjunct2, input_thm RS conjunct1 RS @{thm Quotient_Quotient3})
       
  1988           else if can (fn thm => thm RS @{thm type_definition.Rep}) input_thm
       
  1989             then typedef_bnf
       
  1990             else Pretty.chunks [Pretty.para ("Expected theorem of either form:"),
       
  1991                 Pretty.item [Syntax.pretty_term lthy @{term "Quotient R Abs Rep T \<and> equivp R"}],
       
  1992                 Pretty.item [Syntax.pretty_term lthy @{term "type_definition Rep Abs A"}],
       
  1993                 Pretty.para ("Got"), Pretty.item [Thm.pretty_thm lthy input_thm]]
       
  1994               |> Pretty.string_of
       
  1995               |> error
       
  1996       | _ => typedef_bnf);
       
  1997 
       
  1998   in
  2032   in
  1999     which_bnf input_thm wits specs map_b rel_b pred_b plugins lthy
  2033     which_bnf wits specs map_b rel_b pred_b plugins lthy
  2000   end;
  2034   end;
  2001 
  2035 
  2002 fun prepare_lift_bnf prepare_name prepare_sort prepare_term prepare_thm =
  2036 fun prepare_lift_bnf prepare_name prepare_sort prepare_term prepare_thm =
  2003   (fn (goals, after_qed, definitions, lthy) =>
  2037   (fn (goals, after_qed, definitions, lthy) =>
  2004     lthy
  2038     lthy
  2020 in
  2054 in
  2021 
  2055 
  2022 val lift_bnf_cmd =
  2056 val lift_bnf_cmd =
  2023   prepare_lift_bnf
  2057   prepare_lift_bnf
  2024     (fst o dest_Type oo Proof_Context.read_type_name {proper = true, strict = false})
  2058     (fst o dest_Type oo Proof_Context.read_type_name {proper = true, strict = false})
  2025     Syntax.read_sort Syntax.read_term (singleton o Attrib.eval_thms);
  2059     Syntax.read_sort Syntax.read_term Attrib.eval_thms;
  2026 
  2060 
  2027 fun lift_bnf args tacs =
  2061 fun lift_bnf args tacs =
  2028   prepare_solve (K I) (K I) (K I) (K I) (K tacs) args;
  2062   prepare_solve (K I) (K I) (K I) (K I) (K tacs) args;
  2029 
  2063 
  2030 fun copy_bnf_tac {context = ctxt, prems = _} =
  2064 fun copy_bnf_tac {context = ctxt, prems = _} =
  2031   REPEAT_DETERM (resolve_tac ctxt [bexI, conjI, UNIV_I, refl, subset_refl] 1);
  2065   REPEAT_DETERM (resolve_tac ctxt [bexI, conjI, UNIV_I, refl, subset_refl] 1);
  2032 
  2066 
  2033 val copy_bnf =
  2067 val copy_bnf =
  2034   apfst (apfst (rpair NONE))
  2068   apfst (apfst (rpair NONE))
       
  2069   #> apfst (apsnd (Option.map single))
  2035   #> prepare_solve (K I) (K I) (K I) (K I)
  2070   #> prepare_solve (K I) (K I) (K I) (K I)
  2036     (fn n => replicate n copy_bnf_tac);
  2071     (fn n => replicate n copy_bnf_tac);
  2037 
  2072 
  2038 val copy_bnf_cmd =
  2073 val copy_bnf_cmd =
  2039   apfst (apfst (rpair NONE))
  2074   apfst (apfst (rpair NONE))
       
  2075   #> apfst (apsnd (Option.map single))
  2040   #> prepare_solve
  2076   #> prepare_solve
  2041     (fst o dest_Type oo Proof_Context.read_type_name {proper = true, strict = false})
  2077     (fst o dest_Type oo Proof_Context.read_type_name {proper = true, strict = false})
  2042     Syntax.read_sort Syntax.read_term (singleton o Attrib.eval_thms)
  2078     Syntax.read_sort Syntax.read_term Attrib.eval_thms
  2043     (fn n => replicate n copy_bnf_tac);
  2079     (fn n => replicate n copy_bnf_tac);
  2044 
  2080 
  2045 end;
  2081 end;
  2046 
  2082 
  2047 (** outer syntax **)
  2083 (** outer syntax **)
  2066 val parse_lift_opts = Parse.reserved "no_warn_wits" >> K No_Warn_Wits |> parse_common_opts;
  2102 val parse_lift_opts = Parse.reserved "no_warn_wits" >> K No_Warn_Wits |> parse_common_opts;
  2067 
  2103 
  2068 val parse_copy_opts = parse_common_opts Scan.fail;
  2104 val parse_copy_opts = parse_common_opts Scan.fail;
  2069 
  2105 
  2070 val parse_xthm = Scan.option (Parse.reserved "via" |-- Parse.thm);
  2106 val parse_xthm = Scan.option (Parse.reserved "via" |-- Parse.thm);
       
  2107 val parse_xthms = Scan.option (Parse.reserved "via" |-- Parse.thms1);
  2071 
  2108 
  2072 in
  2109 in
  2073 
  2110 
  2074 (* exposed commands *)
  2111 (* exposed commands *)
  2075 
  2112 
  2076 val _ =
  2113 val _ =
  2077   Outer_Syntax.local_theory_to_proof @{command_keyword lift_bnf}
  2114   Outer_Syntax.local_theory_to_proof @{command_keyword lift_bnf}
  2078     "register a quotient type/subtype of a bounded natural functor (BNF) as a BNF"
  2115     "register a quotient type/subtype of a bounded natural functor (BNF) as a BNF"
  2079     ((parse_lift_opts -- parse_type_args_named_constrained -- Parse.type_const -- parse_wits --
  2116     ((parse_lift_opts -- parse_type_args_named_constrained -- Parse.type_const -- parse_wits --
  2080       parse_xthm -- parse_map_rel_pred_bindings) >> lift_bnf_cmd);
  2117       parse_xthms -- parse_map_rel_pred_bindings) >> lift_bnf_cmd);
  2081 
  2118 
  2082 val _ =
  2119 val _ =
  2083   Outer_Syntax.local_theory @{command_keyword copy_bnf}
  2120   Outer_Syntax.local_theory @{command_keyword copy_bnf}
  2084     "register a type copy of a bounded natural functor (BNF) as a BNF"
  2121     "register a type copy of a bounded natural functor (BNF) as a BNF"
  2085     ((parse_copy_opts -- parse_type_args_named_constrained -- Parse.type_const --
  2122     ((parse_copy_opts -- parse_type_args_named_constrained -- Parse.type_const --