| 15172 |      1 | (*  Title:      HOL/Induct/QuoNestedDataType
 | 
|  |      2 |     ID:         $Id$
 | 
|  |      3 |     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
 | 
|  |      4 |     Copyright   2004  University of Cambridge
 | 
|  |      5 | 
 | 
|  |      6 | *)
 | 
|  |      7 | 
 | 
|  |      8 | header{*Quotienting a Free Algebra Involving Nested Recursion*}
 | 
|  |      9 | 
 | 
| 16417 |     10 | theory QuoNestedDataType imports Main begin
 | 
| 15172 |     11 | 
 | 
|  |     12 | subsection{*Defining the Free Algebra*}
 | 
|  |     13 | 
 | 
|  |     14 | text{*Messages with encryption and decryption as free constructors.*}
 | 
|  |     15 | datatype
 | 
|  |     16 |      freeExp = VAR  nat
 | 
|  |     17 | 	     | PLUS  freeExp freeExp
 | 
|  |     18 | 	     | FNCALL  nat "freeExp list"
 | 
|  |     19 | 
 | 
|  |     20 | text{*The equivalence relation, which makes PLUS associative.*}
 | 
|  |     21 | consts  exprel :: "(freeExp * freeExp) set"
 | 
|  |     22 | 
 | 
| 19736 |     23 | abbreviation
 | 
|  |     24 |   exp_rel :: "[freeExp, freeExp] => bool"  (infixl "~~" 50)
 | 
|  |     25 |   "X ~~ Y == (X,Y) \<in> exprel"
 | 
|  |     26 | 
 | 
|  |     27 | const_syntax (xsymbols)
 | 
|  |     28 |   exp_rel  (infixl "\<sim>" 50)
 | 
|  |     29 | const_syntax (HTML output)
 | 
|  |     30 |   exp_rel  (infixl "\<sim>" 50)
 | 
| 15172 |     31 | 
 | 
|  |     32 | text{*The first rule is the desired equation. The next three rules
 | 
|  |     33 | make the equations applicable to subterms. The last two rules are symmetry
 | 
|  |     34 | and transitivity.*}
 | 
|  |     35 | inductive "exprel"
 | 
|  |     36 |   intros 
 | 
|  |     37 |     ASSOC: "PLUS X (PLUS Y Z) \<sim> PLUS (PLUS X Y) Z"
 | 
|  |     38 |     VAR: "VAR N \<sim> VAR N"
 | 
|  |     39 |     PLUS: "\<lbrakk>X \<sim> X'; Y \<sim> Y'\<rbrakk> \<Longrightarrow> PLUS X Y \<sim> PLUS X' Y'"
 | 
|  |     40 |     FNCALL: "(Xs,Xs') \<in> listrel exprel \<Longrightarrow> FNCALL F Xs \<sim> FNCALL F Xs'"
 | 
|  |     41 |     SYM:   "X \<sim> Y \<Longrightarrow> Y \<sim> X"
 | 
|  |     42 |     TRANS: "\<lbrakk>X \<sim> Y; Y \<sim> Z\<rbrakk> \<Longrightarrow> X \<sim> Z"
 | 
|  |     43 |   monos listrel_mono
 | 
|  |     44 | 
 | 
|  |     45 | 
 | 
|  |     46 | text{*Proving that it is an equivalence relation*}
 | 
|  |     47 | 
 | 
| 18460 |     48 | lemma exprel_refl: "X \<sim> X"
 | 
|  |     49 |   and list_exprel_refl: "(Xs,Xs) \<in> listrel(exprel)"
 | 
|  |     50 |   by (induct X and Xs) (blast intro: exprel.intros listrel.intros)+
 | 
| 15172 |     51 | 
 | 
|  |     52 | theorem equiv_exprel: "equiv UNIV exprel"
 | 
| 18460 |     53 | proof -
 | 
|  |     54 |   have "reflexive exprel" by (simp add: refl_def exprel_refl)
 | 
|  |     55 |   moreover have "sym exprel" by (simp add: sym_def, blast intro: exprel.SYM)
 | 
|  |     56 |   moreover have "trans exprel" by (simp add: trans_def, blast intro: exprel.TRANS)
 | 
