Quot/quotient_term.ML
changeset 1128 17ca92ab4660
parent 1113 9f6c606d5b59
child 1188 e5413596e098
equal deleted inserted replaced
1127:243a5ceaa088 1128:17ca92ab4660
    39 
    39 
    40 
    40 
    41 (*** Aggregate Rep/Abs Function ***)
    41 (*** Aggregate Rep/Abs Function ***)
    42 
    42 
    43 
    43 
    44 (* The flag RepF is for types in negative position; AbsF is for types 
    44 (* The flag RepF is for types in negative position; AbsF is for types
    45    in positive position. Because of this, function types need to be   
    45    in positive position. Because of this, function types need to be
    46    treated specially, since there the polarity changes.               
    46    treated specially, since there the polarity changes.
    47 *)
    47 *)
    48 
    48 
    49 datatype flag = AbsF | RepF
    49 datatype flag = AbsF | RepF
    50 
    50 
    51 fun negF AbsF = RepF
    51 fun negF AbsF = RepF
    54 fun is_identity (Const (@{const_name "id"}, _)) = true
    54 fun is_identity (Const (@{const_name "id"}, _)) = true
    55   | is_identity _ = false
    55   | is_identity _ = false
    56 
    56 
    57 fun mk_identity ty = Const (@{const_name "id"}, ty --> ty)
    57 fun mk_identity ty = Const (@{const_name "id"}, ty --> ty)
    58 
    58 
    59 fun mk_fun_compose flag (trm1, trm2) = 
    59 fun mk_fun_compose flag (trm1, trm2) =
    60   case flag of
    60   case flag of
    61     AbsF => Const (@{const_name "comp"}, dummyT) $ trm1 $ trm2
    61     AbsF => Const (@{const_name "comp"}, dummyT) $ trm1 $ trm2
    62   | RepF => Const (@{const_name "comp"}, dummyT) $ trm2 $ trm1
    62   | RepF => Const (@{const_name "comp"}, dummyT) $ trm2 $ trm1
    63 
    63 
    64 fun get_mapfun ctxt s =
    64 fun get_mapfun ctxt s =
    71 end
    71 end
    72 
    72 
    73 (* makes a Free out of a TVar *)
    73 (* makes a Free out of a TVar *)
    74 fun mk_Free (TVar ((x, i), _)) = Free (unprefix "'" x ^ string_of_int i, dummyT)
    74 fun mk_Free (TVar ((x, i), _)) = Free (unprefix "'" x ^ string_of_int i, dummyT)
    75 
    75 
    76 (* produces an aggregate map function for the       
    76 (* produces an aggregate map function for the
    77    rty-part of a quotient definition; abstracts     
    77    rty-part of a quotient definition; abstracts
    78    over all variables listed in vs (these variables 
    78    over all variables listed in vs (these variables
    79    correspond to the type variables in rty)         
    79    correspond to the type variables in rty)
    80                                                     
    80 
    81    for example for: (?'a list * ?'b)                
    81    for example for: (?'a list * ?'b)
    82    it produces:     %a b. prod_map (map a) b 
    82    it produces:     %a b. prod_map (map a) b
    83 *)
    83 *)
    84 fun mk_mapfun ctxt vs rty =
    84 fun mk_mapfun ctxt vs rty =
    85 let
    85 let
    86   val vs' = map (mk_Free) vs
    86   val vs' = map (mk_Free) vs
    87 
    87 
    93     | _ => raise LIFT_MATCH "mk_mapfun (default)"
    93     | _ => raise LIFT_MATCH "mk_mapfun (default)"
    94 in
    94 in
    95   fold_rev Term.lambda vs' (mk_mapfun_aux rty)
    95   fold_rev Term.lambda vs' (mk_mapfun_aux rty)
    96 end
    96 end
    97 
    97 
    98 (* looks up the (varified) rty and qty for 
    98 (* looks up the (varified) rty and qty for
    99    a quotient definition                   
    99    a quotient definition
   100 *)
   100 *)
   101 fun get_rty_qty ctxt s =
   101 fun get_rty_qty ctxt s =
   102 let
   102 let
   103   val thy = ProofContext.theory_of ctxt
   103   val thy = ProofContext.theory_of ctxt
   104   val exn = LIFT_MATCH ("No quotient type " ^ quote s ^ " found.")
   104   val exn = LIFT_MATCH ("No quotient type " ^ quote s ^ " found.")
   105   val qdata = (quotdata_lookup thy s) handle Quotient_Info.NotFound => raise exn
   105   val qdata = (quotdata_lookup thy s) handle Quotient_Info.NotFound => raise exn
   106 in
   106 in
   107   (#rtyp qdata, #qtyp qdata)
   107   (#rtyp qdata, #qtyp qdata)
   108 end
   108 end
   109 
   109 
   110 (* takes two type-environments and looks    
   110 (* takes two type-environments and looks
   111    up in both of them the variable v, which 
   111    up in both of them the variable v, which
   112    must be listed in the environment        
   112    must be listed in the environment
   113 *)
   113 *)
   114 fun double_lookup rtyenv qtyenv v =
   114 fun double_lookup rtyenv qtyenv v =
   115 let
   115 let
   116   val v' = fst (dest_TVar v)
   116   val v' = fst (dest_TVar v)
   117 in
   117 in
   143   Syntax.check_term ctxt (absrep_const flag ctxt qty_str)
   143   Syntax.check_term ctxt (absrep_const flag ctxt qty_str)
   144 
   144 
   145 fun absrep_match_err ctxt ty_pat ty =
   145 fun absrep_match_err ctxt ty_pat ty =
   146 let
   146 let
   147   val ty_pat_str = Syntax.string_of_typ ctxt ty_pat
   147   val ty_pat_str = Syntax.string_of_typ ctxt ty_pat
   148   val ty_str = Syntax.string_of_typ ctxt ty 
   148   val ty_str = Syntax.string_of_typ ctxt ty
   149 in
   149 in
   150   raise LIFT_MATCH (space_implode " " 
   150   raise LIFT_MATCH (space_implode " "
   151     ["absrep_fun (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"])
   151     ["absrep_fun (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"])
   152 end
   152 end
   153 
   153 
   154 
   154 
   155 (** generation of an aggregate absrep function **)
   155 (** generation of an aggregate absrep function **)
   156 
   156 
   157 (* - In case of equal types we just return the identity.           
   157 (* - In case of equal types we just return the identity.
   158      
   158 
   159    - In case of TFrees we also return the identity.
   159    - In case of TFrees we also return the identity.
   160                                                              
   160 
   161    - In case of function types we recurse taking   
   161    - In case of function types we recurse taking
   162      the polarity change into account.              
   162      the polarity change into account.
   163                                                                    
   163 
   164    - If the type constructors are equal, we recurse for the        
   164    - If the type constructors are equal, we recurse for the
   165      arguments and build the appropriate map function.             
   165      arguments and build the appropriate map function.
   166                                                                    
   166 
   167    - If the type constructors are unequal, there must be an        
   167    - If the type constructors are unequal, there must be an
   168      instance of quotient types:         
   168      instance of quotient types:
   169                           
   169 
   170        - we first look up the corresponding rty_pat and qty_pat    
   170        - we first look up the corresponding rty_pat and qty_pat
   171          from the quotient definition; the arguments of qty_pat    
   171          from the quotient definition; the arguments of qty_pat
   172          must be some distinct TVars                               
   172          must be some distinct TVars
   173        - we then match the rty_pat with rty and qty_pat with qty;  
   173        - we then match the rty_pat with rty and qty_pat with qty;
   174          if matching fails the types do not correspond -> error                  
   174          if matching fails the types do not correspond -> error
   175        - the matching produces two environments; we look up the    
   175        - the matching produces two environments; we look up the
   176          assignments for the qty_pat variables and recurse on the  
   176          assignments for the qty_pat variables and recurse on the
   177          assignments                                               
   177          assignments
   178        - we prefix the aggregate map function for the rty_pat,     
   178        - we prefix the aggregate map function for the rty_pat,
   179          which is an abstraction over all type variables           
   179          which is an abstraction over all type variables
   180        - finally we compose the result with the appropriate        
   180        - finally we compose the result with the appropriate
   181          absrep function in case at least one argument produced
   181          absrep function in case at least one argument produced
   182          a non-identity function /
   182          a non-identity function /
   183          otherwise we just return the appropriate absrep
   183          otherwise we just return the appropriate absrep
   184          function                                          
   184          function
   185                                                                    
   185 
   186      The composition is necessary for types like                   
   186      The composition is necessary for types like
   187                                                                  
   187 
   188         ('a list) list / ('a foo) foo                              
   188         ('a list) list / ('a foo) foo
   189                                                                  
   189 
   190      The matching is necessary for types like                      
   190      The matching is necessary for types like
   191                                                                  
   191 
   192         ('a * 'a) list / 'a bar   
   192         ('a * 'a) list / 'a bar
   193 
   193 
   194      The test is necessary in order to eliminate superfluous
   194      The test is necessary in order to eliminate superfluous
   195      identity maps.                                 
   195      identity maps.
   196 *)  
   196 *)
   197 
   197 
   198 fun absrep_fun flag ctxt (rty, qty) =
   198 fun absrep_fun flag ctxt (rty, qty) =
   199   if rty = qty  
   199   if rty = qty
   200   then mk_identity rty
   200   then mk_identity rty
   201   else
   201   else
   202     case (rty, qty) of
   202     case (rty, qty) of
   203       (Type ("fun", [ty1, ty2]), Type ("fun", [ty1', ty2'])) =>
   203       (Type ("fun", [ty1, ty2]), Type ("fun", [ty1', ty2'])) =>
   204         let
   204         let
   207         in
   207         in
   208           list_comb (get_mapfun ctxt "fun", [arg1, arg2])
   208           list_comb (get_mapfun ctxt "fun", [arg1, arg2])
   209         end
   209         end
   210     | (Type (s, tys), Type (s', tys')) =>
   210     | (Type (s, tys), Type (s', tys')) =>
   211         if s = s'
   211         if s = s'
   212         then 
   212         then
   213            let
   213            let
   214              val args = map (absrep_fun flag ctxt) (tys ~~ tys')
   214              val args = map (absrep_fun flag ctxt) (tys ~~ tys')
   215            in
   215            in
   216              list_comb (get_mapfun ctxt s, args)
   216              list_comb (get_mapfun ctxt s, args)
   217            end 
   217            end
   218         else
   218         else
   219            let
   219            let
   220              val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s'
   220              val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s'
   221              val rtyenv = match ctxt absrep_match_err rty_pat rty
   221              val rtyenv = match ctxt absrep_match_err rty_pat rty
   222              val qtyenv = match ctxt absrep_match_err qty_pat qty
   222              val qtyenv = match ctxt absrep_match_err qty_pat qty
   223              val args_aux = map (double_lookup rtyenv qtyenv) vs
   223              val args_aux = map (double_lookup rtyenv qtyenv) vs
   224              val args = map (absrep_fun flag ctxt) args_aux
   224              val args = map (absrep_fun flag ctxt) args_aux
   225              val map_fun = mk_mapfun ctxt vs rty_pat       
   225              val map_fun = mk_mapfun ctxt vs rty_pat
   226              val result = list_comb (map_fun, args) 
   226              val result = list_comb (map_fun, args)
   227            in
   227            in
   228              if forall is_identity args
   228              if forall is_identity args
   229              then absrep_const flag ctxt s'
   229              then absrep_const flag ctxt s'
   230              else mk_fun_compose flag (absrep_const flag ctxt s', result)
   230              else mk_fun_compose flag (absrep_const flag ctxt s', result)
   231            end
   231            end
   251 *)
   251 *)
   252 
   252 
   253 (* instantiates TVars so that the term is of type ty *)
   253 (* instantiates TVars so that the term is of type ty *)
   254 fun force_typ ctxt trm ty =
   254 fun force_typ ctxt trm ty =
   255 let
   255 let
   256   val thy = ProofContext.theory_of ctxt 
   256   val thy = ProofContext.theory_of ctxt
   257   val trm_ty = fastype_of trm
   257   val trm_ty = fastype_of trm
   258   val ty_inst = Sign.typ_match thy (trm_ty, ty) Vartab.empty
   258   val ty_inst = Sign.typ_match thy (trm_ty, ty) Vartab.empty
   259 in
   259 in
   260   map_types (Envir.subst_type ty_inst) trm
   260   map_types (Envir.subst_type ty_inst) trm
   261 end
   261 end
   267   Const (@{const_name "rel_conj"}, dummyT) $ trm1 $ trm2
   267   Const (@{const_name "rel_conj"}, dummyT) $ trm1 $ trm2
   268 
   268 
   269 fun get_relmap ctxt s =
   269 fun get_relmap ctxt s =
   270 let
   270 let
   271   val thy = ProofContext.theory_of ctxt
   271   val thy = ProofContext.theory_of ctxt
   272   val exn = LIFT_MATCH ("get_relmap (no relation map function found for type " ^ s ^ ")") 
   272   val exn = LIFT_MATCH ("get_relmap (no relation map function found for type " ^ s ^ ")")
   273   val relmap = #relmap (maps_lookup thy s) handle Quotient_Info.NotFound => raise exn
   273   val relmap = #relmap (maps_lookup thy s) handle Quotient_Info.NotFound => raise exn
   274 in
   274 in
   275   Const (relmap, dummyT)
   275   Const (relmap, dummyT)
   276 end
   276 end
   277 
   277 
   290 end
   290 end
   291 
   291 
   292 fun get_equiv_rel ctxt s =
   292 fun get_equiv_rel ctxt s =
   293 let
   293 let
   294   val thy = ProofContext.theory_of ctxt
   294   val thy = ProofContext.theory_of ctxt
   295   val exn = LIFT_MATCH ("get_quotdata (no quotient found for type " ^ s ^ ")") 
   295   val exn = LIFT_MATCH ("get_quotdata (no quotient found for type " ^ s ^ ")")
   296 in
   296 in
   297   #equiv_rel (quotdata_lookup thy s) handle Quotient_Info.NotFound => raise exn
   297   #equiv_rel (quotdata_lookup thy s) handle Quotient_Info.NotFound => raise exn
   298 end
   298 end
   299 
   299 
   300 fun equiv_match_err ctxt ty_pat ty =
   300 fun equiv_match_err ctxt ty_pat ty =
   301 let
   301 let
   302   val ty_pat_str = Syntax.string_of_typ ctxt ty_pat
   302   val ty_pat_str = Syntax.string_of_typ ctxt ty_pat
   303   val ty_str = Syntax.string_of_typ ctxt ty 
   303   val ty_str = Syntax.string_of_typ ctxt ty
   304 in
   304 in
   305   raise LIFT_MATCH (space_implode " " 
   305   raise LIFT_MATCH (space_implode " "
   306     ["equiv_relation (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"])
   306     ["equiv_relation (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"])
   307 end
   307 end
   308 
   308 
   309 (* builds the aggregate equivalence relation 
   309 (* builds the aggregate equivalence relation
   310    that will be the argument of Respects     
   310    that will be the argument of Respects
   311 *)
   311 *)
   312 fun equiv_relation ctxt (rty, qty) =
   312 fun equiv_relation ctxt (rty, qty) =
   313   if rty = qty
   313   if rty = qty
   314   then HOLogic.eq_const rty
   314   then HOLogic.eq_const rty
   315   else
   315   else
   316     case (rty, qty) of
   316     case (rty, qty) of
   317       (Type (s, tys), Type (s', tys')) =>
   317       (Type (s, tys), Type (s', tys')) =>
   318        if s = s' 
   318        if s = s'
   319        then 
   319        then
   320          let
   320          let
   321            val args = map (equiv_relation ctxt) (tys ~~ tys')
   321            val args = map (equiv_relation ctxt) (tys ~~ tys')
   322          in
   322          in
   323            list_comb (get_relmap ctxt s, args) 
   323            list_comb (get_relmap ctxt s, args)
   324          end  
   324          end
   325        else 
   325        else
   326          let
   326          let
   327            val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s'
   327            val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s'
   328            val rtyenv = match ctxt equiv_match_err rty_pat rty
   328            val rtyenv = match ctxt equiv_match_err rty_pat rty
   329            val qtyenv = match ctxt equiv_match_err qty_pat qty
   329            val qtyenv = match ctxt equiv_match_err qty_pat qty
   330            val args_aux = map (double_lookup rtyenv qtyenv) vs 
   330            val args_aux = map (double_lookup rtyenv qtyenv) vs
   331            val args = map (equiv_relation ctxt) args_aux
   331            val args = map (equiv_relation ctxt) args_aux
   332            val rel_map = mk_relmap ctxt vs rty_pat       
   332            val rel_map = mk_relmap ctxt vs rty_pat
   333            val result = list_comb (rel_map, args)
   333            val result = list_comb (rel_map, args)
   334            val eqv_rel = get_equiv_rel ctxt s'
   334            val eqv_rel = get_equiv_rel ctxt s'
   335            val eqv_rel' = force_typ ctxt eqv_rel ([rty, rty] ---> @{typ bool})
   335            val eqv_rel' = force_typ ctxt eqv_rel ([rty, rty] ---> @{typ bool})
   336          in
   336          in
   337            if forall is_eq args 
   337            if forall is_eq args
   338            then eqv_rel'
   338            then eqv_rel'
   339            else mk_rel_compose (result, eqv_rel')
   339            else mk_rel_compose (result, eqv_rel')
   340          end
   340          end
   341       | _ => HOLogic.eq_const rty
   341       | _ => HOLogic.eq_const rty
   342 
   342 
   347 
   347 
   348 
   348 
   349 (*** Regularization ***)
   349 (*** Regularization ***)
   350 
   350 
   351 (* Regularizing an rtrm means:
   351 (* Regularizing an rtrm means:
   352  
   352 
   353  - Quantifiers over types that need lifting are replaced 
   353  - Quantifiers over types that need lifting are replaced
   354    by bounded quantifiers, for example:
   354    by bounded quantifiers, for example:
   355 
   355 
   356       All P  ----> All (Respects R) P
   356       All P  ----> All (Respects R) P
   357 
   357 
   358    where the aggregate relation R is given by the rty and qty;
   358    where the aggregate relation R is given by the rty and qty;
   359  
   359 
   360  - Abstractions over types that need lifting are replaced
   360  - Abstractions over types that need lifting are replaced
   361    by bounded abstractions, for example:
   361    by bounded abstractions, for example:
   362       
   362 
   363       %x. P  ----> Ball (Respects R) %x. P
   363       %x. P  ----> Ball (Respects R) %x. P
   364 
   364 
   365  - Equalities over types that need lifting are replaced by
   365  - Equalities over types that need lifting are replaced by
   366    corresponding equivalence relations, for example:
   366    corresponding equivalence relations, for example:
   367 
   367 
   390 val mk_ball = Const (@{const_name Ball}, dummyT)
   390 val mk_ball = Const (@{const_name Ball}, dummyT)
   391 val mk_bex  = Const (@{const_name Bex}, dummyT)
   391 val mk_bex  = Const (@{const_name Bex}, dummyT)
   392 val mk_bex1_rel = Const (@{const_name Bex1_rel}, dummyT)
   392 val mk_bex1_rel = Const (@{const_name Bex1_rel}, dummyT)
   393 val mk_resp = Const (@{const_name Respects}, dummyT)
   393 val mk_resp = Const (@{const_name Respects}, dummyT)
   394 
   394 
   395 (* - applies f to the subterm of an abstraction, 
   395 (* - applies f to the subterm of an abstraction,
   396      otherwise to the given term,                
   396      otherwise to the given term,
   397    - used by regularize, therefore abstracted    
   397    - used by regularize, therefore abstracted
   398      variables do not have to be treated specially 
   398      variables do not have to be treated specially
   399 *)
   399 *)
   400 fun apply_subt f (trm1, trm2) =
   400 fun apply_subt f (trm1, trm2) =
   401   case (trm1, trm2) of
   401   case (trm1, trm2) of
   402     (Abs (x, T, t), Abs (_ , _, t')) => Abs (x, T, f (t, t'))
   402     (Abs (x, T, t), Abs (_ , _, t')) => Abs (x, T, f (t, t'))
   403   | _ => f (trm1, trm2)
   403   | _ => f (trm1, trm2)
   431   | _ => false
   431   | _ => false
   432 
   432 
   433 
   433 
   434 (* produces a regularized version of rtrm
   434 (* produces a regularized version of rtrm
   435 
   435 
   436    - the result might contain dummyTs           
   436    - the result might contain dummyTs
   437 
   437 
   438    - for regularisation we do not need any      
   438    - for regularisation we do not need any
   439      special treatment of bound variables       
   439      special treatment of bound variables
   440 *)
   440 *)
   441 fun regularize_trm ctxt (rtrm, qtrm) =
   441 fun regularize_trm ctxt (rtrm, qtrm) =
   442   case (rtrm, qtrm) of
   442   case (rtrm, qtrm) of
   443     (Abs (x, ty, t), Abs (_, ty', t')) =>
   443     (Abs (x, ty, t), Abs (_, ty', t')) =>
   444        let
   444        let
   472          if ty = ty' then Const (@{const_name "Ex"}, ty) $ subtrm
   472          if ty = ty' then Const (@{const_name "Ex"}, ty) $ subtrm
   473          else mk_bex $ (mk_resp $ equiv_relation ctxt (qnt_typ ty, qnt_typ ty')) $ subtrm
   473          else mk_bex $ (mk_resp $ equiv_relation ctxt (qnt_typ ty, qnt_typ ty')) $ subtrm
   474        end
   474        end
   475 
   475 
   476   | (Const (@{const_name "Ex1"}, ty) $ (Abs (_, _,
   476   | (Const (@{const_name "Ex1"}, ty) $ (Abs (_, _,
   477       (Const (@{const_name "op &"}, _) $ (Const (@{const_name "op :"}, _) $ _ $ 
   477       (Const (@{const_name "op &"}, _) $ (Const (@{const_name "op :"}, _) $ _ $
   478         (Const (@{const_name "Respects"}, _) $ resrel)) $ (t $ _)))), 
   478         (Const (@{const_name "Respects"}, _) $ resrel)) $ (t $ _)))),
   479      Const (@{const_name "Ex1"}, ty') $ t') =>
   479      Const (@{const_name "Ex1"}, ty') $ t') =>
   480        let
   480        let
   481          val t_ = incr_boundvars (~1) t
   481          val t_ = incr_boundvars (~1) t
   482          val subtrm = apply_subt (regularize_trm ctxt) (t_, t')
   482          val subtrm = apply_subt (regularize_trm ctxt) (t_, t')
   483          val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty')
   483          val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty')
   493        in
   493        in
   494          if ty = ty' then Const (@{const_name "Ex1"}, ty) $ subtrm
   494          if ty = ty' then Const (@{const_name "Ex1"}, ty) $ subtrm
   495          else mk_bex1_rel $ (equiv_relation ctxt (qnt_typ ty, qnt_typ ty')) $ subtrm
   495          else mk_bex1_rel $ (equiv_relation ctxt (qnt_typ ty, qnt_typ ty')) $ subtrm
   496        end
   496        end
   497 
   497 
   498   | (Const (@{const_name "Ball"}, ty) $ (Const (@{const_name "Respects"}, _) $ resrel) $ t, 
   498   | (Const (@{const_name "Ball"}, ty) $ (Const (@{const_name "Respects"}, _) $ resrel) $ t,
   499      Const (@{const_name "All"}, ty') $ t') =>
   499      Const (@{const_name "All"}, ty') $ t') =>
   500        let
   500        let
   501          val subtrm = apply_subt (regularize_trm ctxt) (t, t')
   501          val subtrm = apply_subt (regularize_trm ctxt) (t, t')
   502          val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty')
   502          val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty')
   503        in
   503        in
   504          if resrel <> needrel
   504          if resrel <> needrel
   505          then term_mismatch "regularize (Ball)" ctxt resrel needrel
   505          then term_mismatch "regularize (Ball)" ctxt resrel needrel
   506          else mk_ball $ (mk_resp $ resrel) $ subtrm
   506          else mk_ball $ (mk_resp $ resrel) $ subtrm
   507        end
   507        end
   508 
   508 
   509   | (Const (@{const_name "Bex"}, ty) $ (Const (@{const_name "Respects"}, _) $ resrel) $ t, 
   509   | (Const (@{const_name "Bex"}, ty) $ (Const (@{const_name "Respects"}, _) $ resrel) $ t,
   510      Const (@{const_name "Ex"}, ty') $ t') =>
   510      Const (@{const_name "Ex"}, ty') $ t') =>
   511        let
   511        let
   512          val subtrm = apply_subt (regularize_trm ctxt) (t, t')
   512          val subtrm = apply_subt (regularize_trm ctxt) (t, t')
   513          val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty')
   513          val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty')
   514        in
   514        in
   525          if resrel <> needrel
   525          if resrel <> needrel
   526          then term_mismatch "regularize (Bex1_res)" ctxt resrel needrel
   526          then term_mismatch "regularize (Bex1_res)" ctxt resrel needrel
   527          else mk_bex1_rel $ resrel $ subtrm
   527          else mk_bex1_rel $ resrel $ subtrm
   528        end
   528        end
   529 
   529 
   530   | (* equalities need to be replaced by appropriate equivalence relations *) 
   530   | (* equalities need to be replaced by appropriate equivalence relations *)
   531     (Const (@{const_name "op ="}, ty), Const (@{const_name "op ="}, ty')) =>
   531     (Const (@{const_name "op ="}, ty), Const (@{const_name "op ="}, ty')) =>
   532          if ty = ty' then rtrm
   532          if ty = ty' then rtrm
   533          else equiv_relation ctxt (domain_type ty, domain_type ty') 
   533          else equiv_relation ctxt (domain_type ty, domain_type ty')
   534 
   534 
   535   | (* in this case we just check whether the given equivalence relation is correct *) 
   535   | (* in this case we just check whether the given equivalence relation is correct *)
   536     (rel, Const (@{const_name "op ="}, ty')) =>
   536     (rel, Const (@{const_name "op ="}, ty')) =>
   537        let
   537        let
   538          val rel_ty = fastype_of rel
   538          val rel_ty = fastype_of rel
   539          val rel' = equiv_relation_chk ctxt (domain_type rel_ty, domain_type ty') 
   539          val rel' = equiv_relation_chk ctxt (domain_type rel_ty, domain_type ty')
   540        in
   540        in
   541          if rel' aconv rel then rtrm 
   541          if rel' aconv rel then rtrm
   542          else term_mismatch "regularise (relation mismatch)" ctxt rel rel'
   542          else term_mismatch "regularise (relation mismatch)" ctxt rel rel'
   543        end
   543        end
   544 
   544 
   545   | (_, Const _) =>
   545   | (_, Const _) =>
   546        let
   546        let
   555                handle Quotient_Info.NotFound => term_mismatch "regularize(constant notfound)" ctxt rtrm qtrm
   555                handle Quotient_Info.NotFound => term_mismatch "regularize(constant notfound)" ctxt rtrm qtrm
   556            in
   556            in
   557              if Pattern.matches thy (rtrm', rtrm)
   557              if Pattern.matches thy (rtrm', rtrm)
   558              then rtrm else term_mismatch "regularize(constant mismatch)" ctxt rtrm qtrm
   558              then rtrm else term_mismatch "regularize(constant mismatch)" ctxt rtrm qtrm
   559            end
   559            end
   560        end 
   560        end
   561 
   561 
   562   | (((t1 as Const (@{const_name "split"}, _)) $ Abs (v1, ty, Abs(v1', ty', s1))),
   562   | (((t1 as Const (@{const_name "split"}, _)) $ Abs (v1, ty, Abs(v1', ty', s1))),
   563      ((t2 as Const (@{const_name "split"}, _)) $ Abs (v2, _ , Abs(v2', _  , s2)))) =>
   563      ((t2 as Const (@{const_name "split"}, _)) $ Abs (v2, _ , Abs(v2', _  , s2)))) =>
   564        regularize_trm ctxt (t1, t2) $ Abs (v1, ty, Abs (v1', ty', regularize_trm ctxt (s1, s2)))
   564        regularize_trm ctxt (t1, t2) $ Abs (v1, ty, Abs (v1', ty', regularize_trm ctxt (s1, s2)))
   565 
   565 
   569 
   569 
   570   | (t1 $ t2, t1' $ t2') =>
   570   | (t1 $ t2, t1' $ t2') =>
   571        regularize_trm ctxt (t1, t1') $ regularize_trm ctxt (t2, t2')
   571        regularize_trm ctxt (t1, t1') $ regularize_trm ctxt (t2, t2')
   572 
   572 
   573   | (Bound i, Bound i') =>
   573   | (Bound i, Bound i') =>
   574        if i = i' then rtrm 
   574        if i = i' then rtrm
   575        else raise (LIFT_MATCH "regularize (bounds mismatch)")
   575        else raise (LIFT_MATCH "regularize (bounds mismatch)")
   576 
   576 
   577   | _ =>
   577   | _ =>
   578        let 
   578        let
   579          val rtrm_str = Syntax.string_of_term ctxt rtrm
   579          val rtrm_str = Syntax.string_of_term ctxt rtrm
   580          val qtrm_str = Syntax.string_of_term ctxt qtrm
   580          val qtrm_str = Syntax.string_of_term ctxt qtrm
   581        in
   581        in
   582          raise (LIFT_MATCH ("regularize failed (default: " ^ rtrm_str ^ "," ^ qtrm_str ^ ")"))
   582          raise (LIFT_MATCH ("regularize failed (default: " ^ rtrm_str ^ "," ^ qtrm_str ^ ")"))
   583        end
   583        end
   584 
   584 
   585 fun regularize_trm_chk ctxt (rtrm, qtrm) =
   585 fun regularize_trm_chk ctxt (rtrm, qtrm) =
   586   regularize_trm ctxt (rtrm, qtrm) 
   586   regularize_trm ctxt (rtrm, qtrm)
   587   |> Syntax.check_term ctxt
   587   |> Syntax.check_term ctxt
   588 
   588 
   589 
   589 
   590 
   590 
   591 (*** Rep/Abs Injection ***)
   591 (*** Rep/Abs Injection ***)
   593 (*
   593 (*
   594 Injection of Rep/Abs means:
   594 Injection of Rep/Abs means:
   595 
   595 
   596   For abstractions:
   596   For abstractions:
   597 
   597 
   598   * If the type of the abstraction needs lifting, then we add Rep/Abs 
   598   * If the type of the abstraction needs lifting, then we add Rep/Abs
   599     around the abstraction; otherwise we leave it unchanged.
   599     around the abstraction; otherwise we leave it unchanged.
   600  
   600 
   601   For applications:
   601   For applications:
   602   
   602 
   603   * If the application involves a bounded quantifier, we recurse on 
   603   * If the application involves a bounded quantifier, we recurse on
   604     the second argument. If the application is a bounded abstraction,
   604     the second argument. If the application is a bounded abstraction,
   605     we always put an Rep/Abs around it (since bounded abstractions
   605     we always put an Rep/Abs around it (since bounded abstractions
   606     are assumed to always need lifting). Otherwise we recurse on both 
   606     are assumed to always need lifting). Otherwise we recurse on both
   607     arguments.
   607     arguments.
   608 
   608 
   609   For constants:
   609   For constants:
   610 
   610 
   611   * If the constant is (op =), we leave it always unchanged. 
   611   * If the constant is (op =), we leave it always unchanged.
   612     Otherwise the type of the constant needs lifting, we put
   612     Otherwise the type of the constant needs lifting, we put
   613     and Rep/Abs around it. 
   613     and Rep/Abs around it.
   614 
   614 
   615   For free variables:
   615   For free variables:
   616 
   616 
   617   * We put a Rep/Abs around it if the type needs lifting.
   617   * We put a Rep/Abs around it if the type needs lifting.
   618 
   618 
   619   Vars case cannot occur.
   619   Vars case cannot occur.
   620 *)
   620 *)
   621 
   621 
   622 fun mk_repabs ctxt (T, T') trm = 
   622 fun mk_repabs ctxt (T, T') trm =
   623   absrep_fun RepF ctxt (T, T') $ (absrep_fun AbsF ctxt (T, T') $ trm)
   623   absrep_fun RepF ctxt (T, T') $ (absrep_fun AbsF ctxt (T, T') $ trm)
   624 
   624 
   625 fun inj_repabs_err ctxt msg rtrm qtrm =
   625 fun inj_repabs_err ctxt msg rtrm qtrm =
   626 let
   626 let
   627   val rtrm_str = Syntax.string_of_term ctxt rtrm
   627   val rtrm_str = Syntax.string_of_term ctxt rtrm
   628   val qtrm_str = Syntax.string_of_term ctxt qtrm 
   628   val qtrm_str = Syntax.string_of_term ctxt qtrm
   629 in
   629 in
   630   raise LIFT_MATCH (space_implode " " [msg, quote rtrm_str, "and", quote qtrm_str])
   630   raise LIFT_MATCH (space_implode " " [msg, quote rtrm_str, "and", quote qtrm_str])
   631 end
   631 end
   632 
   632 
   633 
   633 
   660       in
   660       in
   661         if rty = qty then result
   661         if rty = qty then result
   662         else mk_repabs ctxt (rty, qty) result
   662         else mk_repabs ctxt (rty, qty) result
   663       end
   663       end
   664 
   664 
   665   | (t $ s, t' $ s') =>  
   665   | (t $ s, t' $ s') =>
   666        (inj_repabs_trm ctxt (t, t')) $ (inj_repabs_trm ctxt (s, s'))
   666        (inj_repabs_trm ctxt (t, t')) $ (inj_repabs_trm ctxt (s, s'))
   667 
   667 
   668   | (Free (_, T), Free (_, T')) => 
   668   | (Free (_, T), Free (_, T')) =>
   669         if T = T' then rtrm 
   669         if T = T' then rtrm
   670         else mk_repabs ctxt (T, T') rtrm
   670         else mk_repabs ctxt (T, T') rtrm
   671 
   671 
   672   | (_, Const (@{const_name "op ="}, _)) => rtrm
   672   | (_, Const (@{const_name "op ="}, _)) => rtrm
   673 
   673 
   674   | (_, Const (_, T')) =>
   674   | (_, Const (_, T')) =>
   675       let
   675       let
   676         val rty = fastype_of rtrm
   676         val rty = fastype_of rtrm
   677       in 
   677       in
   678         if rty = T' then rtrm
   678         if rty = T' then rtrm
   679         else mk_repabs ctxt (rty, T') rtrm
   679         else mk_repabs ctxt (rty, T') rtrm
   680       end   
   680       end
   681   
   681 
   682   | _ => inj_repabs_err ctxt "injection (default):" rtrm qtrm
   682   | _ => inj_repabs_err ctxt "injection (default):" rtrm qtrm
   683 
   683 
   684 fun inj_repabs_trm_chk ctxt (rtrm, qtrm) =
   684 fun inj_repabs_trm_chk ctxt (rtrm, qtrm) =
   685   inj_repabs_trm ctxt (rtrm, qtrm) 
   685   inj_repabs_trm ctxt (rtrm, qtrm)
   686   |> Syntax.check_term ctxt
   686   |> Syntax.check_term ctxt
   687 
   687 
   688 
   688 
   689 
   689 
   690 (*** Wrapper for automatically transforming an rthm into a qthm ***)
   690 (*** Wrapper for automatically transforming an rthm into a qthm ***)