src/HOL/Tools/Lifting/lifting_term.ML
author kuncar
Mon, 26 Nov 2012 14:20:51 +0100
changeset 51242 01d545993e8c
parent 48966 8c8a03765de7
child 51303 986598b0efd1
permissions -rw-r--r--
generate a parameterized correspondence relation
     1 (*  Title:      HOL/Tools/Lifting/lifting_term.ML
     2     Author:     Ondrej Kuncar
     3 
     4 Proves Quotient theorem.
     5 *)
     6 
     7 signature LIFTING_TERM =
     8 sig
     9   exception QUOT_THM of typ * typ * Pretty.T
    10   exception PARAM_QUOT_THM of typ * Pretty.T
    11   exception CHECK_RTY of typ * typ
    12 
    13   val prove_quot_thm: Proof.context -> typ * typ -> thm
    14 
    15   val abs_fun: Proof.context -> typ * typ -> term
    16 
    17   val equiv_relation: Proof.context -> typ * typ -> term
    18 
    19   val prove_param_quot_thm: Proof.context -> typ -> thm * (typ * thm) list
    20 end
    21 
    22 structure Lifting_Term: LIFTING_TERM =
    23 struct
    24 open Lifting_Util
    25 
    26 infix 0 MRSL
    27 
    28 exception QUOT_THM_INTERNAL of Pretty.T
    29 exception QUOT_THM of typ * typ * Pretty.T
    30 exception PARAM_QUOT_THM of typ * Pretty.T
    31 exception CHECK_RTY of typ * typ
    32 
    33 fun match ctxt err ty_pat ty =
    34   let
    35     val thy = Proof_Context.theory_of ctxt
    36   in
    37     Sign.typ_match thy (ty_pat, ty) Vartab.empty
    38       handle Type.TYPE_MATCH => err ctxt ty_pat ty
    39   end
    40 
    41 fun equiv_match_err ctxt ty_pat ty =
    42   let
    43     val ty_pat_str = Syntax.string_of_typ ctxt ty_pat
    44     val ty_str = Syntax.string_of_typ ctxt ty
    45   in
    46     raise QUOT_THM_INTERNAL (Pretty.block
    47       [Pretty.str ("The quotient type " ^ quote ty_str),
    48        Pretty.brk 1,
    49        Pretty.str ("and the quotient type pattern " ^ quote ty_pat_str),
    50        Pretty.brk 1,
    51        Pretty.str "don't match."])
    52   end
    53 
    54 fun get_quot_thm ctxt s =
    55   let
    56     val thy = Proof_Context.theory_of ctxt
    57   in
    58     (case Lifting_Info.lookup_quotients ctxt s of
    59       SOME qdata => Thm.transfer thy (#quot_thm qdata)
    60     | NONE => raise QUOT_THM_INTERNAL (Pretty.block 
    61       [Pretty.str ("No quotient type " ^ quote s), 
    62        Pretty.brk 1, 
    63        Pretty.str "found."]))
    64   end
    65 
    66 fun get_rel_quot_thm ctxt s =
    67    let
    68     val thy = Proof_Context.theory_of ctxt
    69   in
    70     (case Lifting_Info.lookup_quotmaps ctxt s of
    71       SOME map_data => Thm.transfer thy (#rel_quot_thm map_data)
    72     | NONE => raise QUOT_THM_INTERNAL (Pretty.block 
    73       [Pretty.str ("No relator for the type " ^ quote s), 
    74        Pretty.brk 1,
    75        Pretty.str "found."]))
    76   end
    77 
    78 fun is_id_quot thm = (prop_of thm = prop_of @{thm identity_quotient})
    79 
    80 fun check_raw_types (provided_rty_name, rty_of_qty_name) qty_name =
    81   if provided_rty_name <> rty_of_qty_name then
    82     raise QUOT_THM_INTERNAL (Pretty.block 
    83         [Pretty.str ("The type " ^ quote provided_rty_name),
    84          Pretty.brk 1,
    85          Pretty.str ("is not a raw type for the quotient type " ^ quote qty_name ^ ";"),
    86          Pretty.brk 1,
    87          Pretty.str ("the correct raw type is " ^ quote rty_of_qty_name ^ ".")])
    88   else
    89     ()
    90 
    91 fun zip_Tvars ctxt type_name rty_Tvars qty_Tvars =
    92   case try (get_rel_quot_thm ctxt) type_name of
    93     NONE => rty_Tvars ~~ qty_Tvars
    94     | SOME rel_quot_thm =>
    95       let 
    96         fun quot_term_absT quot_term = 
    97           let 
    98             val (_, abs, _, _) = (dest_Quotient o HOLogic.dest_Trueprop) quot_term
    99           in
   100             fastype_of abs
   101           end
   102 
   103         fun equiv_univ_err ctxt ty_pat ty =
   104           let
   105             val ty_pat_str = Syntax.string_of_typ ctxt ty_pat
   106             val ty_str = Syntax.string_of_typ ctxt ty
   107           in
   108             raise QUOT_THM_INTERNAL (Pretty.block
   109               [Pretty.str ("The type " ^ quote ty_str),
   110                Pretty.brk 1,
   111                Pretty.str ("and the relator type pattern " ^ quote ty_pat_str),
   112                Pretty.brk 1,
   113                Pretty.str "don't unify."])
   114           end
   115 
   116         fun raw_match (TVar (v, S), T) subs =
   117               (case Vartab.defined subs v of
   118                 false => Vartab.update_new (v, (S, T)) subs
   119               | true => subs)
   120           | raw_match (Type (_, Ts), Type (_, Us)) subs =
   121               raw_matches (Ts, Us) subs
   122           | raw_match _ subs = subs
   123         and raw_matches (T :: Ts, U :: Us) subs = raw_matches (Ts, Us) (raw_match (T, U) subs)
   124           | raw_matches _ subs = subs
   125 
   126         val rty = Type (type_name, rty_Tvars)
   127         val qty = Type (type_name, qty_Tvars)
   128         val rel_quot_thm_concl = (Logic.strip_imp_concl o prop_of) rel_quot_thm
   129         val schematic_rel_absT = quot_term_absT rel_quot_thm_concl;
   130         val ctxt' = Variable.declare_typ schematic_rel_absT ctxt
   131         val thy = Proof_Context.theory_of ctxt'
   132         val absT = rty --> qty
   133         val schematic_absT = Logic.type_map (singleton (Variable.polymorphic ctxt')) absT
   134         val maxidx = Term.maxidx_of_typs [schematic_rel_absT, schematic_absT]
   135         val _ = Sign.typ_unify thy (schematic_rel_absT, schematic_absT) (Vartab.empty,maxidx)
   136           handle Type.TUNIFY => equiv_univ_err ctxt schematic_rel_absT schematic_absT
   137         val subs = raw_match (schematic_rel_absT, absT) Vartab.empty
   138         val rel_quot_thm_prems = (Logic.strip_imp_prems o prop_of) rel_quot_thm
   139       in
   140         map (dest_funT o 
   141              Envir.subst_type subs o
   142              quot_term_absT) 
   143           rel_quot_thm_prems
   144       end
   145 
   146 fun prove_schematic_quot_thm ctxt (rty, qty) =
   147   (case (rty, qty) of
   148     (Type (s, tys), Type (s', tys')) =>
   149       if s = s'
   150       then
   151         let
   152           val args = map (prove_schematic_quot_thm ctxt) (zip_Tvars ctxt s tys tys')
   153         in
   154           if forall is_id_quot args
   155           then
   156             @{thm identity_quotient}
   157           else
   158             args MRSL (get_rel_quot_thm ctxt s)
   159         end
   160       else
   161         let
   162           val quot_thm = get_quot_thm ctxt s'
   163           val (Type (rs, rtys), qty_pat) = quot_thm_rty_qty quot_thm
   164           val _ = check_raw_types (s, rs) s'
   165           val qtyenv = match ctxt equiv_match_err qty_pat qty
   166           val rtys' = map (Envir.subst_type qtyenv) rtys
   167           val args = map (prove_schematic_quot_thm ctxt) (tys ~~ rtys')
   168         in
   169           if forall is_id_quot args
   170           then
   171             quot_thm
   172           else
   173             let
   174               val rel_quot_thm = args MRSL (get_rel_quot_thm ctxt s)
   175             in
   176               [rel_quot_thm, quot_thm] MRSL @{thm Quotient_compose}
   177            end
   178         end
   179     | (_, Type (s', tys')) => 
   180       (case try (get_quot_thm ctxt) s' of
   181         SOME quot_thm => 
   182           let
   183             val rty_pat = (fst o quot_thm_rty_qty) quot_thm
   184           in
   185             prove_schematic_quot_thm ctxt (rty_pat, qty)
   186           end
   187         | NONE =>
   188           let
   189             val rty_pat = Type (s', map (fn _ => TFree ("a",[])) tys')
   190           in
   191             prove_schematic_quot_thm ctxt (rty_pat, qty)
   192           end)
   193     | _ => @{thm identity_quotient})
   194     handle QUOT_THM_INTERNAL pretty_msg => raise QUOT_THM (rty, qty, pretty_msg)
   195 
   196 fun force_qty_type thy qty quot_thm =
   197   let
   198     val (_, qty_schematic) = quot_thm_rty_qty quot_thm
   199     val match_env = Sign.typ_match thy (qty_schematic, qty) Vartab.empty
   200     fun prep_ty thy (x, (S, ty)) =
   201       (ctyp_of thy (TVar (x, S)), ctyp_of thy ty)
   202     val ty_inst = Vartab.fold (cons o (prep_ty thy)) match_env []
   203   in
   204     Thm.instantiate (ty_inst, []) quot_thm
   205   end
   206 
   207 fun check_rty_type ctxt rty quot_thm =
   208   let  
   209     val thy = Proof_Context.theory_of ctxt
   210     val (rty_forced, _) = quot_thm_rty_qty quot_thm
   211     val rty_schematic = Logic.type_map (singleton (Variable.polymorphic ctxt)) rty
   212     val _ = Sign.typ_match thy (rty_schematic, rty_forced) Vartab.empty
   213       handle Type.TYPE_MATCH => raise CHECK_RTY (rty_schematic, rty_forced)
   214   in
   215     ()
   216   end
   217 
   218 (*
   219   The function tries to prove that rty and qty form a quotient.
   220 
   221   Returns: Quotient theorem; an abstract type of the theorem is exactly
   222     qty, a representation type of the theorem is an instance of rty in general.
   223 *)
   224 
   225 fun prove_quot_thm ctxt (rty, qty) =
   226   let
   227     val thy = Proof_Context.theory_of ctxt
   228     val schematic_quot_thm = prove_schematic_quot_thm ctxt (rty, qty)
   229     val quot_thm = force_qty_type thy qty schematic_quot_thm
   230     val _ = check_rty_type ctxt rty quot_thm
   231   in
   232     quot_thm
   233   end
   234 
   235 fun abs_fun ctxt (rty, qty) =
   236   quot_thm_abs (prove_quot_thm ctxt (rty, qty))
   237 
   238 fun equiv_relation ctxt (rty, qty) =
   239   quot_thm_rel (prove_quot_thm ctxt (rty, qty))
   240 
   241 fun get_fresh_Q_t ctxt =
   242   let
   243     val Q_t = Syntax.read_term ctxt "Trueprop (Quotient R Abs Rep T)"
   244     val ctxt = Variable.declare_names Q_t ctxt
   245     val frees_Q_t = Term.add_free_names Q_t []
   246     val (_, ctxt) = Variable.variant_fixes frees_Q_t ctxt
   247   in
   248     (Q_t, ctxt)
   249   end
   250 
   251 fun prove_param_quot_thm ctxt ty = 
   252   let 
   253     fun generate (ty as Type (s, tys)) (table_ctxt as (table, ctxt)) =
   254       if null tys 
   255       then 
   256         let 
   257           val thy = Proof_Context.theory_of ctxt
   258           val instantiated_id_quot_thm = instantiate' [SOME (ctyp_of thy ty)] [] @{thm identity_quotient}
   259         in
   260           (instantiated_id_quot_thm, (table, ctxt)) 
   261         end
   262       else
   263         let
   264           val (args, table_ctxt) = fold_map generate tys table_ctxt
   265         in
   266           (args MRSL (get_rel_quot_thm ctxt s), table_ctxt)
   267         end 
   268       | generate (ty as (TVar _)) (table, ctxt) =
   269         if AList.defined (op=) table ty 
   270         then (the (AList.lookup (op=) table ty), (table, ctxt))
   271         else 
   272           let
   273             val thy = Proof_Context.theory_of ctxt
   274             val (Q_t, ctxt') = get_fresh_Q_t ctxt
   275             val Q_thm = Thm.assume (cterm_of thy Q_t)
   276             val table' = (ty, Q_thm)::table
   277           in
   278             (Q_thm, (table', ctxt'))
   279           end
   280       | generate _ _ = error "generate_param_quot_thm: TFree"
   281 
   282     val (param_quot_thm, (table, _)) = generate ty ([], ctxt)
   283   in
   284     (param_quot_thm, rev table)
   285   end
   286   handle QUOT_THM_INTERNAL pretty_msg => raise PARAM_QUOT_THM (ty, pretty_msg)
   287 
   288 end;