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 *) |