src/HOL/Tools/Quotient/quotient_def.ML
author kuncar
Thu, 10 Apr 2014 17:48:18 +0200
changeset 57866 f4ba736040fa
parent 57861 c1048f5bbb45
child 59180 85ec71012df8
permissions -rw-r--r--
setup for Transfer and Lifting from BNF; tuned thm names
haftmann@37743
     1
(*  Title:      HOL/Tools/Quotient/quotient_def.ML
kaliszyk@35222
     2
    Author:     Cezary Kaliszyk and Christian Urban
kaliszyk@35222
     3
wenzelm@35788
     4
Definitions for constants on quotient types.
kaliszyk@35222
     5
*)
kaliszyk@35222
     6
kaliszyk@35222
     7
signature QUOTIENT_DEF =
kaliszyk@35222
     8
sig
kuncar@47961
     9
  val add_quotient_def:
kuncar@47961
    10
    ((binding * mixfix) * Attrib.binding) * (term * term) -> thm ->
kuncar@47961
    11
    local_theory -> Quotient_Info.quotconsts * local_theory
kuncar@47961
    12
wenzelm@46469
    13
  val quotient_def:
wenzelm@46469
    14
    (binding * typ option * mixfix) option * (Attrib.binding * (term * term)) ->
kuncar@47961
    15
    local_theory -> Proof.state
kaliszyk@35222
    16
wenzelm@46469
    17
  val quotient_def_cmd:
wenzelm@46469
    18
    (binding * string option * mixfix) option * (Attrib.binding * (string * string)) ->
kuncar@47961
    19
    local_theory -> Proof.state
kaliszyk@35222
    20
kaliszyk@35222
    21
end;
kaliszyk@35222
    22
kaliszyk@35222
    23
structure Quotient_Def: QUOTIENT_DEF =
kaliszyk@35222
    24
struct
kaliszyk@35222
    25
kaliszyk@35222
    26
(** Interface and Syntax Setup **)
kaliszyk@35222
    27
kuncar@47966
    28
(* Generation of the code certificate from the rsp theorem *)
kuncar@47966
    29
kuncar@48569
    30
open Lifting_Util
kuncar@48569
    31
kuncar@47966
    32
infix 0 MRSL
kuncar@47966
    33
kaliszyk@35222
    34
(* The ML-interface for a quotient definition takes
kaliszyk@35222
    35
   as argument:
kaliszyk@35222
    36
kaliszyk@35222
    37
    - an optional binding and mixfix annotation
kaliszyk@35222
    38
    - attributes
kaliszyk@35222
    39
    - the new constant as term
kaliszyk@35222
    40
    - the rhs of the definition as term
kuncar@47961
    41
    - respectfulness theorem for the rhs
kaliszyk@35222
    42
wenzelm@46150
    43
   It stores the qconst_info in the quotconsts data slot.
kaliszyk@35222
    44
wenzelm@41700
    45
   Restriction: At the moment the left- and right-hand
wenzelm@41700
    46
   side of the definition must be a constant.
kaliszyk@35222
    47
*)
wenzelm@41700
    48
fun error_msg bind str =
wenzelm@41700
    49
  let
wenzelm@41700
    50
    val name = Binding.name_of bind
wenzelm@50007
    51
    val pos = Position.here (Binding.pos_of bind)
wenzelm@41700
    52
  in
wenzelm@41700
    53
    error ("Head of quotient_definition " ^
wenzelm@41700
    54
      quote str ^ " differs from declaration " ^ name ^ pos)
wenzelm@41700
    55
  end
kaliszyk@35222
    56
kuncar@47961
    57
fun add_quotient_def ((var, (name, atts)), (lhs, rhs)) rsp_thm lthy =
kuncar@47961
    58
  let
kuncar@47966
    59
    val rty = fastype_of rhs
kuncar@47966
    60
    val qty = fastype_of lhs
kuncar@47961
    61
    val absrep_trm = 
kuncar@47966
    62
      Quotient_Term.absrep_fun lthy Quotient_Term.AbsF (rty, qty) $ rhs
