various tunings; map_lookup now raises an exception; addition to FIXME-TODO
authorChristian Urban <urbanc@in.tum.de>
Sat, 19 Dec 2009 22:04:34 +0100
changeset 760 c1989de100b4
parent 759 119f7d6a3556
child 761 e2ac18492c68
various tunings; map_lookup now raises an exception; addition to FIXME-TODO
FIXME-TODO
Quot/quotient_def.ML
Quot/quotient_info.ML
Quot/quotient_term.ML
Quot/quotient_typ.ML
--- a/FIXME-TODO	Thu Dec 17 17:59:12 2009 +0100
+++ b/FIXME-TODO	Sat Dec 19 22:04:34 2009 +0100
@@ -14,14 +14,21 @@
 
 - Handle theorems that include Ball/Bex
 
-- quotient_respects and preserves in a natural form.
+- user should be able to give quotient_respects and 
+  preserves theorems in a more natural form.
 
+- the test in the (_, Const _) needs to be fixed
 
 Lower Priority
 ==============
 
 - accept partial equvalence relations
 
+- what happens if the original theorem contains bounded
+  quantifiers? can such theorems be lifted? If not, would 
+  it help if we introduced separate Bex and Ball constants
+  for quotienting?
+
 - inductions from the datatype package have a strange
   order of quantifiers in assumptions.
 
--- a/Quot/quotient_def.ML	Thu Dec 17 17:59:12 2009 +0100
+++ b/Quot/quotient_def.ML	Sat Dec 19 22:04:34 2009 +0100
@@ -3,6 +3,7 @@
 sig
   datatype flag = absF | repF
   val get_fun: flag -> Proof.context -> typ * typ -> term
+  
   val quotient_def: mixfix -> Attrib.binding -> term -> term ->
     Proof.context -> (term * thm) * local_theory
   val quotdef_cmd: (Attrib.binding * string) * (mixfix * string) ->
@@ -29,10 +30,13 @@
 fun mk_identity ty = Const (@{const_name "id"}, ty --> ty)
 
 fun get_fun_aux lthy s fs =
