the command "quotient" can now define more than one quotient at the same time; quotients need to be separated by and
authorChristian Urban <urbanc@in.tum.de>
Sun, 18 Oct 2009 00:52:10 +0200
changeset 127 b054cf6bd179
parent 126 9cb8f9a59402
child 128 6ddb2f99be1d
the command "quotient" can now define more than one quotient at the same time; quotients need to be separated by and
QuotMain.thy
quotient.ML
--- a/QuotMain.thy	Sat Oct 17 16:06:54 2009 +0200
+++ b/QuotMain.thy	Sun Oct 18 00:52:10 2009 +0200
@@ -3,6 +3,7 @@
 uses ("quotient.ML")
 begin
 
+
 locale QUOT_TYPE =
   fixes R :: "'a \<Rightarrow> 'a \<Rightarrow> bool"
   and   Abs :: "('a \<Rightarrow> bool) \<Rightarrow> 'b"
@@ -141,6 +142,7 @@
 
 end
 
+
 section {* type definition for the quotient type *}
 
 use "quotient.ML"
@@ -250,7 +252,6 @@
 
 ML {* lookup @{theory} @{type_name list} *}
 
-
 ML {*
 (* calculates the aggregate abs and rep functions for a given type; 
    repF is for constants' arguments; absF is for constants;
--- a/quotient.ML	Sat Oct 17 16:06:54 2009 +0200
+++ b/quotient.ML	Sun Oct 18 00:52:10 2009 +0200
@@ -1,5 +1,10 @@
+signature QUOTIENT =
+sig
+  val mk_quotient_type: ((binding * mixfix) * (typ * term)) list -> Proof.context -> Proof.state
+  val mk_quotient_type_cmd: (((bstring * mixfix) * string) * string) list -> Proof.context -> Proof.state
+end;
 
-structure Quotient =
+structure Quotient: QUOTIENT =
 struct
 
 (* constructs the term lambda (c::rty => bool). EX (x::rty). c = rel x *)
@@ -94,7 +99,7 @@
 end
 
 (* main function for constructing the quotient type *)
-fun mk_typedef_main (qty_name, mx, rel, rty, equiv_thm) lthy =
+fun mk_typedef_main (((qty_name, mx), (rty, rel)), equiv_thm) lthy =
 let
   (* generates typedef *)
   val ((_, typedef_info), lthy1) = typedef_make (qty_name, mx, rel, rty) lthy
@@ -160,37 +165,55 @@
       in ProofContext.theory_of (bymt (Expression.interpretation (exp_i, []) global_eqns3 thy)) end)
 end
 
-(* syntax setup *)
-local structure P = OuterParse in
+(* interface and syntax setup *)
 
-fun mk_typedef (qty_name, mx, rty, rel_trm) lthy = 
+(* the ML-interface takes a list of 4-tuples consisting of  *)
+(*                                                          *)
+(* - the name of the quotient type                          *)
+(* - its mixfix annotation                                  *)
+(* - the type to be quotient                                *)
+(* - the relation according to which the type is quotient   *)
+  
+fun mk_quotient_type quot_list lthy = 
 let
-  val EQUIV_ty = ([rty, rty] ---> @{typ bool}) --> @{typ bool}
-  val EQUIV_goal = HOLogic.mk_Trueprop (Const (@{const_name EQUIV}, EQUIV_ty) $ rel_trm)
-		    
+  fun get_goal (rty, rel) =
+  let
+    val EQUIV_ty = ([rty, rty] ---> @{typ bool}) --> @{typ bool}
+  in 
+    (HOLogic.mk_Trueprop (Const (@{const_name EQUIV}, EQUIV_ty) $ rel), [])
+  end
+
+  val goals = map (get_goal o snd) quot_list
+              
   fun after_qed thms lthy =
   let
-    val thm = the_single (flat thms)
+    val thms' = flat thms
   in
-    mk_typedef_main (Binding.name qty_name, mx, rel_trm, rty, thm) lthy |> snd   
+    fold_map mk_typedef_main (quot_list ~~ thms') lthy |> snd
   end
 in
-  Proof.theorem_i NONE after_qed [[(EQUIV_goal, [])]] lthy
+  Proof.theorem_i NONE after_qed [goals] lthy
 end
 
-(* FIXME: allow more than one type definition *)
-val quottype_parser = 
-    P.short_ident -- P.opt_infix -- 
-       (P.$$$ "=" |-- P.typ) -- 
-         (P.$$$ "/" |-- P.term)
+val quotspec_parser = 
+    OuterParse.and_list1
+     (OuterParse.short_ident -- OuterParse.opt_infix -- 
+       (OuterParse.$$$ "=" |-- OuterParse.typ) -- 
+         (OuterParse.$$$ "/" |-- OuterParse.term))
            
-fun mk_typedef_cmd (((qstr, mx), rstr), rel_str) lthy = 
+fun mk_quotient_type_cmd spec lthy = 
 let
-  val rty = Syntax.parse_typ lthy rstr
-  val rel_trm = Syntax.parse_term lthy rel_str
-                |> Syntax.check_term lthy
+  fun parse_spec (((qty_str, mx), rty_str), rel_str) =
+  let
+    val qty_name = Binding.name qty_str
+    val rty = Syntax.parse_typ lthy rty_str
+    val rel = Syntax.parse_term lthy rel_str
+              |> Syntax.check_term lthy
+  in
+     ((qty_name, mx), (rty, rel))
+  end
 in
-  mk_typedef (qstr, mx, rty, rel_trm) lthy  
+  mk_quotient_type (map parse_spec spec) lthy
 end
 
 val _ = OuterKeyword.keyword "/"
@@ -198,9 +221,7 @@
 val _ = 
     OuterSyntax.local_theory_to_proof "quotient" 
       "quotient type definitions (requires equivalence proofs)"
-         OuterKeyword.thy_goal (quottype_parser >> mk_typedef_cmd)	     
-
-end; (* local *)
+         OuterKeyword.thy_goal (quotspec_parser >> mk_quotient_type_cmd)
 
 end; (* structure *)