|  |     57 |   ultimately show ?thesis by (simp add: equiv_def)
 | 
| 15172 |     58 | qed
 | 
|  |     59 | 
 | 
|  |     60 | theorem equiv_list_exprel: "equiv UNIV (listrel exprel)"
 | 
| 18460 |     61 |   using equiv_listrel [OF equiv_exprel] by simp
 | 
| 15172 |     62 | 
 | 
|  |     63 | 
 | 
|  |     64 | lemma FNCALL_Nil: "FNCALL F [] \<sim> FNCALL F []"
 | 
|  |     65 | apply (rule exprel.intros) 
 | 
|  |     66 | apply (rule listrel.intros) 
 | 
|  |     67 | done
 | 
|  |     68 | 
 | 
|  |     69 | lemma FNCALL_Cons:
 | 
|  |     70 |      "\<lbrakk>X \<sim> X'; (Xs,Xs') \<in> listrel(exprel)\<rbrakk>
 | 
|  |     71 |       \<Longrightarrow> FNCALL F (X#Xs) \<sim> FNCALL F (X'#Xs')"
 | 
|  |     72 | by (blast intro: exprel.intros listrel.intros) 
 | 
|  |     73 | 
 | 
|  |     74 | 
 | 
|  |     75 | 
 | 
|  |     76 | subsection{*Some Functions on the Free Algebra*}
 | 
|  |     77 | 
 | 
|  |     78 | subsubsection{*The Set of Variables*}
 | 
|  |     79 | 
 | 
|  |     80 | text{*A function to return the set of variables present in a message.  It will
 | 
|  |     81 | be lifted to the initial algrebra, to serve as an example of that process.
 | 
|  |     82 | Note that the "free" refers to the free datatype rather than to the concept
 | 
|  |     83 | of a free variable.*}
 | 
|  |     84 | consts
 | 
|  |     85 |   freevars      :: "freeExp \<Rightarrow> nat set"
 | 
|  |     86 |   freevars_list :: "freeExp list \<Rightarrow> nat set"
 | 
|  |     87 | 
 | 
|  |     88 | primrec
 | 
|  |     89 |    "freevars (VAR N) = {N}"
 | 
|  |     90 |    "freevars (PLUS X Y) = freevars X \<union> freevars Y"
 | 
|  |     91 |    "freevars (FNCALL F Xs) = freevars_list Xs"
 | 
|  |     92 | 
 | 
|  |     93 |    "freevars_list [] = {}"
 | 
|  |     94 |    "freevars_list (X # Xs) = freevars X \<union> freevars_list Xs"
 | 
|  |     95 | 
 | 
|  |     96 | text{*This theorem lets us prove that the vars function respects the
 | 
|  |     97 | equivalence relation.  It also helps us prove that Variable
 | 
|  |     98 |   (the abstract constructor) is injective*}
 | 
|  |     99 | theorem exprel_imp_eq_freevars: "U \<sim> V \<Longrightarrow> freevars U = freevars V"
 | 
| 18460 |    100 | apply (induct set: exprel) 
 | 
| 15172 |    101 | apply (erule_tac [4] listrel.induct) 
 | 
|  |    102 | apply (simp_all add: Un_assoc)
 | 
|  |    103 | done
 | 
|  |    104 | 
 | 
|  |    105 | 
 | 
|  |    106 | 
 | 
|  |    107 | subsubsection{*Functions for Freeness*}
 | 
|  |    108 | 
 | 
|  |    109 | text{*A discriminator function to distinguish vars, sums and function calls*}
 | 
|  |    110 | consts freediscrim :: "freeExp \<Rightarrow> int"
 | 
|  |    111 | primrec
 | 
|  |    112 |    "freediscrim (VAR N) = 0"
 | 
|  |    113 |    "freediscrim (PLUS X Y) = 1"
 | 
|  |    114 |    "freediscrim (FNCALL F Xs) = 2"
 | 
|  |    115 | 
 | 
|  |    116 | theorem exprel_imp_eq_freediscrim:
 | 
|  |    117 |      "U \<sim> V \<Longrightarrow> freediscrim U = freediscrim V"
 | 
| 18460 |    118 |   by (induct set: exprel) auto
 | 
| 15172 |    119 | 
 | 
|  |    120 | 
 | 
|  |    121 | text{*This function, which returns the function name, is used to
 | 
|  |    122 | prove part of the injectivity property for FnCall.*}
 | 
|  |    123 | consts  freefun :: "freeExp \<Rightarrow> nat"
 | 
|  |    124 | 
 | 
|  |    125 | primrec
 | 
|  |    126 |    "freefun (VAR N) = 0"
 | 
|  |    127 |    "freefun (PLUS X Y) = 0"
 | 
|  |    128 |    "freefun (FNCALL F Xs) = F"
 | 
|  |    129 | 
 | 
|  |    130 | theorem exprel_imp_eq_freefun:
 | 
|  |    131 |      "U \<sim> V \<Longrightarrow> freefun U = freefun V"
 | 
| 18460 |    132 |   by (induct set: exprel) (simp_all add: listrel.intros)
 | 
| 15172 |    133 | 
 | 
|  |    134 | 
 | 
|  |    135 | text{*This function, which returns the list of function arguments, is used to
 | 
|  |    136 | prove part of the injectivity property for FnCall.*}
 | 
|  |    137 | consts  freeargs      :: "freeExp \<Rightarrow> freeExp list"
 | 
|  |    138 | primrec
 | 
|  |    139 |    "freeargs (VAR N) = []"
 | 
|  |    140 |    "freeargs (PLUS X Y) = []"
 | 
|  |    141 |    "freeargs (FNCALL F Xs) = Xs"
 | 
|  |    142 | 
 | 
|  |    143 | theorem exprel_imp_eqv_freeargs:
 | 
|  |    144 |      "U \<sim> V \<Longrightarrow> (freeargs U, freeargs V) \<in> listrel exprel"
 | 
| 18460 |    145 | apply (induct set: exprel)
 | 
| 15172 |    146 | apply (erule_tac [4] listrel.induct) 
 | 
|  |    147 | apply (simp_all add: listrel.intros)
 | 
|  |    148 | apply (blast intro: symD [OF equiv.sym [OF equiv_list_exprel]])
 | 
|  |    149 | apply (blast intro: transD [OF equiv.trans [OF equiv_list_exprel]])
 | 
|  |    150 | done
 | 
|  |    151 | 
 | 
|  |    152 | 
 | 
|  |    153 | 
 | 
|  |    154 | subsection{*The Initial Algebra: A Quotiented Message Type*}
 | 
|  |    155 | 
 | 
|  |    156 | 
 | 
|  |    157 | typedef (Exp)  exp = "UNIV//exprel"
 | 
|  |    158 |     by (auto simp add: quotient_def)
 | 
|  |    159 | 
 | 
|  |    160 | text{*The abstract message constructors*}
 | 
|  |    161 | 
 | 
| 19736 |    162 | definition
 | 
| 15172 |    163 |   Var :: "nat \<Rightarrow> exp"
 | 
| 19736 |    164 |   "Var N = Abs_Exp(exprel``{VAR N})"
 | 
| 15172 |    165 | 
 | 
|  |    166 |   Plus :: "[exp,exp] \<Rightarrow> exp"
 | 
| 19736 |    167 |    "Plus X Y =
 | 
| 15172 |    168 |        Abs_Exp (\<Union>U \<in> Rep_Exp X. \<Union>V \<in> Rep_Exp Y. exprel``{PLUS U V})"
 | 
|  |    169 | 
 | 
|  |    170 |   FnCall :: "[nat, exp list] \<Rightarrow> exp"
 | 
| 19736 |    171 |    "FnCall F Xs =
 | 
| 15172 |    172 |        Abs_Exp (\<Union>Us \<in> listset (map Rep_Exp Xs). exprel `` {FNCALL F Us})"
 | 
|  |    173 | 
 | 
|  |    174 | 
 | 
|  |    175 | text{*Reduces equality of equivalence classes to the @{term exprel} relation:
 | 
|  |    176 |   @{term "(exprel `` {x} = exprel `` {y}) = ((x,y) \<in> exprel)"} *}
 | 
|  |    177 | lemmas equiv_exprel_iff = eq_equiv_class_iff [OF equiv_exprel UNIV_I UNIV_I]
 | 
|  |    178 | 
 | 
|  |    179 | declare equiv_exprel_iff [simp]
 | 
|  |    180 | 
 | 
|  |    181 | 
 | 
|  |    182 | text{*All equivalence classes belong to set of representatives*}
 | 
|  |    183 | lemma [simp]: "exprel``{U} \<in> Exp"
 | 
|  |    184 | by (auto simp add: Exp_def quotient_def intro: exprel_refl)
 | 
|  |    185 | 
 | 
|  |    186 | lemma inj_on_Abs_Exp: "inj_on Abs_Exp Exp"
 | 
|  |    187 | apply (rule inj_on_inverseI)
 | 
|  |    188 | apply (erule Abs_Exp_inverse)
 | 
|  |    189 | done
 | 
|  |    190 | 
 | 
|  |    191 | text{*Reduces equality on abstractions to equality on representatives*}
 | 
|  |    192 | declare inj_on_Abs_Exp [THEN inj_on_iff, simp]
 | 
|  |    193 | 
 | 
|  |    194 | declare Abs_Exp_inverse [simp]
 | 
|  |    195 | 
 | 
|  |    196 | 
 | 
|  |    197 | text{*Case analysis on the representation of a exp as an equivalence class.*}
 | 
|  |    198 | lemma eq_Abs_Exp [case_names Abs_Exp, cases type: exp]:
 | 
|  |    199 |      "(!!U. z = Abs_Exp(exprel``{U}) ==> P) ==> P"
 | 
|  |    200 | apply (rule Rep_Exp [of z, unfolded Exp_def, THEN quotientE])
 | 
|  |    201 | apply (drule arg_cong [where f=Abs_Exp])
 | 
|  |    202 | apply (auto simp add: Rep_Exp_inverse intro: exprel_refl)
 | 
|  |    203 | done
 | 
|  |    204 | 
 | 
|  |    205 | 
 | 
|  |    206 | subsection{*Every list of abstract expressions can be expressed in terms of a
 | 
|  |    207 |   list of concrete expressions*}
 | 
|  |    208 | 
 | 
| 19736 |    209 | definition
 | 
|  |    210 |   Abs_ExpList :: "freeExp list => exp list"
 | 
|  |    211 |   "Abs_ExpList Xs = map (%U. Abs_Exp(exprel``{U})) Xs"
 | 
| 15172 |    212 | 
 | 
|  |    213 | lemma Abs_ExpList_Nil [simp]: "Abs_ExpList [] == []"
 | 
|  |    214 | by (simp add: Abs_ExpList_def)
 | 
|  |    215 | 
 | 
|  |    216 | lemma Abs_ExpList_Cons [simp]:
 | 
|  |    217 |      "Abs_ExpList (X#Xs) == Abs_Exp (exprel``{X}) # Abs_ExpList Xs"
 | 
|  |    218 | by (simp add: Abs_ExpList_def)
 | 
|  |    219 | 
 | 
|  |    220 | lemma ExpList_rep: "\<exists>Us. z = Abs_ExpList Us"
 | 
|  |    221 | apply (induct z)
 | 
|  |    222 | apply (rule_tac [2] z=a in eq_Abs_Exp)
 | 
| 18447 |    223 | apply (auto simp add: Abs_ExpList_def Cons_eq_map_conv intro: exprel_refl)
 | 
| 15172 |    224 | done
 | 
|  |    225 | 
 | 
|  |    226 | lemma eq_Abs_ExpList [case_names Abs_ExpList]:
 | 
|  |    227 |      "(!!Us. z = Abs_ExpList Us ==> P) ==> P"
 | 
|  |    228 | by (rule exE [OF ExpList_rep], blast) 
 | 
|  |    229 | 
 | 
|  |    230 | 
 | 
|  |    231 | subsubsection{*Characteristic Equations for the Abstract Constructors*}
 | 
|  |    232 | 
 | 
|  |    233 | lemma Plus: "Plus (Abs_Exp(exprel``{U})) (Abs_Exp(exprel``{V})) = 
 | 
|  |    234 |              Abs_Exp (exprel``{PLUS U V})"
 | 
|  |    235 | proof -
 | 
|  |    236 |   have "(\<lambda>U V. exprel `` {PLUS U V}) respects2 exprel"
 | 
|  |    237 |     by (simp add: congruent2_def exprel.PLUS)
 | 
|  |    238 |   thus ?thesis
 | 
|  |    239 |     by (simp add: Plus_def UN_equiv_class2 [OF equiv_exprel equiv_exprel])
 | 
|  |    240 | qed
 | 
|  |    241 | 
 | 
|  |    242 | text{*It is not clear what to do with FnCall: it's argument is an abstraction
 | 
|  |    243 | of an @{typ "exp list"}. Is it just Nil or Cons? What seems to work best is to
 | 
|  |    244 | regard an @{typ "exp list"} as a @{term "listrel exprel"} equivalence class*}
 | 
|  |    245 | 
 | 
|  |    246 | text{*This theorem is easily proved but never used. There's no obvious way
 | 
|  |    247 | even to state the analogous result, @{text FnCall_Cons}.*}
 | 
|  |    248 | lemma FnCall_Nil: "FnCall F [] = Abs_Exp (exprel``{FNCALL F []})"
 | 
|  |    249 |   by (simp add: FnCall_def)
 | 
|  |    250 | 
 | 
|  |    251 | lemma FnCall_respects: 
 | 
|  |    252 |      "(\<lambda>Us. exprel `` {FNCALL F Us}) respects (listrel exprel)"
 | 
|  |    253 |   by (simp add: congruent_def exprel.FNCALL)
 | 
|  |    254 | 
 | 
|  |    255 | lemma FnCall_sing:
 | 
|  |    256 |      "FnCall F [Abs_Exp(exprel``{U})] = Abs_Exp (exprel``{FNCALL F [U]})"
 | 
|  |    257 | proof -
 | 
|  |    258 |   have "(\<lambda>U. exprel `` {FNCALL F [U]}) respects exprel"
 | 
|  |    259 |     by (simp add: congruent_def FNCALL_Cons listrel.intros)
 | 
|  |    260 |   thus ?thesis
 | 
|  |    261 |     by (simp add: FnCall_def UN_equiv_class [OF equiv_exprel])
 | 
|  |    262 | qed
 | 
|  |    263 | 
 | 
|  |    264 | lemma listset_Rep_Exp_Abs_Exp:
 | 
|  |    265 |      "listset (map Rep_Exp (Abs_ExpList Us)) = listrel exprel `` {Us}";
 | 
| 18460 |    266 |   by (induct Us) (simp_all add: listrel_Cons Abs_ExpList_def)
 | 
| 15172 |    267 | 
 | 
|  |    268 | lemma FnCall:
 | 
|  |    269 |      "FnCall F (Abs_ExpList Us) = Abs_Exp (exprel``{FNCALL F Us})"
 | 
|  |    270 | proof -
 | 
|  |    271 |   have "(\<lambda>Us. exprel `` {FNCALL F Us}) respects (listrel exprel)"
 | 
|  |    272 |     by (simp add: congruent_def exprel.FNCALL)
 | 
|  |    273 |   thus ?thesis
 | 
|  |    274 |     by (simp add: FnCall_def UN_equiv_class [OF equiv_list_exprel]
 | 
|  |    275 |                   listset_Rep_Exp_Abs_Exp)
 | 
|  |    276 | qed
 | 
|  |    277 | 
 | 
|  |    278 | 
 | 
|  |    279 | text{*Establishing this equation is the point of the whole exercise*}
 | 
|  |    280 | theorem Plus_assoc: "Plus X (Plus Y Z) = Plus (Plus X Y) Z"
 | 
|  |    281 | by (cases X, cases Y, cases Z, simp add: Plus exprel.ASSOC)
 | 
|  |    282 | 
 | 
|  |    283 | 
 | 
|  |    284 | 
 | 
|  |    285 | subsection{*The Abstract Function to Return the Set of Variables*}
 | 
|  |    286 | 
 | 
| 19736 |    287 | definition
 | 
| 15172 |    288 |   vars :: "exp \<Rightarrow> nat set"
 | 
| 19736 |    289 |   "vars X = (\<Union>U \<in> Rep_Exp X. freevars U)"
 | 
| 15172 |    290 | 
 | 
|  |    291 | lemma vars_respects: "freevars respects exprel"
 | 
|  |    292 | by (simp add: congruent_def exprel_imp_eq_freevars) 
 | 
|  |    293 | 
 | 
|  |    294 | text{*The extension of the function @{term vars} to lists*}
 | 
|  |    295 | consts vars_list :: "exp list \<Rightarrow> nat set"
 | 
|  |    296 | primrec
 | 
|  |    297 |    "vars_list []    = {}"
 | 
|  |    298 |    "vars_list(E#Es) = vars E \<union> vars_list Es"
 | 
|  |    299 | 
 | 
|  |    300 | 
 | 
|  |    301 | text{*Now prove the three equations for @{term vars}*}
 | 
|  |    302 | 
 | 
|  |    303 | lemma vars_Variable [simp]: "vars (Var N) = {N}"
 | 
|  |    304 | by (simp add: vars_def Var_def 
 | 
|  |    305 |               UN_equiv_class [OF equiv_exprel vars_respects]) 
 | 
|  |    306 |  
 | 
|  |    307 | lemma vars_Plus [simp]: "vars (Plus X Y) = vars X \<union> vars Y"
 | 
|  |    308 | apply (cases X, cases Y) 
 | 
|  |    309 | apply (simp add: vars_def Plus 
 | 
|  |    310 |                  UN_equiv_class [OF equiv_exprel vars_respects]) 
 | 
|  |    311 | done
 | 
|  |    312 | 
 | 
|  |    313 | lemma vars_FnCall [simp]: "vars (FnCall F Xs) = vars_list Xs"
 | 
|  |    314 | apply (cases Xs rule: eq_Abs_ExpList) 
 | 
|  |    315 | apply (simp add: FnCall)
 | 
|  |    316 | apply (induct_tac Us) 
 | 
|  |    317 | apply (simp_all add: vars_def UN_equiv_class [OF equiv_exprel vars_respects])
 | 
|  |    318 | done
 | 
|  |    319 | 
 | 
|  |    320 | lemma vars_FnCall_Nil: "vars (FnCall F Nil) = {}" 
 | 
|  |    321 | by simp
 | 
|  |    322 | 
 | 
|  |    323 | lemma vars_FnCall_Cons: "vars (FnCall F (X#Xs)) = vars X \<union> vars_list Xs"
 | 
|  |    324 | by simp
 | 
|  |    325 | 
 | 
|  |    326 | 
 | 
|  |    327 | subsection{*Injectivity Properties of Some Constructors*}
 | 
|  |    328 | 
 | 
|  |    329 | lemma VAR_imp_eq: "VAR m \<sim> VAR n \<Longrightarrow> m = n"
 | 
|  |    330 | by (drule exprel_imp_eq_freevars, simp)
 | 
|  |    331 | 
 | 
|  |    332 | text{*Can also be proved using the function @{term vars}*}
 | 
|  |    333 | lemma Var_Var_eq [iff]: "(Var m = Var n) = (m = n)"
 | 
|  |    334 | by (auto simp add: Var_def exprel_refl dest: VAR_imp_eq)
 | 
|  |    335 | 
 | 
|  |    336 | lemma VAR_neqv_PLUS: "VAR m \<sim> PLUS X Y \<Longrightarrow> False"
 | 
|  |    337 | by (drule exprel_imp_eq_freediscrim, simp)
 | 
|  |    338 | 
 | 
|  |    339 | theorem Var_neq_Plus [iff]: "Var N \<noteq> Plus X Y"
 | 
|  |    340 | apply (cases X, cases Y) 
 | 
|  |    341 | apply (simp add: Var_def Plus) 
 | 
|  |    342 | apply (blast dest: VAR_neqv_PLUS) 
 | 
|  |    343 | done
 | 
|  |    344 | 
 | 
|  |    345 | theorem Var_neq_FnCall [iff]: "Var N \<noteq> FnCall F Xs"
 | 
|  |    346 | apply (cases Xs rule: eq_Abs_ExpList) 
 | 
|  |    347 | apply (auto simp add: FnCall Var_def)
 | 
|  |    348 | apply (drule exprel_imp_eq_freediscrim, simp)
 | 
|  |    349 | done
 | 
|  |    350 | 
 | 
|  |    351 | subsection{*Injectivity of @{term FnCall}*}
 | 
|  |    352 | 
 | 
| 19736 |    353 | definition
 | 
| 15172 |    354 |   fun :: "exp \<Rightarrow> nat"
 | 
| 19736 |    355 |   "fun X = contents (\<Union>U \<in> Rep_Exp X. {freefun U})"
 | 
| 15172 |    356 | 
 | 
|  |    357 | lemma fun_respects: "(%U. {freefun U}) respects exprel"
 | 
|  |    358 | by (simp add: congruent_def exprel_imp_eq_freefun) 
 | 
|  |    359 | 
 | 
|  |    360 | lemma fun_FnCall [simp]: "fun (FnCall F Xs) = F"
 | 
|  |    361 | apply (cases Xs rule: eq_Abs_ExpList) 
 | 
|  |    362 | apply (simp add: FnCall fun_def UN_equiv_class [OF equiv_exprel fun_respects])
 | 
|  |    363 | done
 | 
|  |    364 | 
 | 
| 19736 |    365 | definition
 | 
| 15172 |    366 |   args :: "exp \<Rightarrow> exp list"
 | 
| 19736 |    367 |   "args X = contents (\<Union>U \<in> Rep_Exp X. {Abs_ExpList (freeargs U)})"
 | 
| 15172 |    368 | 
 | 
|  |    369 | text{*This result can probably be generalized to arbitrary equivalence
 | 
|  |    370 | relations, but with little benefit here.*}
 | 
|  |    371 | lemma Abs_ExpList_eq:
 | 
|  |    372 |      "(y, z) \<in> listrel exprel \<Longrightarrow> Abs_ExpList (y) = Abs_ExpList (z)"
 | 
| 18460 |    373 |   by (induct set: listrel) simp_all
 | 
| 15172 |    374 | 
 | 
|  |    375 | lemma args_respects: "(%U. {Abs_ExpList (freeargs U)}) respects exprel"
 | 
|  |    376 | by (simp add: congruent_def Abs_ExpList_eq exprel_imp_eqv_freeargs) 
 | 
|  |    377 | 
 | 
|  |    378 | lemma args_FnCall [simp]: "args (FnCall F Xs) = Xs"
 | 
|  |    379 | apply (cases Xs rule: eq_Abs_ExpList) 
 | 
|  |    380 | apply (simp add: FnCall args_def UN_equiv_class [OF equiv_exprel args_respects])
 | 
|  |    381 | done
 | 
|  |    382 | 
 | 
|  |    383 | 
 | 
|  |    384 | lemma FnCall_FnCall_eq [iff]:
 | 
|  |    385 |      "(FnCall F Xs = FnCall F' Xs') = (F=F' & Xs=Xs')" 
 | 
|  |    386 | proof
 | 
|  |    387 |   assume "FnCall F Xs = FnCall F' Xs'"
 | 
|  |    388 |   hence "fun (FnCall F Xs) = fun (FnCall F' Xs')" 
 | 
|  |    389 |     and "args (FnCall F Xs) = args (FnCall F' Xs')" by auto
 | 
|  |    390 |   thus "F=F' & Xs=Xs'" by simp
 | 
|  |    391 | next
 | 
|  |    392 |   assume "F=F' & Xs=Xs'" thus "FnCall F Xs = FnCall F' Xs'" by simp
 | 
|  |    393 | qed
 | 
|  |    394 | 
 | 
|  |    395 | 
 | 
|  |    396 | subsection{*The Abstract Discriminator*}
 | 
|  |    397 | text{*However, as @{text FnCall_Var_neq_Var} illustrates, we don't need this
 | 
|  |    398 | function in order to prove discrimination theorems.*}
 | 
|  |    399 | 
 | 
| 19736 |    400 | definition
 | 
| 15172 |    401 |   discrim :: "exp \<Rightarrow> int"
 | 
| 19736 |    402 |   "discrim X = contents (\<Union>U \<in> Rep_Exp X. {freediscrim U})"
 | 
| 15172 |    403 | 
 | 
|  |    404 | lemma discrim_respects: "(\<lambda>U. {freediscrim U}) respects exprel"
 | 
|  |    405 | by (simp add: congruent_def exprel_imp_eq_freediscrim) 
 | 
|  |    406 | 
 | 
|  |    407 | text{*Now prove the four equations for @{term discrim}*}
 | 
|  |    408 | 
 | 
|  |    409 | lemma discrim_Var [simp]: "discrim (Var N) = 0"
 | 
|  |    410 | by (simp add: discrim_def Var_def 
 | 
|  |    411 |               UN_equiv_class [OF equiv_exprel discrim_respects]) 
 | 
|  |    412 | 
 | 
|  |    413 | lemma discrim_Plus [simp]: "discrim (Plus X Y) = 1"
 | 
|  |    414 | apply (cases X, cases Y) 
 | 
|  |    415 | apply (simp add: discrim_def Plus 
 | 
|  |    416 |                  UN_equiv_class [OF equiv_exprel discrim_respects]) 
 | 
|  |    417 | done
 | 
|  |    418 | 
 | 
|  |    419 | lemma discrim_FnCall [simp]: "discrim (FnCall F Xs) = 2"
 | 
|  |    420 | apply (rule_tac z=Xs in eq_Abs_ExpList) 
 | 
|  |    421 | apply (simp add: discrim_def FnCall
 | 
|  |    422 |                  UN_equiv_class [OF equiv_exprel discrim_respects]) 
 | 
|  |    423 | done
 | 
|  |    424 | 
 | 
|  |    425 | 
 | 
|  |    426 | text{*The structural induction rule for the abstract type*}
 | 
| 18460 |    427 | theorem exp_inducts:
 | 
| 15172 |    428 |   assumes V:    "\<And>nat. P1 (Var nat)"
 | 
|  |    429 |       and P:    "\<And>exp1 exp2. \<lbrakk>P1 exp1; P1 exp2\<rbrakk> \<Longrightarrow> P1 (Plus exp1 exp2)"
 | 
|  |    430 |       and F:    "\<And>nat list. P2 list \<Longrightarrow> P1 (FnCall nat list)"
 | 
|  |    431 |       and Nil:  "P2 []"
 | 
|  |    432 |       and Cons: "\<And>exp list. \<lbrakk>P1 exp; P2 list\<rbrakk> \<Longrightarrow> P2 (exp # list)"
 | 
| 18460 |    433 |   shows "P1 exp" and "P2 list"
 | 
|  |    434 | proof -
 | 
|  |    435 |   obtain U where exp: "exp = (Abs_Exp (exprel `` {U}))" by (cases exp)
 | 
|  |    436 |   obtain Us where list: "list = Abs_ExpList Us" by (rule eq_Abs_ExpList)
 | 
|  |    437 |   have "P1 (Abs_Exp (exprel `` {U}))" and "P2 (Abs_ExpList Us)"
 | 
| 15172 |    438 |   proof (induct U and Us)
 | 
| 18460 |    439 |     case (VAR nat)
 | 
| 15172 |    440 |     with V show ?case by (simp add: Var_def) 
 | 
|  |    441 |   next
 | 
|  |    442 |     case (PLUS X Y)
 | 
|  |    443 |     with P [of "Abs_Exp (exprel `` {X})" "Abs_Exp (exprel `` {Y})"]
 | 
|  |    444 |     show ?case by (simp add: Plus) 
 | 
|  |    445 |   next
 | 
|  |    446 |     case (FNCALL nat list)
 | 
|  |    447 |     with F [of "Abs_ExpList list"]
 | 
|  |    448 |     show ?case by (simp add: FnCall) 
 | 
|  |    449 |   next
 | 
|  |    450 |     case Nil_freeExp
 | 
|  |    451 |     with Nil show ?case by simp
 | 
|  |    452 |   next
 | 
|  |    453 |     case Cons_freeExp
 | 
| 18460 |    454 |     with Cons show ?case by simp
 | 
| 15172 |    455 |   qed
 | 
| 18460 |    456 |   with exp and list show "P1 exp" and "P2 list" by (simp_all only:)
 | 
| 15172 |    457 | qed
 | 
|  |    458 | 
 | 
|  |    459 | end
 |