-  case (maps_lookup (ProofContext.theory_of lthy) s) of
-    SOME info => list_comb (Const (#mapfun info, dummyT), fs)
-  | NONE      => raise
-        (LIFT_MATCH (space_implode " " ["get_fun_aux: no map for type", quote s, "."]))
+let
+  val thy = ProofContext.theory_of lthy
+  val exc = LIFT_MATCH (space_implode " " ["get_fun_aux: no map for type", quote s, "."])
+  val info = maps_lookup thy s handle NotFound => raise exc
+in
+  list_comb (Const (#mapfun info, dummyT), fs)
+end
 
 fun get_const flag lthy _ qty =
 (* FIXME: check here that _ and qty are related *)
@@ -72,9 +76,9 @@
   | (TFree x, TFree x') =>
      if x = x'
      then mk_identity qty
-     else raise (LIFT_MATCH "get_fun")
-  | (TVar _, TVar _) => raise (LIFT_MATCH "get_fun")
-  | _ => raise (LIFT_MATCH "get_fun")
+     else raise (LIFT_MATCH "get_fun (frees)")
+  | (TVar _, TVar _) => raise (LIFT_MATCH "get_fun (vars)")
+  | _ => raise (LIFT_MATCH "get_fun (default)")
 
 (* interface and syntax setup *)
 
@@ -84,6 +88,7 @@
 (* - name and attributes of the meta eq           *)
 (* - the new constant including its type          *)
 (* - the rhs of the definition                    *)
+
 fun quotient_def mx attr lhs rhs lthy =
 let
   val Free (lhs_str, lhs_ty) = lhs;
@@ -115,9 +120,9 @@
 
 val quotdef_parser =
   (SpecParse.opt_thm_name ":" --
-  OuterParse.term) --
-  (OuterParse.opt_mixfix' --| OuterParse.$$$ "as" --
-  OuterParse.term)
+     OuterParse.term) --
+      (OuterParse.opt_mixfix' --| OuterParse.$$$ "as" --
+         OuterParse.term)
 
 val _ = OuterSyntax.local_theory "quotient_def" "lifted definition of constants"
   OuterKeyword.thy_decl (quotdef_parser >> quotdef_cmd)
--- a/Quot/quotient_info.ML	Thu Dec 17 17:59:12 2009 +0100
+++ b/Quot/quotient_info.ML	Sat Dec 19 22:04:34 2009 +0100
@@ -3,7 +3,7 @@
   exception NotFound
 
   type maps_info = {mapfun: string, relfun: string}
-  val maps_lookup: theory -> string -> maps_info option
+  val maps_lookup: theory -> string -> maps_info       (* raises NotFound *)
   val maps_update_thy: string -> maps_info -> theory -> theory    
   val maps_update: string -> maps_info -> Proof.context -> Proof.context     
   val print_mapsinfo: Proof.context -> unit
@@ -18,7 +18,7 @@
 
   type qconsts_info = {qconst: term, rconst: term, def: thm}
   val qconsts_transfer: morphism -> qconsts_info -> qconsts_info
-  val qconsts_lookup: theory -> term -> qconsts_info
+  val qconsts_lookup: theory -> term -> qconsts_info    (* raises NotFound *)
   val qconsts_update_thy: string -> qconsts_info -> theory -> theory
   val qconsts_update_gen: string -> qconsts_info -> Context.generic -> Context.generic
   val qconsts_dest: theory -> qconsts_info list
@@ -50,7 +50,10 @@
    val extend = I
    val merge = Symtab.merge (K true))
 
-val maps_lookup = Symtab.lookup o MapsData.get
+fun maps_lookup thy s = 
+  case (Symtab.lookup (MapsData.get thy) s) of
+    SOME map_fun => map_fun
+  | NONE => raise NotFound
 
 fun maps_update_thy k minfo = MapsData.map (Symtab.update (k, minfo))
 fun maps_update k minfo = ProofContext.theory (maps_update_thy k minfo)
@@ -188,14 +191,15 @@
     | _ => raise NotFound
   end
 
-(* We omit printing the definition *)
 fun print_qconstinfo ctxt =
 let
   fun prt_qconst {qconst, rconst, def} =
       Pretty.block (separate (Pretty.brk 1)
           [Syntax.pretty_term ctxt qconst,
            Pretty.str ":=",
-           Syntax.pretty_term ctxt rconst])
+           Syntax.pretty_term ctxt rconst,
+           Pretty.str "as",
+           Syntax.pretty_term ctxt (prop_of def)])
 in
   QConstsData.get (ProofContext.theory_of ctxt)
   |> Symtab.dest
--- a/Quot/quotient_term.ML	Thu Dec 17 17:59:12 2009 +0100
+++ b/Quot/quotient_term.ML	Sat Dec 19 22:04:34 2009 +0100
@@ -10,31 +10,32 @@
 (*
 Regularizing an rtrm means:
  
- - Quantifiers over a type that need lifting are replaced 
+ - Quantifiers over types that need lifting are replaced 
    by bounded quantifiers, for example:
 
-      All P  ===> All (Respects R) P
+      All P  ----> All (Respects R) P
 
-   where the relation R is given by the rty and qty;
+   where the aggregate relation R is given by the rty and qty;
  
- - Abstractions over a type that needs lifting are replaced
-   by bounded abstractions:
+ - Abstractions over types that need lifting are replaced
+   by bounded abstractions, for example:
       
-      %x. P  ===> Ball (Respects R) %x. P
+      %x. P  ----> Ball (Respects R) %x. P
 
- - Equalities over the type being lifted are replaced by
-   corresponding equivalence relations:
+ - Equalities over types that need lifting are replaced by
+   corresponding equivalence relations, for example:
 
-      A = B  ===> R A B
+      A = B  ----> R A B
 
    or 
 
-      A = B  ===> (R ===> R) A B
+      A = B  ----> (R ===> R) A B
  
    for more complicated types of A and B
 *)
 
-(* builds the relation that is the argument of respects *)
+(* builds the aggregate equivalence relation *)
+(* that will be the argument of Respects     *)
 fun mk_resp_arg lthy (rty, qty) =
 let
   val thy = ProofContext.theory_of lthy
@@ -46,8 +47,9 @@
       (Type (s, tys), Type (s', tys')) =>
        if s = s' 
        then let
-              val SOME map_info = maps_lookup thy s
-              (* FIXME dont return an option, raise an exception *)
+              val map_info = maps_lookup thy s
+                             handle NotFound => 
+                               raise LIFT_MATCH ("mk_resp_arg (no map function found for type " ^ s) 
               val args = map (mk_resp_arg lthy) (tys ~~ tys')
             in
               list_comb (Const (#relfun map_info, dummyT), args) 
@@ -88,7 +90,7 @@
 
 (* produces a regularized version of rtrm       *)
 (*                                              *)
-(* - the result is still contains dummyT        *)
+(* - the result still contains dummyTs          *)
 (*                                              *)
 (* - for regularisation we do not need any      *)
 (*   special treatment of bound variables       *)
@@ -124,14 +126,14 @@
          if ty = ty' then rtrm
          else mk_resp_arg lthy (domain_type ty, domain_type ty') 
 
-  | (* in this case we check whether the given equivalence relation is correct *) 
+  | (* in this case we just check whether the given equivalence relation is correct *) 
     (rel, Const (@{const_name "op ="}, ty')) =>
        let 
          val exc = LIFT_MATCH "regularise (relation mismatch)"
          val rel_ty = (fastype_of rel) handle TERM _ => raise exc 
          val rel' = mk_resp_arg lthy (domain_type rel_ty, domain_type ty') 
        in 
-         if rel' = rel then rtrm else raise exc
+         if rel' aconv rel then rtrm else raise exc
        end  
 
   | (_, Const _) =>
@@ -168,10 +170,6 @@
   | (t1 $ t2, t1' $ t2') =>
        (regularize_trm lthy t1 t1') $ (regularize_trm lthy t2 t2')
 
-  | (Free (x, ty), Free (x', ty')) => 
-       (* this case cannot arrise as we start with two fully atomized terms *)
-       raise (LIFT_MATCH "regularize (frees)")
-
   | (Bound i, Bound i') =>
        if i = i' then rtrm 
        else raise (LIFT_MATCH "regularize (bounds mismatch)")
@@ -187,32 +185,31 @@
 
 
 (*
-Injecting of Rep/Abs means:
+Injection of Rep/Abs means:
 
   For abstractions
 :
-  * If the type of the abstraction doesn't need lifting we recurse.
-
-  * If it needs lifting then we add Rep/Abs around the whole term and 
-    check if the bound variable needs lifting.
+  * If the type of the abstraction needs lifting, then we add Rep/Abs 
+    around the abstraction; otherwise we leave it unchanged.
  
-    * If it does we recurse and put Rep/Abs around all occurences
-      of the variable in the obtained subterm. This in combination
-      with the Rep/Abs from above will let us change the type of 
-      the abstraction with rewriting.
-  
   For applications:
   
-  * If the term is Respects applied to anything we leave it unchanged
+  * If the application involves a bounded quantifier, we recurse on 
+    the second argument. If the application is a bounded abstraction,
+    we always put an Re/Abs around it (since bounded abstractions
+    always need lifting). Otherwise we recurse on both arguments.
 
-  * If the term needs lifting and the head is a constant that we know
-    how to lift, we put a Rep/Abs and recurse
+  For constants:
 
-  * If the term needs lifting and the head is a Free applied to subterms
-    (if it is not applied we treated it in Abs branch) then we
-    put Rep/Abs and recurse
+  * If the constant is (op =), we leave it always unchanged. 
+    Otherwise the type of the constant needs lifting, we put
+    and Rep/Abs around it. 
 
-  * Otherwise just recurse.
+  For free variables:
+
+  * We put aRep/Abs around it if the type needs lifting.
+
+  Vars case cannot occur.
 *)
 
 fun mk_repabs lthy (T, T') trm = 
@@ -269,7 +266,7 @@
         else mk_repabs lthy (rty, T') rtrm
       end   
   
-  | _ => raise (LIFT_MATCH "injection")
+  | _ => raise (LIFT_MATCH "injection (default)")
 
 end; (* structure *)
 
--- a/Quot/quotient_typ.ML	Thu Dec 17 17:59:12 2009 +0100
+++ b/Quot/quotient_typ.ML	Sat Dec 19 22:04:34 2009 +0100
@@ -12,7 +12,7 @@
 
 exception LIFT_MATCH of string
 
-(* wrappers for define, note and theorem_i *)
+(* wrappers for define, note, Attrib.internal and theorem_i *)
 fun define (name, mx, rhs) lthy =
 let
   val ((rhs, (_ , thm)), lthy') =
@@ -28,7 +28,7 @@
   (thm', lthy')
 end
 
-fun internal_attr at = Attrib.internal (K at)
+fun intern_attr at = Attrib.internal (K at)
 
 fun theorem after_qed goals ctxt =
 let
@@ -117,13 +117,13 @@
     (K typedef_quotient_thm_tac)
 end
 
-(* main function for constructing the quotient type *)
+(* main function for constructing a quotient type *)
 fun mk_typedef_main (((qty_name, mx), (rty, rel)), equiv_thm) lthy =
 let
-  (* generates typedef *)
+  (* generates the typedef *)
   val ((_, typedef_info), lthy1) = typedef_make (qty_name, mx, rel, rty) lthy
 
-  (* abs and rep functions *)
+  (* abs and rep functions from the typedef *)
   val abs_ty = #abs_type typedef_info
   val rep_ty = #rep_type typedef_info
   val abs_name = #Abs_name typedef_info
@@ -131,7 +131,7 @@
   val abs = Const (abs_name, rep_ty --> abs_ty)
   val rep = Const (rep_name, abs_ty --> rep_ty)
 
-  (* ABS and REP definitions *)
+  (* more abstract ABS and REP definitions *)
   val ABS_const = Const (@{const_name "QUOT_TYPE.abs"}, dummyT )
   val REP_const = Const (@{const_name "QUOT_TYPE.rep"}, dummyT )
   val ABS_trm = Syntax.check_term lthy1 (ABS_const $ rel $ abs)
@@ -155,14 +155,14 @@
   val lthy3 = quotdata_update qty_str 
                (Logic.varifyT abs_ty, Logic.varifyT rty, rel, equiv_thm) lthy2  
   (* FIXME: varifyT should not be used *)
-  (* FIXME: the relation needs to be a string, since its type needs *)
-  (* FIXME: to recalculated in for example REGULARIZE *)
+  (* FIXME: the relation can be any term, that later maybe needs to be given *)
+  (* FIXME: a different type (in regularize_trm); how should tis be done?    *)
 
 in
   lthy3
   |> note (quot_thm_name, quot_thm, [])
-  ||>> note (quotient_thm_name, quotient_thm, [internal_attr quotient_rules_add])
-  ||>> note (Binding.suffix_name "_equivp" qty_name, equiv_thm, [internal_attr equiv_rules_add])
+  ||>> note (quotient_thm_name, quotient_thm, [intern_attr quotient_rules_add])
+  ||>> note (Binding.suffix_name "_equivp" qty_name, equiv_thm, [intern_attr equiv_rules_add])
 end