src/HOL/Tools/Quotient/quotient_typ.ML
changeset 37493 2377d246a631
parent 36960 01594f816e3a
child 37530 70d03844b2f9
equal deleted inserted replaced
37492:ab36b1a50ca8 37493:2377d246a631
     5 
     5 
     6 *)
     6 *)
     7 
     7 
     8 signature QUOTIENT_TYPE =
     8 signature QUOTIENT_TYPE =
     9 sig
     9 sig
    10   val add_quotient_type: ((string list * binding * mixfix) * (typ * term)) * thm
    10   val add_quotient_type: ((string list * binding * mixfix) * (typ * term * bool)) * thm
    11     -> Proof.context -> (thm * thm) * local_theory
    11     -> Proof.context -> (thm * thm) * local_theory
    12 
    12 
    13   val quotient_type: ((string list * binding * mixfix) * (typ * term)) list
    13   val quotient_type: ((string list * binding * mixfix) * (typ * term * bool)) list
    14     -> Proof.context -> Proof.state
    14     -> Proof.context -> Proof.state
    15 
    15 
    16   val quotient_type_cmd: ((((string list * binding) * mixfix) * string) * string) list
    16   val quotient_type_cmd: ((((string list * binding) * mixfix) * string) * (bool * string)) list
    17     -> Proof.context -> Proof.state
    17     -> Proof.context -> Proof.state
    18 end;
    18 end;
    19 
    19 
    20 structure Quotient_Type: QUOTIENT_TYPE =
    20 structure Quotient_Type: QUOTIENT_TYPE =
    21 struct
    21 struct
    62     [("x", rty), ("c", HOLogic.mk_setT rty)]
    62     [("x", rty), ("c", HOLogic.mk_setT rty)]
    63     |> Variable.variant_frees lthy [rel]
    63     |> Variable.variant_frees lthy [rel]
    64     |> map Free
    64     |> map Free
    65 in
    65 in
    66   lambda c (HOLogic.exists_const rty $
    66   lambda c (HOLogic.exists_const rty $
    67      lambda x (HOLogic.mk_eq (c, (rel $ x))))
    67      lambda x (HOLogic.mk_conj ((rel $ x $ x), (HOLogic.mk_eq (c, (rel $ x))))))
    68 end
    68 end
    69 
    69 
    70 
    70 
    71 (* makes the new type definitions and proves non-emptyness *)
    71 (* makes the new type definitions and proves non-emptyness *)
    72 fun typedef_make (vs, qty_name, mx, rel, rty) lthy =
    72 fun typedef_make (vs, qty_name, mx, rel, rty) equiv_thm lthy =
    73 let
    73 let
    74   val typedef_tac =
    74   val typedef_tac =
    75     EVERY1 (map rtac [@{thm exI}, mem_def2, @{thm exI}, @{thm refl}])
    75     EVERY1 (map rtac [@{thm part_equivp_typedef}, equiv_thm])
    76 in
    76 in
    77 (* FIXME: purely local typedef causes at the moment 
    77 (* FIXME: purely local typedef causes at the moment 
    78    problems with type variables
    78    problems with type variables
    79   
    79   
    80   Typedef.add_typedef false NONE (qty_name, vs, mx) 
    80   Typedef.add_typedef false NONE (qty_name, vs, mx) 
    91 (* tactic to prove the quot_type theorem for the new type *)
    91 (* tactic to prove the quot_type theorem for the new type *)
    92 fun typedef_quot_type_tac equiv_thm ((_, typedef_info): Typedef.info) =
    92 fun typedef_quot_type_tac equiv_thm ((_, typedef_info): Typedef.info) =
    93 let
    93 let
    94   val rep_thm = #Rep typedef_info RS mem_def1
    94   val rep_thm = #Rep typedef_info RS mem_def1
    95   val rep_inv = #Rep_inverse typedef_info
    95   val rep_inv = #Rep_inverse typedef_info
    96   val abs_inv = mem_def2 RS #Abs_inverse typedef_info
    96   val abs_inv = #Abs_inverse typedef_info
    97   val rep_inj = #Rep_inject typedef_info
    97   val rep_inj = #Rep_inject typedef_info
    98 in
    98 in
    99   (rtac @{thm quot_type.intro} THEN' RANGE [
    99   (rtac @{thm quot_type.intro} THEN' RANGE [
   100     rtac equiv_thm,
   100     rtac equiv_thm,
   101     rtac rep_thm,
   101     rtac rep_thm,
   102     rtac rep_inv,
   102     rtac rep_inv,
   103     EVERY' (map rtac [abs_inv, @{thm exI}, @{thm refl}]),
   103     rtac abs_inv THEN' rtac mem_def2 THEN' atac,
   104     rtac rep_inj]) 1
   104     rtac rep_inj]) 1
   105 end
   105 end
   106 
   106 
   107 
   107 
   108 (* proves the quot_type theorem for the new type *)
   108 (* proves the quot_type theorem for the new type *)
   135     (K typedef_quotient_thm_tac)
   135     (K typedef_quotient_thm_tac)
   136 end
   136 end
   137 
   137 
   138 
   138 
   139 (* main function for constructing a quotient type *)
   139 (* main function for constructing a quotient type *)
   140 fun add_quotient_type (((vs, qty_name, mx), (rty, rel)), equiv_thm) lthy =
   140 fun add_quotient_type (((vs, qty_name, mx), (rty, rel, partial)), equiv_thm) lthy =
   141 let
   141 let
       
   142   val part_equiv = if partial then equiv_thm else equiv_thm RS @{thm equivp_implies_part_equivp}
       
   143 
   142   (* generates the typedef *)
   144   (* generates the typedef *)
   143   val ((qty_full_name, typedef_info), lthy1) = typedef_make (vs, qty_name, mx, rel, rty) lthy
   145   val ((qty_full_name, typedef_info), lthy1) = typedef_make (vs, qty_name, mx, rel, rty) part_equiv lthy
   144 
   146 
   145   (* abs and rep functions from the typedef *)
   147   (* abs and rep functions from the typedef *)
   146   val Abs_ty = #abs_type (#1 typedef_info)
   148   val Abs_ty = #abs_type (#1 typedef_info)
   147   val Rep_ty = #rep_type (#1 typedef_info)
   149   val Rep_ty = #rep_type (#1 typedef_info)
   148   val Abs_name = #Abs_name (#1 typedef_info)
   150   val Abs_name = #Abs_name (#1 typedef_info)
   160 
   162 
   161   val ((abs, abs_def), lthy2) = define (abs_name, NoSyn, abs_trm) lthy1
   163   val ((abs, abs_def), lthy2) = define (abs_name, NoSyn, abs_trm) lthy1
   162   val ((rep, rep_def), lthy3) = define (rep_name, NoSyn, rep_trm) lthy2
   164   val ((rep, rep_def), lthy3) = define (rep_name, NoSyn, rep_trm) lthy2
   163 
   165 
   164   (* quot_type theorem *)
   166   (* quot_type theorem *)
   165   val quot_thm = typedef_quot_type_thm (rel, Abs_const, Rep_const, equiv_thm, typedef_info) lthy3
   167   val quot_thm = typedef_quot_type_thm (rel, Abs_const, Rep_const, part_equiv, typedef_info) lthy3
   166 
   168 
   167   (* quotient theorem *)
   169   (* quotient theorem *)
   168   val quotient_thm = typedef_quotient_thm (rel, abs, rep, abs_def, rep_def, quot_thm) lthy3
   170   val quotient_thm = typedef_quotient_thm (rel, abs, rep, abs_def, rep_def, quot_thm) lthy3
   169   val quotient_thm_name = Binding.prefix_name "Quotient_" qty_name
   171   val quotient_thm_name = Binding.prefix_name "Quotient_" qty_name
   170 
   172 
   177   val lthy4 = Local_Theory.declaration true
   179   val lthy4 = Local_Theory.declaration true
   178     (fn phi => quotdata_update_gen qty_full_name (qinfo phi)) lthy3
   180     (fn phi => quotdata_update_gen qty_full_name (qinfo phi)) lthy3
   179 in
   181 in
   180   lthy4
   182   lthy4
   181   |> note (quotient_thm_name, quotient_thm, [intern_attr quotient_rules_add])
   183   |> note (quotient_thm_name, quotient_thm, [intern_attr quotient_rules_add])
   182   ||>> note (equiv_thm_name, equiv_thm, [intern_attr equiv_rules_add])
   184   ||>> note (equiv_thm_name, equiv_thm, if partial then [] else [intern_attr equiv_rules_add])
   183 end
   185 end
   184 
   186 
   185 
   187 
   186 (* sanity checks for the quotient type specifications *)
   188 (* sanity checks for the quotient type specifications *)
   187 fun sanity_check ((vs, qty_name, _), (rty, rel)) =
   189 fun sanity_check ((vs, qty_name, _), (rty, rel, _)) =
   188 let
   190 let
   189   val rty_tfreesT = map fst (Term.add_tfreesT rty [])
   191   val rty_tfreesT = map fst (Term.add_tfreesT rty [])
   190   val rel_tfrees = map fst (Term.add_tfrees rel [])
   192   val rel_tfrees = map fst (Term.add_tfrees rel [])
   191   val rel_frees = map fst (Term.add_frees rel [])
   193   val rel_frees = map fst (Term.add_frees rel [])
   192   val rel_vars = Term.add_vars rel []
   194   val rel_vars = Term.add_vars rel []
   221 in
   223 in
   222   if null errs then () else error (cat_lines errs)
   224   if null errs then () else error (cat_lines errs)
   223 end
   225 end
   224 
   226 
   225 (* check for existence of map functions *)
   227 (* check for existence of map functions *)
   226 fun map_check ctxt (_, (rty, _)) =
   228 fun map_check ctxt (_, (rty, _, _)) =
   227 let
   229 let
   228   val thy = ProofContext.theory_of ctxt
   230   val thy = ProofContext.theory_of ctxt
   229 
   231 
   230   fun map_check_aux rty warns =
   232   fun map_check_aux rty warns =
   231     case rty of
   233     case rty of
   261 let
   263 let
   262   (* sanity check *)
   264   (* sanity check *)
   263   val _ = List.app sanity_check quot_list
   265   val _ = List.app sanity_check quot_list
   264   val _ = List.app (map_check lthy) quot_list
   266   val _ = List.app (map_check lthy) quot_list
   265 
   267 
   266   fun mk_goal (rty, rel) =
   268   fun mk_goal (rty, rel, partial) =
   267   let
   269   let
   268     val equivp_ty = ([rty, rty] ---> @{typ bool}) --> @{typ bool}
   270     val equivp_ty = ([rty, rty] ---> @{typ bool}) --> @{typ bool}
       
   271     val const = if partial then @{const_name part_equivp} else @{const_name equivp}
   269   in
   272   in
   270     HOLogic.mk_Trueprop (Const (@{const_name equivp}, equivp_ty) $ rel)
   273     HOLogic.mk_Trueprop (Const (const, equivp_ty) $ rel)
   271   end
   274   end
   272 
   275 
   273   val goals = map (mk_goal o snd) quot_list
   276   val goals = map (mk_goal o snd) quot_list
   274 
   277 
   275   fun after_qed thms lthy =
   278   fun after_qed thms lthy =
   278   theorem after_qed goals lthy
   281   theorem after_qed goals lthy
   279 end
   282 end
   280 
   283 
   281 fun quotient_type_cmd specs lthy =
   284 fun quotient_type_cmd specs lthy =
   282 let
   285 let
   283   fun parse_spec ((((vs, qty_name), mx), rty_str), rel_str) lthy =
   286   fun parse_spec ((((vs, qty_name), mx), rty_str), (partial, rel_str)) lthy =
   284   let
   287   let
   285     val rty = Syntax.read_typ lthy rty_str
   288     val rty = Syntax.read_typ lthy rty_str
   286     val lthy1 = Variable.declare_typ rty lthy
   289     val lthy1 = Variable.declare_typ rty lthy
   287     val rel = 
   290     val rel = 
   288       Syntax.parse_term lthy1 rel_str
   291       Syntax.parse_term lthy1 rel_str
   289       |> Syntax.type_constraint (rty --> rty --> @{typ bool}) 
   292       |> Syntax.type_constraint (rty --> rty --> @{typ bool}) 
   290       |> Syntax.check_term lthy1 
   293       |> Syntax.check_term lthy1 
   291     val lthy2 = Variable.declare_term rel lthy1 
   294     val lthy2 = Variable.declare_term rel lthy1 
   292   in
   295   in
   293     (((vs, qty_name, mx), (rty, rel)), lthy2)
   296     (((vs, qty_name, mx), (rty, rel, partial)), lthy2)
   294   end
   297   end
   295 
   298 
   296   val (spec', lthy') = fold_map parse_spec specs lthy
   299   val (spec', lthy') = fold_map parse_spec specs lthy
   297 in
   300 in
   298   quotient_type spec' lthy'
   301   quotient_type spec' lthy'
   299 end
   302 end
   300 
   303 
       
   304 val partial = Scan.optional (Parse.reserved "partial" -- Parse.$$$ ":" >> K true) false
       
   305 
   301 val quotspec_parser =
   306 val quotspec_parser =
   302     Parse.and_list1
   307   Parse.and_list1
   303      ((Parse.type_args -- Parse.binding) --
   308     ((Parse.type_args -- Parse.binding) --
   304         Parse.opt_mixfix -- (Parse.$$$ "=" |-- Parse.typ) --
   309       Parse.opt_mixfix -- (Parse.$$$ "=" |-- Parse.typ) --
   305          (Parse.$$$ "/" |-- Parse.term))
   310         (Parse.$$$ "/" |-- (partial -- Parse.term)))
   306 
   311 
   307 val _ = Keyword.keyword "/"
   312 val _ = Keyword.keyword "/"
   308 
   313 
   309 val _ =
   314 val _ =
   310     Outer_Syntax.local_theory_to_proof "quotient_type"
   315     Outer_Syntax.local_theory_to_proof "quotient_type"