kuncar@47961
    63
    val prop = Syntax.check_term lthy (Logic.mk_equals (lhs, absrep_trm))
kuncar@47961
    64
    val (_, prop') = Local_Defs.cert_def lthy prop
kuncar@47961
    65
    val (_, newrhs) = Local_Defs.abs_def prop'
kuncar@47961
    66
kuncar@47966
    67
    val ((trm, (_ , def_thm)), lthy') =
kuncar@47961
    68
      Local_Theory.define (var, ((Thm.def_binding_optional (#1 var) name, atts), newrhs)) lthy
kuncar@47961
    69
kuncar@47961
    70
    (* data storage *)
kuncar@47966
    71
    val qconst_data = {qconst = trm, rconst = rhs, def = def_thm}
kuncar@48069
    72
     
kuncar@48069
    73
    fun qualify defname suffix = Binding.name suffix
kuncar@48069
    74
      |> Binding.qualify true defname
kuncar@48069
    75
kuncar@48069
    76
    val lhs_name = Binding.name_of (#1 var)
kuncar@48069
    77
    val rsp_thm_name = qualify lhs_name "rsp"
kuncar@47961
    78
    
kuncar@47961
    79
    val lthy'' = lthy'
kuncar@47961
    80
      |> Local_Theory.declaration {syntax = false, pervasive = true}
kuncar@47961
    81
        (fn phi =>
kuncar@47961
    82
          (case Quotient_Info.transform_quotconsts phi qconst_data of
kuncar@47961
    83
            qcinfo as {qconst = Const (c, _), ...} =>
kuncar@47961
    84
              Quotient_Info.update_quotconsts c qcinfo
kuncar@47961
    85
          | _ => I))
kuncar@47961
    86
      |> (snd oo Local_Theory.note) 
kuncar@48027
    87
        ((rsp_thm_name, [Attrib.internal (K Quotient_Info.rsp_rules_add)]),
kuncar@47961
    88
        [rsp_thm])
kuncar@47961
    89
  in
kuncar@47961
    90
    (qconst_data, lthy'')
kuncar@47961
    91
  end
kuncar@47961
    92
kuncar@47961
    93
fun mk_readable_rsp_thm_eq tm lthy =
kuncar@47961
    94
  let
kuncar@47961
    95
    val ctm = cterm_of (Proof_Context.theory_of lthy) tm
kuncar@47961
    96
    
kuncar@47961
    97
    fun norm_fun_eq ctm = 
kuncar@47961
    98
      let
kuncar@47961
    99
        fun abs_conv2 cv = Conv.abs_conv (K (Conv.abs_conv (K cv) lthy)) lthy
kuncar@47961
   100
        fun erase_quants ctm' =
kuncar@47961
   101
          case (Thm.term_of ctm') of
bulwahn@48050
   102
            Const (@{const_name HOL.eq}, _) $ _ $ _ => Conv.all_conv ctm'
kuncar@47961
   103
            | _ => (Conv.binder_conv (K erase_quants) lthy then_conv 
kuncar@47961
   104
              Conv.rewr_conv @{thm fun_eq_iff[symmetric, THEN eq_reflection]}) ctm'
kuncar@47961
   105
      in
kuncar@47961
   106
        (abs_conv2 erase_quants then_conv Thm.eta_conversion) ctm
kuncar@47961
   107
      end
kuncar@47961
   108
kuncar@47961
   109
    fun simp_arrows_conv ctm =
kuncar@47961
   110
      let
kuncar@47961
   111
        val unfold_conv = Conv.rewrs_conv 
kuncar@57861
   112
          [@{thm rel_fun_eq_eq_onp[THEN eq_reflection]}, @{thm rel_fun_eq_rel[THEN eq_reflection]}, 
blanchet@57287
   113
            @{thm rel_fun_def[THEN eq_reflection]}]
kuncar@47961
   114
        val left_conv = simp_arrows_conv then_conv Conv.try_conv norm_fun_eq
kuncar@47961
   115
        fun binop_conv2 cv1 cv2 = Conv.combination_conv (Conv.arg_conv cv1) cv2
kuncar@47961
   116
      in
kuncar@47961
   117
        case (Thm.term_of ctm) of
blanchet@57287
   118
          Const (@{const_name rel_fun}, _) $ _ $ _ => 
bulwahn@48050
   119
            (binop_conv2 left_conv simp_arrows_conv then_conv unfold_conv) ctm
kuncar@47961
   120
          | _ => Conv.all_conv ctm
kuncar@47961
   121
      end
kuncar@47961
   122
kuncar@47966
   123
    val unfold_ret_val_invs = Conv.bottom_conv 
kuncar@57866
   124
      (K (Conv.try_conv (Conv.rewr_conv @{thm eq_onp_same_args[THEN eq_reflection]}))) lthy 
kuncar@47961
   125
    val simp_conv = Conv.arg_conv (Conv.fun2_conv simp_arrows_conv)
kuncar@47961
   126
    val univq_conv = Conv.rewr_conv @{thm HOL.all_simps(6)[symmetric, THEN eq_reflection]}
kuncar@47961
   127
    val univq_prenex_conv = Conv.top_conv (K (Conv.try_conv univq_conv)) lthy
kuncar@47966
   128
    val beta_conv = Thm.beta_conversion true
kuncar@47961
   129
    val eq_thm = 
kuncar@47966
   130
      (simp_conv then_conv univq_prenex_conv then_conv beta_conv then_conv unfold_ret_val_invs) ctm
kuncar@47961
   131
  in
wenzelm@56084
   132
    Object_Logic.rulify lthy (eq_thm RS Drule.equal_elim_rule2)
kuncar@47961
   133
  end
kuncar@47961
   134
kuncar@47961
   135
kuncar@47961
   136
kuncar@47961
   137
fun gen_quotient_def prep_vars prep_term (raw_var, (attr, (lhs_raw, rhs_raw))) lthy =
wenzelm@41700
   138
  let
krauss@44464
   139
    val (vars, ctxt) = prep_vars (the_list raw_var) lthy
krauss@44534
   140
    val T_opt = (case vars of [(_, SOME T, _)] => SOME T | _ => NONE)
krauss@44534
   141
    val lhs = prep_term T_opt ctxt lhs_raw
krauss@44534
   142
    val rhs = prep_term NONE ctxt rhs_raw
krauss@44464
   143
wenzelm@41700
   144
    val (lhs_str, lhs_ty) = dest_Free lhs handle TERM _ => error "Constant already defined."
wenzelm@41700
   145
    val _ = if null (strip_abs_vars rhs) then () else error "The definiens cannot be an abstraction"
wenzelm@41700
   146
    val _ = if is_Const rhs then () else warning "The definiens is not a constant"
kaliszyk@35222
   147
krauss@44464
   148
    val var =
krauss@44464
   149
      (case vars of 
krauss@44464
   150
        [] => (Binding.name lhs_str, NoSyn)
krauss@44464
   151
      | [(binding, _, mx)] =>
krauss@44464
   152
          if Variable.check_name binding = lhs_str then (binding, mx)
krauss@44464
   153
          else error_msg binding lhs_str
krauss@44464
   154
      | _ => raise Match)
kuncar@47961
   155
    
kuncar@47961
   156
    fun try_to_prove_refl thm = 
kuncar@47961
   157
      let
kuncar@47961
   158
        val lhs_eq =
kuncar@47961
   159
          thm
kuncar@47961
   160
          |> prop_of
kuncar@47961
   161
          |> Logic.dest_implies
kuncar@47961
   162
          |> fst
kuncar@47961
   163
          |> strip_all_body
kuncar@47961
   164
          |> try HOLogic.dest_Trueprop
kuncar@47961
   165
      in
kuncar@47961
   166
        case lhs_eq of
bulwahn@48050
   167
          SOME (Const (@{const_name HOL.eq}, _) $ _ $ _) => SOME (@{thm refl} RS thm)
kuncar@47961
   168
          | SOME _ => (case body_type (fastype_of lhs) of
wenzelm@51917
   169
            Type (typ_name, _) =>
wenzelm@51917
   170
              try (fn () =>
wenzelm@51917
   171
                #equiv_thm (the (Quotient_Info.lookup_quotients lthy typ_name)) 
wenzelm@51917
   172
                  RS @{thm Equiv_Relations.equivp_reflp} RS thm) ()
kuncar@47961
   173
            | _ => NONE
kuncar@47961
   174
            )
kuncar@47961
   175
          | _ => NONE
kuncar@47961
   176
      end
kaliszyk@35222
   177
kuncar@47961
   178
    val rsp_rel = Quotient_Term.equiv_relation lthy (fastype_of rhs, lhs_ty)
kuncar@47961
   179
    val internal_rsp_tm = HOLogic.mk_Trueprop (Syntax.check_term lthy (rsp_rel $ rhs $ rhs))
kuncar@47961
   180
    val readable_rsp_thm_eq = mk_readable_rsp_thm_eq internal_rsp_tm lthy
kuncar@47961
   181
    val maybe_proven_rsp_thm = try_to_prove_refl readable_rsp_thm_eq
kuncar@47961
   182
    val (readable_rsp_tm, _) = Logic.dest_implies (prop_of readable_rsp_thm_eq)
kuncar@47961
   183
  
kuncar@47961
   184
    fun after_qed thm_list lthy = 
kuncar@47961
   185
      let
kuncar@47961
   186
        val internal_rsp_thm =
kuncar@47961
   187
          case thm_list of
kuncar@47961
   188
            [] => the maybe_proven_rsp_thm
kuncar@47961
   189
          | [[thm]] => Goal.prove ctxt [] [] internal_rsp_tm 
wenzelm@56084
   190
            (fn _ => rtac readable_rsp_thm_eq 1 THEN Proof_Context.fact_tac ctxt [thm] 1)
kuncar@47961
   191
      in
kuncar@47961
   192
        snd (add_quotient_def ((var, attr), (lhs, rhs)) internal_rsp_thm lthy)
kuncar@47961
   193
      end
kaliszyk@35222
   194
wenzelm@41700
   195
  in
kuncar@47961
   196
    case maybe_proven_rsp_thm of
kuncar@47961
   197
      SOME _ => Proof.theorem NONE after_qed [] lthy
kuncar@47961
   198
      | NONE =>  Proof.theorem NONE after_qed [[(readable_rsp_tm,[])]] lthy
wenzelm@41700
   199
  end
kaliszyk@35222
   200
krauss@44534
   201
fun check_term' cnstr ctxt =
krauss@44534
   202
  Syntax.check_term ctxt o (case cnstr of SOME T => Type.constraint T | _ => I)
wenzelm@46469
   203
wenzelm@46469
   204
fun read_term' cnstr ctxt =
bulwahn@46800
   205
  check_term' cnstr ctxt o Syntax.parse_term ctxt
krauss@44534
   206
krauss@44534
   207
val quotient_def = gen_quotient_def Proof_Context.cert_vars check_term'
wenzelm@46469
   208
val quotient_def_cmd = gen_quotient_def Proof_Context.read_vars read_term'
krauss@44464
   209
kaliszyk@35222
   210
kuncar@47961
   211
(* parser and command *)
kuncar@47961
   212
val quotdef_parser =
kuncar@47961
   213
  Scan.option Parse_Spec.constdecl --
kuncar@47961
   214
    Parse.!!! (Parse_Spec.opt_thm_name ":" -- (Parse.term --| @{keyword "is"} -- Parse.term))
kaliszyk@35222
   215
kaliszyk@35222
   216
val _ =
kuncar@47961
   217
  Outer_Syntax.local_theory_to_proof @{command_spec "quotient_definition"}
kaliszyk@35222
   218
    "definition for constants over the quotient type"
kuncar@47961
   219
      (quotdef_parser >> quotient_def_cmd)
kuncar@47961
   220
kaliszyk@35222
   221
kaliszyk@35222
   222
end; (* structure *)