src/HOL/Induct/QuoNestedDataType.thy
changeset 60530 44f9873d6f6f
parent 59478 1755b24e8b44
child 61520 8f85bb443d33
equal deleted inserted replaced
60529:24c2ef12318b 60530:44f9873d6f6f
     1 (*  Title:      HOL/Induct/QuoNestedDataType.thy
     1 (*  Title:      HOL/Induct/QuoNestedDataType.thy
     2     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     2     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     3     Copyright   2004  University of Cambridge
     3     Copyright   2004  University of Cambridge
     4 *)
     4 *)
     5 
     5 
     6 section{*Quotienting a Free Algebra Involving Nested Recursion*}
     6 section\<open>Quotienting a Free Algebra Involving Nested Recursion\<close>
     7 
     7 
     8 theory QuoNestedDataType imports Main begin
     8 theory QuoNestedDataType imports Main begin
     9 
     9 
    10 subsection{*Defining the Free Algebra*}
    10 subsection\<open>Defining the Free Algebra\<close>
    11 
    11 
    12 text{*Messages with encryption and decryption as free constructors.*}
    12 text\<open>Messages with encryption and decryption as free constructors.\<close>
    13 datatype
    13 datatype
    14      freeExp = VAR  nat
    14      freeExp = VAR  nat
    15              | PLUS  freeExp freeExp
    15              | PLUS  freeExp freeExp
    16              | FNCALL  nat "freeExp list"
    16              | FNCALL  nat "freeExp list"
    17 
    17 
    18 datatype_compat freeExp
    18 datatype_compat freeExp
    19 
    19 
    20 text{*The equivalence relation, which makes PLUS associative.*}
    20 text\<open>The equivalence relation, which makes PLUS associative.\<close>
    21 
    21 
    22 text{*The first rule is the desired equation. The next three rules
    22 text\<open>The first rule is the desired equation. The next three rules
    23 make the equations applicable to subterms. The last two rules are symmetry
    23 make the equations applicable to subterms. The last two rules are symmetry
    24 and transitivity.*}
    24 and transitivity.\<close>
    25 inductive_set
    25 inductive_set
    26   exprel :: "(freeExp * freeExp) set"
    26   exprel :: "(freeExp * freeExp) set"
    27   and exp_rel :: "[freeExp, freeExp] => bool"  (infixl "\<sim>" 50)
    27   and exp_rel :: "[freeExp, freeExp] => bool"  (infixl "\<sim>" 50)
    28   where
    28   where
    29     "X \<sim> Y == (X,Y) \<in> exprel"
    29     "X \<sim> Y == (X,Y) \<in> exprel"
    34   | SYM:   "X \<sim> Y \<Longrightarrow> Y \<sim> X"
    34   | SYM:   "X \<sim> Y \<Longrightarrow> Y \<sim> X"
    35   | TRANS: "\<lbrakk>X \<sim> Y; Y \<sim> Z\<rbrakk> \<Longrightarrow> X \<sim> Z"
    35   | TRANS: "\<lbrakk>X \<sim> Y; Y \<sim> Z\<rbrakk> \<Longrightarrow> X \<sim> Z"
    36   monos listrel_mono
    36   monos listrel_mono
    37 
    37 
    38 
    38 
    39 text{*Proving that it is an equivalence relation*}
    39 text\<open>Proving that it is an equivalence relation\<close>
    40 
    40 
    41 lemma exprel_refl: "X \<sim> X"
    41 lemma exprel_refl: "X \<sim> X"
    42   and list_exprel_refl: "(Xs,Xs) \<in> listrel(exprel)"
    42   and list_exprel_refl: "(Xs,Xs) \<in> listrel(exprel)"
    43   by (induct X and Xs rule: compat_freeExp.induct compat_freeExp_list.induct)
    43   by (induct X and Xs rule: compat_freeExp.induct compat_freeExp_list.induct)
    44     (blast intro: exprel.intros listrel.intros)+
    44     (blast intro: exprel.intros listrel.intros)+
    65       \<Longrightarrow> FNCALL F (X#Xs) \<sim> FNCALL F (X'#Xs')"
    65       \<Longrightarrow> FNCALL F (X#Xs) \<sim> FNCALL F (X'#Xs')"
    66 by (blast intro: exprel.intros listrel.intros) 
    66 by (blast intro: exprel.intros listrel.intros) 
    67 
    67 
    68 
    68 
    69 
    69 
    70 subsection{*Some Functions on the Free Algebra*}
    70 subsection\<open>Some Functions on the Free Algebra\<close>
    71 
    71 
    72 subsubsection{*The Set of Variables*}
    72 subsubsection\<open>The Set of Variables\<close>
    73 
    73 
    74 text{*A function to return the set of variables present in a message.  It will
    74 text\<open>A function to return the set of variables present in a message.  It will
    75 be lifted to the initial algebra, to serve as an example of that process.
    75 be lifted to the initial algebra, to serve as an example of that process.
    76 Note that the "free" refers to the free datatype rather than to the concept
    76 Note that the "free" refers to the free datatype rather than to the concept
    77 of a free variable.*}
    77 of a free variable.\<close>
    78 primrec freevars :: "freeExp \<Rightarrow> nat set" 
    78 primrec freevars :: "freeExp \<Rightarrow> nat set" 
    79   and freevars_list :: "freeExp list \<Rightarrow> nat set" where
    79   and freevars_list :: "freeExp list \<Rightarrow> nat set" where
    80   "freevars (VAR N) = {N}"
    80   "freevars (VAR N) = {N}"
    81 | "freevars (PLUS X Y) = freevars X \<union> freevars Y"
    81 | "freevars (PLUS X Y) = freevars X \<union> freevars Y"
    82 | "freevars (FNCALL F Xs) = freevars_list Xs"
    82 | "freevars (FNCALL F Xs) = freevars_list Xs"
    83 
    83 
    84 | "freevars_list [] = {}"
    84 | "freevars_list [] = {}"
    85 | "freevars_list (X # Xs) = freevars X \<union> freevars_list Xs"
    85 | "freevars_list (X # Xs) = freevars X \<union> freevars_list Xs"
    86 
    86 
    87 text{*This theorem lets us prove that the vars function respects the
    87 text\<open>This theorem lets us prove that the vars function respects the
    88 equivalence relation.  It also helps us prove that Variable
    88 equivalence relation.  It also helps us prove that Variable
    89   (the abstract constructor) is injective*}
    89   (the abstract constructor) is injective\<close>
    90 theorem exprel_imp_eq_freevars: "U \<sim> V \<Longrightarrow> freevars U = freevars V"
    90 theorem exprel_imp_eq_freevars: "U \<sim> V \<Longrightarrow> freevars U = freevars V"
    91 apply (induct set: exprel) 
    91 apply (induct set: exprel) 
    92 apply (erule_tac [4] listrel.induct) 
    92 apply (erule_tac [4] listrel.induct) 
    93 apply (simp_all add: Un_assoc)
    93 apply (simp_all add: Un_assoc)
    94 done
    94 done
    95 
    95 
    96 
    96 
    97 
    97 
    98 subsubsection{*Functions for Freeness*}
    98 subsubsection\<open>Functions for Freeness\<close>
    99 
    99 
   100 text{*A discriminator function to distinguish vars, sums and function calls*}
   100 text\<open>A discriminator function to distinguish vars, sums and function calls\<close>
   101 primrec freediscrim :: "freeExp \<Rightarrow> int" where
   101 primrec freediscrim :: "freeExp \<Rightarrow> int" where
   102   "freediscrim (VAR N) = 0"
   102   "freediscrim (VAR N) = 0"
   103 | "freediscrim (PLUS X Y) = 1"
   103 | "freediscrim (PLUS X Y) = 1"
   104 | "freediscrim (FNCALL F Xs) = 2"
   104 | "freediscrim (FNCALL F Xs) = 2"
   105 
   105 
   106 theorem exprel_imp_eq_freediscrim:
   106 theorem exprel_imp_eq_freediscrim:
   107      "U \<sim> V \<Longrightarrow> freediscrim U = freediscrim V"
   107      "U \<sim> V \<Longrightarrow> freediscrim U = freediscrim V"
   108   by (induct set: exprel) auto
   108   by (induct set: exprel) auto
   109 
   109 
   110 
   110 
   111 text{*This function, which returns the function name, is used to
   111 text\<open>This function, which returns the function name, is used to
   112 prove part of the injectivity property for FnCall.*}
   112 prove part of the injectivity property for FnCall.\<close>
   113 primrec freefun :: "freeExp \<Rightarrow> nat" where
   113 primrec freefun :: "freeExp \<Rightarrow> nat" where
   114   "freefun (VAR N) = 0"
   114   "freefun (VAR N) = 0"
   115 | "freefun (PLUS X Y) = 0"
   115 | "freefun (PLUS X Y) = 0"
   116 | "freefun (FNCALL F Xs) = F"
   116 | "freefun (FNCALL F Xs) = F"
   117 
   117 
   118 theorem exprel_imp_eq_freefun:
   118 theorem exprel_imp_eq_freefun:
   119      "U \<sim> V \<Longrightarrow> freefun U = freefun V"
   119      "U \<sim> V \<Longrightarrow> freefun U = freefun V"
   120   by (induct set: exprel) (simp_all add: listrel.intros)
   120   by (induct set: exprel) (simp_all add: listrel.intros)
   121 
   121 
   122 
   122 
   123 text{*This function, which returns the list of function arguments, is used to
   123 text\<open>This function, which returns the list of function arguments, is used to
   124 prove part of the injectivity property for FnCall.*}
   124 prove part of the injectivity property for FnCall.\<close>
   125 primrec freeargs :: "freeExp \<Rightarrow> freeExp list" where
   125 primrec freeargs :: "freeExp \<Rightarrow> freeExp list" where
   126   "freeargs (VAR N) = []"
   126   "freeargs (VAR N) = []"
   127 | "freeargs (PLUS X Y) = []"
   127 | "freeargs (PLUS X Y) = []"
   128 | "freeargs (FNCALL F Xs) = Xs"
   128 | "freeargs (FNCALL F Xs) = Xs"
   129 
   129 
   141     apply (blast intro: transD [OF trans])
   141     apply (blast intro: transD [OF trans])
   142     done
   142     done
   143 qed
   143 qed
   144 
   144 
   145 
   145 
   146 subsection{*The Initial Algebra: A Quotiented Message Type*}
   146 subsection\<open>The Initial Algebra: A Quotiented Message Type\<close>
   147 
   147 
   148 definition "Exp = UNIV//exprel"
   148 definition "Exp = UNIV//exprel"
   149 
   149 
   150 typedef exp = Exp
   150 typedef exp = Exp
   151   morphisms Rep_Exp Abs_Exp
   151   morphisms Rep_Exp Abs_Exp
   152   unfolding Exp_def by (auto simp add: quotient_def)
   152   unfolding Exp_def by (auto simp add: quotient_def)
   153 
   153 
   154 text{*The abstract message constructors*}
   154 text\<open>The abstract message constructors\<close>
   155 
   155 
   156 definition
   156 definition
   157   Var :: "nat \<Rightarrow> exp" where
   157   Var :: "nat \<Rightarrow> exp" where
   158   "Var N = Abs_Exp(exprel``{VAR N})"
   158   "Var N = Abs_Exp(exprel``{VAR N})"
   159 
   159 
   166   FnCall :: "[nat, exp list] \<Rightarrow> exp" where
   166   FnCall :: "[nat, exp list] \<Rightarrow> exp" where
   167    "FnCall F Xs =
   167    "FnCall F Xs =
   168        Abs_Exp (\<Union>Us \<in> listset (map Rep_Exp Xs). exprel `` {FNCALL F Us})"
   168        Abs_Exp (\<Union>Us \<in> listset (map Rep_Exp Xs). exprel `` {FNCALL F Us})"
   169 
   169 
   170 
   170 
   171 text{*Reduces equality of equivalence classes to the @{term exprel} relation:
   171 text\<open>Reduces equality of equivalence classes to the @{term exprel} relation:
   172   @{term "(exprel `` {x} = exprel `` {y}) = ((x,y) \<in> exprel)"} *}
   172   @{term "(exprel `` {x} = exprel `` {y}) = ((x,y) \<in> exprel)"}\<close>
   173 lemmas equiv_exprel_iff = eq_equiv_class_iff [OF equiv_exprel UNIV_I UNIV_I]
   173 lemmas equiv_exprel_iff = eq_equiv_class_iff [OF equiv_exprel UNIV_I UNIV_I]
   174 
   174 
   175 declare equiv_exprel_iff [simp]
   175 declare equiv_exprel_iff [simp]
   176 
   176 
   177 
   177 
   178 text{*All equivalence classes belong to set of representatives*}
   178 text\<open>All equivalence classes belong to set of representatives\<close>
   179 lemma [simp]: "exprel``{U} \<in> Exp"
   179 lemma [simp]: "exprel``{U} \<in> Exp"
   180 by (auto simp add: Exp_def quotient_def intro: exprel_refl)
   180 by (auto simp add: Exp_def quotient_def intro: exprel_refl)
   181 
   181 
   182 lemma inj_on_Abs_Exp: "inj_on Abs_Exp Exp"
   182 lemma inj_on_Abs_Exp: "inj_on Abs_Exp Exp"
   183 apply (rule inj_on_inverseI)
   183 apply (rule inj_on_inverseI)
   184 apply (erule Abs_Exp_inverse)
   184 apply (erule Abs_Exp_inverse)
   185 done
   185 done
   186 
   186 
   187 text{*Reduces equality on abstractions to equality on representatives*}
   187 text\<open>Reduces equality on abstractions to equality on representatives\<close>
   188 declare inj_on_Abs_Exp [THEN inj_on_iff, simp]
   188 declare inj_on_Abs_Exp [THEN inj_on_iff, simp]
   189 
   189 
   190 declare Abs_Exp_inverse [simp]
   190 declare Abs_Exp_inverse [simp]
   191 
   191 
   192 
   192 
   193 text{*Case analysis on the representation of a exp as an equivalence class.*}
   193 text\<open>Case analysis on the representation of a exp as an equivalence class.\<close>
   194 lemma eq_Abs_Exp [case_names Abs_Exp, cases type: exp]:
   194 lemma eq_Abs_Exp [case_names Abs_Exp, cases type: exp]:
   195      "(!!U. z = Abs_Exp(exprel``{U}) ==> P) ==> P"
   195      "(!!U. z = Abs_Exp(exprel``{U}) ==> P) ==> P"
   196 apply (rule Rep_Exp [of z, unfolded Exp_def, THEN quotientE])
   196 apply (rule Rep_Exp [of z, unfolded Exp_def, THEN quotientE])
   197 apply (drule arg_cong [where f=Abs_Exp])
   197 apply (drule arg_cong [where f=Abs_Exp])
   198 apply (auto simp add: Rep_Exp_inverse intro: exprel_refl)
   198 apply (auto simp add: Rep_Exp_inverse intro: exprel_refl)
   199 done
   199 done
   200 
   200 
   201 
   201 
   202 subsection{*Every list of abstract expressions can be expressed in terms of a
   202 subsection\<open>Every list of abstract expressions can be expressed in terms of a
   203   list of concrete expressions*}
   203   list of concrete expressions\<close>
   204 
   204 
   205 definition
   205 definition
   206   Abs_ExpList :: "freeExp list => exp list" where
   206   Abs_ExpList :: "freeExp list => exp list" where
   207   "Abs_ExpList Xs = map (%U. Abs_Exp(exprel``{U})) Xs"
   207   "Abs_ExpList Xs = map (%U. Abs_Exp(exprel``{U})) Xs"
   208 
   208 
   223 lemma eq_Abs_ExpList [case_names Abs_ExpList]:
   223 lemma eq_Abs_ExpList [case_names Abs_ExpList]:
   224      "(!!Us. z = Abs_ExpList Us ==> P) ==> P"
   224      "(!!Us. z = Abs_ExpList Us ==> P) ==> P"
   225 by (rule exE [OF ExpList_rep], blast) 
   225 by (rule exE [OF ExpList_rep], blast) 
   226 
   226 
   227 
   227 
   228 subsubsection{*Characteristic Equations for the Abstract Constructors*}
   228 subsubsection\<open>Characteristic Equations for the Abstract Constructors\<close>
   229 
   229 
   230 lemma Plus: "Plus (Abs_Exp(exprel``{U})) (Abs_Exp(exprel``{V})) = 
   230 lemma Plus: "Plus (Abs_Exp(exprel``{U})) (Abs_Exp(exprel``{V})) = 
   231              Abs_Exp (exprel``{PLUS U V})"
   231              Abs_Exp (exprel``{PLUS U V})"
   232 proof -
   232 proof -
   233   have "(\<lambda>U V. exprel `` {PLUS U V}) respects2 exprel"
   233   have "(\<lambda>U V. exprel `` {PLUS U V}) respects2 exprel"
   234     by (auto simp add: congruent2_def exprel.PLUS)
   234     by (auto simp add: congruent2_def exprel.PLUS)
   235   thus ?thesis
   235   thus ?thesis
   236     by (simp add: Plus_def UN_equiv_class2 [OF equiv_exprel equiv_exprel])
   236     by (simp add: Plus_def UN_equiv_class2 [OF equiv_exprel equiv_exprel])
   237 qed
   237 qed
   238 
   238 
   239 text{*It is not clear what to do with FnCall: it's argument is an abstraction
   239 text\<open>It is not clear what to do with FnCall: it's argument is an abstraction
   240 of an @{typ "exp list"}. Is it just Nil or Cons? What seems to work best is to
   240 of an @{typ "exp list"}. Is it just Nil or Cons? What seems to work best is to
   241 regard an @{typ "exp list"} as a @{term "listrel exprel"} equivalence class*}
   241 regard an @{typ "exp list"} as a @{term "listrel exprel"} equivalence class\<close>
   242 
   242 
   243 text{*This theorem is easily proved but never used. There's no obvious way
   243 text\<open>This theorem is easily proved but never used. There's no obvious way
   244 even to state the analogous result, @{text FnCall_Cons}.*}
   244 even to state the analogous result, @{text FnCall_Cons}.\<close>
   245 lemma FnCall_Nil: "FnCall F [] = Abs_Exp (exprel``{FNCALL F []})"
   245 lemma FnCall_Nil: "FnCall F [] = Abs_Exp (exprel``{FNCALL F []})"
   246   by (simp add: FnCall_def)
   246   by (simp add: FnCall_def)
   247 
   247 
   248 lemma FnCall_respects: 
   248 lemma FnCall_respects: 
   249      "(\<lambda>Us. exprel `` {FNCALL F Us}) respects (listrel exprel)"
   249      "(\<lambda>Us. exprel `` {FNCALL F Us}) respects (listrel exprel)"
   271     by (simp add: FnCall_def UN_equiv_class [OF equiv_list_exprel]
   271     by (simp add: FnCall_def UN_equiv_class [OF equiv_list_exprel]
   272                   listset_Rep_Exp_Abs_Exp)
   272                   listset_Rep_Exp_Abs_Exp)
   273 qed
   273 qed
   274 
   274 
   275 
   275 
   276 text{*Establishing this equation is the point of the whole exercise*}
   276 text\<open>Establishing this equation is the point of the whole exercise\<close>
   277 theorem Plus_assoc: "Plus X (Plus Y Z) = Plus (Plus X Y) Z"
   277 theorem Plus_assoc: "Plus X (Plus Y Z) = Plus (Plus X Y) Z"
   278 by (cases X, cases Y, cases Z, simp add: Plus exprel.ASSOC)
   278 by (cases X, cases Y, cases Z, simp add: Plus exprel.ASSOC)
   279 
   279 
   280 
   280 
   281 
   281 
   282 subsection{*The Abstract Function to Return the Set of Variables*}
   282 subsection\<open>The Abstract Function to Return the Set of Variables\<close>
   283 
   283 
   284 definition
   284 definition
   285   vars :: "exp \<Rightarrow> nat set" where
   285   vars :: "exp \<Rightarrow> nat set" where
   286   "vars X = (\<Union>U \<in> Rep_Exp X. freevars U)"
   286   "vars X = (\<Union>U \<in> Rep_Exp X. freevars U)"
   287 
   287 
   288 lemma vars_respects: "freevars respects exprel"
   288 lemma vars_respects: "freevars respects exprel"
   289 by (auto simp add: congruent_def exprel_imp_eq_freevars) 
   289 by (auto simp add: congruent_def exprel_imp_eq_freevars) 
   290 
   290 
   291 text{*The extension of the function @{term vars} to lists*}
   291 text\<open>The extension of the function @{term vars} to lists\<close>
   292 primrec vars_list :: "exp list \<Rightarrow> nat set" where
   292 primrec vars_list :: "exp list \<Rightarrow> nat set" where
   293   "vars_list []    = {}"
   293   "vars_list []    = {}"
   294 | "vars_list(E#Es) = vars E \<union> vars_list Es"
   294 | "vars_list(E#Es) = vars E \<union> vars_list Es"
   295 
   295 
   296 
   296 
   297 text{*Now prove the three equations for @{term vars}*}
   297 text\<open>Now prove the three equations for @{term vars}\<close>
   298 
   298 
   299 lemma vars_Variable [simp]: "vars (Var N) = {N}"
   299 lemma vars_Variable [simp]: "vars (Var N) = {N}"
   300 by (simp add: vars_def Var_def 
   300 by (simp add: vars_def Var_def 
   301               UN_equiv_class [OF equiv_exprel vars_respects]) 
   301               UN_equiv_class [OF equiv_exprel vars_respects]) 
   302  
   302  
   318 
   318 
   319 lemma vars_FnCall_Cons: "vars (FnCall F (X#Xs)) = vars X \<union> vars_list Xs"
   319 lemma vars_FnCall_Cons: "vars (FnCall F (X#Xs)) = vars X \<union> vars_list Xs"
   320 by simp
   320 by simp
   321 
   321 
   322 
   322 
   323 subsection{*Injectivity Properties of Some Constructors*}
   323 subsection\<open>Injectivity Properties of Some Constructors\<close>
   324 
   324 
   325 lemma VAR_imp_eq: "VAR m \<sim> VAR n \<Longrightarrow> m = n"
   325 lemma VAR_imp_eq: "VAR m \<sim> VAR n \<Longrightarrow> m = n"
   326 by (drule exprel_imp_eq_freevars, simp)
   326 by (drule exprel_imp_eq_freevars, simp)
   327 
   327 
   328 text{*Can also be proved using the function @{term vars}*}
   328 text\<open>Can also be proved using the function @{term vars}\<close>
   329 lemma Var_Var_eq [iff]: "(Var m = Var n) = (m = n)"
   329 lemma Var_Var_eq [iff]: "(Var m = Var n) = (m = n)"
   330 by (auto simp add: Var_def exprel_refl dest: VAR_imp_eq)
   330 by (auto simp add: Var_def exprel_refl dest: VAR_imp_eq)
   331 
   331 
   332 lemma VAR_neqv_PLUS: "VAR m \<sim> PLUS X Y \<Longrightarrow> False"
   332 lemma VAR_neqv_PLUS: "VAR m \<sim> PLUS X Y \<Longrightarrow> False"
   333 by (drule exprel_imp_eq_freediscrim, simp)
   333 by (drule exprel_imp_eq_freediscrim, simp)
   342 apply (cases Xs rule: eq_Abs_ExpList) 
   342 apply (cases Xs rule: eq_Abs_ExpList) 
   343 apply (auto simp add: FnCall Var_def)
   343 apply (auto simp add: FnCall Var_def)
   344 apply (drule exprel_imp_eq_freediscrim, simp)
   344 apply (drule exprel_imp_eq_freediscrim, simp)
   345 done
   345 done
   346 
   346 
   347 subsection{*Injectivity of @{term FnCall}*}
   347 subsection\<open>Injectivity of @{term FnCall}\<close>
   348 
   348 
   349 definition
   349 definition
   350   "fun" :: "exp \<Rightarrow> nat" where
   350   "fun" :: "exp \<Rightarrow> nat" where
   351   "fun X = the_elem (\<Union>U \<in> Rep_Exp X. {freefun U})"
   351   "fun X = the_elem (\<Union>U \<in> Rep_Exp X. {freefun U})"
   352 
   352 
   360 
   360 
   361 definition
   361 definition
   362   args :: "exp \<Rightarrow> exp list" where
   362   args :: "exp \<Rightarrow> exp list" where
   363   "args X = the_elem (\<Union>U \<in> Rep_Exp X. {Abs_ExpList (freeargs U)})"
   363   "args X = the_elem (\<Union>U \<in> Rep_Exp X. {Abs_ExpList (freeargs U)})"
   364 
   364 
   365 text{*This result can probably be generalized to arbitrary equivalence
   365 text\<open>This result can probably be generalized to arbitrary equivalence
   366 relations, but with little benefit here.*}
   366 relations, but with little benefit here.\<close>
   367 lemma Abs_ExpList_eq:
   367 lemma Abs_ExpList_eq:
   368      "(y, z) \<in> listrel exprel \<Longrightarrow> Abs_ExpList (y) = Abs_ExpList (z)"
   368      "(y, z) \<in> listrel exprel \<Longrightarrow> Abs_ExpList (y) = Abs_ExpList (z)"
   369   by (induct set: listrel) simp_all
   369   by (induct set: listrel) simp_all
   370 
   370 
   371 lemma args_respects: "(%U. {Abs_ExpList (freeargs U)}) respects exprel"
   371 lemma args_respects: "(%U. {Abs_ExpList (freeargs U)}) respects exprel"
   387 next
   387 next
   388   assume "F=F' & Xs=Xs'" thus "FnCall F Xs = FnCall F' Xs'" by simp
   388   assume "F=F' & Xs=Xs'" thus "FnCall F Xs = FnCall F' Xs'" by simp
   389 qed
   389 qed
   390 
   390 
   391 
   391 
   392 subsection{*The Abstract Discriminator*}
   392 subsection\<open>The Abstract Discriminator\<close>
   393 text{*However, as @{text FnCall_Var_neq_Var} illustrates, we don't need this
   393 text\<open>However, as @{text FnCall_Var_neq_Var} illustrates, we don't need this
   394 function in order to prove discrimination theorems.*}
   394 function in order to prove discrimination theorems.\<close>
   395 
   395 
   396 definition
   396 definition
   397   discrim :: "exp \<Rightarrow> int" where
   397   discrim :: "exp \<Rightarrow> int" where
   398   "discrim X = the_elem (\<Union>U \<in> Rep_Exp X. {freediscrim U})"
   398   "discrim X = the_elem (\<Union>U \<in> Rep_Exp X. {freediscrim U})"
   399 
   399 
   400 lemma discrim_respects: "(\<lambda>U. {freediscrim U}) respects exprel"
   400 lemma discrim_respects: "(\<lambda>U. {freediscrim U}) respects exprel"
   401 by (auto simp add: congruent_def exprel_imp_eq_freediscrim) 
   401 by (auto simp add: congruent_def exprel_imp_eq_freediscrim) 
   402 
   402 
   403 text{*Now prove the four equations for @{term discrim}*}
   403 text\<open>Now prove the four equations for @{term discrim}\<close>
   404 
   404 
   405 lemma discrim_Var [simp]: "discrim (Var N) = 0"
   405 lemma discrim_Var [simp]: "discrim (Var N) = 0"
   406 by (simp add: discrim_def Var_def 
   406 by (simp add: discrim_def Var_def 
   407               UN_equiv_class [OF equiv_exprel discrim_respects]) 
   407               UN_equiv_class [OF equiv_exprel discrim_respects]) 
   408 
   408 
   417 apply (simp add: discrim_def FnCall
   417 apply (simp add: discrim_def FnCall
   418                  UN_equiv_class [OF equiv_exprel discrim_respects]) 
   418                  UN_equiv_class [OF equiv_exprel discrim_respects]) 
   419 done
   419 done
   420 
   420 
   421 
   421 
   422 text{*The structural induction rule for the abstract type*}
   422 text\<open>The structural induction rule for the abstract type\<close>
   423 theorem exp_inducts:
   423 theorem exp_inducts:
   424   assumes V:    "\<And>nat. P1 (Var nat)"
   424   assumes V:    "\<And>nat. P1 (Var nat)"
   425       and P:    "\<And>exp1 exp2. \<lbrakk>P1 exp1; P1 exp2\<rbrakk> \<Longrightarrow> P1 (Plus exp1 exp2)"
   425       and P:    "\<And>exp1 exp2. \<lbrakk>P1 exp1; P1 exp2\<rbrakk> \<Longrightarrow> P1 (Plus exp1 exp2)"
   426       and F:    "\<And>nat list. P2 list \<Longrightarrow> P1 (FnCall nat list)"
   426       and F:    "\<And>nat list. P2 list \<Longrightarrow> P1 (FnCall nat list)"
   427       and Nil:  "P2 []"
   427       and Nil:  "P2 []"