src/HOL/Tools/Quotient/quotient_term.ML
changeset 37560 1b5bbc4a14bc
parent 37532 8a9a34be09e0
child 37563 6cf28a1dfd75
equal deleted inserted replaced
37559:9118ce1d1750 37560:1b5bbc4a14bc
    25 
    25 
    26   val inj_repabs_trm: Proof.context -> term * term -> term
    26   val inj_repabs_trm: Proof.context -> term * term -> term
    27   val inj_repabs_trm_chk: Proof.context -> term * term -> term
    27   val inj_repabs_trm_chk: Proof.context -> term * term -> term
    28 
    28 
    29   val derive_qtyp: typ list -> typ -> Proof.context -> typ
    29   val derive_qtyp: typ list -> typ -> Proof.context -> typ
    30   val quotient_lift_all: typ list -> Proof.context -> term -> term
    30   val derive_qtrm: typ list -> term -> Proof.context -> term
    31 end;
    31 end;
    32 
    32 
    33 structure Quotient_Term: QUOTIENT_TERM =
    33 structure Quotient_Term: QUOTIENT_TERM =
    34 struct
    34 struct
    35 
    35 
   690 
   690 
   691 (*** Wrapper for automatically transforming an rthm into a qthm ***)
   691 (*** Wrapper for automatically transforming an rthm into a qthm ***)
   692 
   692 
   693 (* subst_tys takes a list of (rty, qty) substitution pairs
   693 (* subst_tys takes a list of (rty, qty) substitution pairs
   694    and replaces all occurences of rty in the given type
   694    and replaces all occurences of rty in the given type
   695    by appropriate qty, with substitution *)
   695    by an appropriate qty
   696 fun subst_ty thy ty (rty, qty) r =
   696 *)
   697   if r <> NONE then r else
   697 fun subst_rtyp ctxt ty_subst rty =
   698   case try (Sign.typ_match thy (rty, ty)) Vartab.empty of
   698   case rty of
   699     SOME inst => SOME (Envir.subst_type inst qty)
   699     Type (s, rtys) =>
   700   | NONE => NONE
   700       let
   701 fun subst_tys thy substs ty =
   701         val thy = ProofContext.theory_of ctxt
   702   case fold (subst_ty thy ty) substs NONE of
   702         val rty' = Type (s, map (subst_rtyp ctxt ty_subst) rtys)
   703     SOME ty => ty
   703 
   704   | NONE =>
   704         fun matches [] = rty'
   705       (case ty of
   705           | matches ((rty, qty)::tail) =
   706         Type (s, tys) => Type (s, map (subst_tys thy substs) tys)
   706               case try (Sign.typ_match thy (rty, rty')) Vartab.empty of
   707       | x => x)
   707                 NONE => matches tail
   708 
   708               | SOME inst => Envir.subst_type inst qty
   709 (* subst_trms takes a list of (rtrm, qtrm) substitution pairs
   709       in
   710    and if the given term matches any of the raw terms it
   710         matches ty_subst 
   711    returns the appropriate qtrm instantiated. If none of
   711       end 
   712    them matched it returns NONE. *)
   712   | _ => rty
   713 fun subst_trm thy t (rtrm, qtrm) s =
   713 
   714   if s <> NONE then s else
   714 (* subst_trms takes a list of (rconst, qconst) substitution pairs,
   715     case try (Pattern.match thy (rtrm, t)) (Vartab.empty, Vartab.empty) of
   715    as well as (rty, qty) substitution pairs, and replaces all
   716       SOME inst => SOME (Envir.subst_term inst qtrm)
   716    occurences of rconst and rty by appropriate instances of
   717     | NONE => NONE;
   717    qconst and qty
   718 fun subst_trms thy substs t = fold (subst_trm thy t) substs NONE
   718 *)
   719 
   719 fun subst_rtrm ctxt ty_subst trm_subst rtrm =
   720 (* prepares type and term substitution pairs to be used by above
   720   case rtrm of
   721    functions that let replace all raw constructs by appropriate
   721     t1 $ t2 => (subst_rtrm ctxt ty_subst trm_subst t1) $ (subst_rtrm ctxt ty_subst trm_subst t2)
   722    lifted counterparts. *)
   722   | Abs (x, ty, t) => Abs (x, subst_rtyp ctxt ty_subst ty, subst_rtrm ctxt ty_subst trm_subst t)
   723 fun get_ty_trm_substs qtys ctxt =
   723   | Free(n, ty) => Free(n, subst_rtyp ctxt ty_subst ty)
   724 let
   724   | Var(n, ty) => Var(n, subst_rtyp ctxt ty_subst ty)
   725   val thy = ProofContext.theory_of ctxt
   725   | Bound i => Bound i
   726   val quot_infos  = Quotient_Info.quotdata_dest ctxt
   726   | Const (a, ty) => 
   727   val const_infos = Quotient_Info.qconsts_dest ctxt
   727       let
   728   val all_ty_substs = map (fn ri => (#rtyp ri, #qtyp ri)) quot_infos
   728         val thy = ProofContext.theory_of ctxt
   729   val ty_substs =
   729 
   730     if qtys = [] then all_ty_substs else
   730         fun matches [] = Const (a, subst_rtyp ctxt ty_subst ty)
   731     filter (fn (_, qty) => member (op =) qtys qty) all_ty_substs
   731           | matches ((rconst, qconst)::tail) =
   732   val const_substs = map (fn ci => (#rconst ci, #qconst ci)) const_infos
   732               case try (Pattern.match thy (rconst, rtrm)) (Vartab.empty, Vartab.empty) of
   733   fun rel_eq rel = HOLogic.eq_const (subst_tys thy ty_substs (domain_type (fastype_of rel)))
   733                 NONE => matches tail
   734   val rel_substs = map (fn ri => (#equiv_rel ri, rel_eq (#equiv_rel ri))) quot_infos
   734               | SOME inst => Envir.subst_term inst qconst
   735   fun valid_trm_subst (rt, qt) = (subst_tys thy ty_substs (fastype_of rt) = fastype_of qt)
   735       in
   736   val all_trm_substs = const_substs @ rel_substs
   736         matches trm_subst
   737 in
   737       end
   738   (ty_substs, filter valid_trm_subst all_trm_substs)
   738 
   739 end
   739 (* generates type substitutions out of the
   740 
   740    types involved in a quotient
       
   741 *)
       
   742 fun get_ty_subst qtys ctxt =
       
   743   Quotient_Info.quotdata_dest ctxt
       
   744    |> map (fn x => (#rtyp x, #qtyp x))
       
   745    |> filter (fn (_, qty) => member (op =) qtys qty)
       
   746 
       
   747 (* generates term substitutions out of the qconst 
       
   748    definitions and relations in a quotient
       
   749 *)
       
   750 fun get_trm_subst qtys ctxt =
       
   751 let  
       
   752   val subst_rtyp' = subst_rtyp ctxt (get_ty_subst qtys ctxt)
       
   753   fun proper (rt, qt) = (subst_rtyp' (fastype_of rt) = fastype_of qt)
       
   754   
       
   755   val const_substs = 
       
   756     Quotient_Info.qconsts_dest ctxt
       
   757      |> map (fn x => (#rconst x, #qconst x)) 
       
   758 
       
   759   val rel_substs = 
       
   760     Quotient_Info.quotdata_dest ctxt
       
   761      |> map (fn x => (#equiv_rel x, HOLogic.eq_const (#qtyp x)))
       
   762 in
       
   763   filter proper (const_substs @ rel_substs)
       
   764 end
       
   765 
       
   766 (* derives a qtyp and qtrm out of a rtyp and rtrm,
       
   767    respectively 
       
   768 *)
   741 fun derive_qtyp qtys rty ctxt =
   769 fun derive_qtyp qtys rty ctxt =
   742 let
   770   subst_rtyp ctxt (get_ty_subst qtys ctxt) rty
   743   val thy = ProofContext.theory_of ctxt
   771 
   744   val (ty_substs, _) = get_ty_trm_substs qtys ctxt
   772 fun derive_qtrm qtys rtrm ctxt =
   745 in
   773   subst_rtrm ctxt (get_ty_subst qtys ctxt) (get_trm_subst qtys ctxt) rtrm
   746   subst_tys thy ty_substs rty
   774 
   747 end
       
   748 
       
   749 (*
       
   750 Takes a term and
       
   751 
       
   752 * replaces raw constants by the quotient constants
       
   753 
       
   754 * replaces equivalence relations by equalities
       
   755 
       
   756 * replaces raw types by the quotient types
       
   757 
       
   758 *)
       
   759 
       
   760 fun quotient_lift_all qtys ctxt t =
       
   761 let
       
   762   val thy = ProofContext.theory_of ctxt
       
   763   val (ty_substs, substs) = get_ty_trm_substs qtys ctxt
       
   764   fun lift_aux t =
       
   765     case subst_trms thy substs t of
       
   766       SOME x => x
       
   767     | NONE =>
       
   768       (case t of
       
   769         a $ b => lift_aux a $ lift_aux b
       
   770       | Abs(a, ty, s) =>
       
   771           let
       
   772             val (y, s') = Term.dest_abs (a, ty, s)
       
   773             val nty = subst_tys thy ty_substs ty
       
   774           in
       
   775             Abs(y, nty, abstract_over (Free (y, nty), lift_aux s'))
       
   776           end
       
   777       | Free(n, ty) => Free(n, subst_tys thy ty_substs ty)
       
   778       | Var(n, ty) => Var(n, subst_tys thy ty_substs ty)
       
   779       | Bound i => Bound i
       
   780       | Const(s, ty) => Const(s, subst_tys thy ty_substs ty))
       
   781 in
       
   782   lift_aux t
       
   783 end
       
   784 
   775 
   785 end; (* structure *)
   776 end; (* structure *)