author | chaieb |
Mon, 11 Jun 2007 11:06:00 +0200 | |
changeset 23314 | 6894137e854a |
parent 16417 | 9bc16273c2d4 |
child 24893 | b8ef7afe3a6b |
permissions | -rw-r--r-- |
1478 | 1 |
(* Title: ZF/ex/LList.thy |
515 | 2 |
ID: $Id$ |
1478 | 3 |
Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
515 | 4 |
Copyright 1994 University of Cambridge |
5 |
||
6 |
Codatatype definition of Lazy Lists |
|
7 |
||
8 |
Equality for llist(A) as a greatest fixed point |
|
9 |
||
10 |
Functions for Lazy Lists |
|
11 |
||
12 |
STILL NEEDS: |
|
13 |
co_recursion for defining lconst, flip, etc. |
|
14 |
a typing rule for it, based on some notion of "productivity..." |
|
15 |
*) |
|
16 |
||
16417 | 17 |
theory LList imports Main begin |
515 | 18 |
|
19 |
consts |
|
12867 | 20 |
llist :: "i=>i"; |
515 | 21 |
|
22 |
codatatype |
|
12867 | 23 |
"llist(A)" = LNil | LCons ("a \<in> A", "l \<in> llist(A)") |
515 | 24 |
|
25 |
||
26 |
(*Coinductive definition of equality*) |
|
27 |
consts |
|
12867 | 28 |
lleq :: "i=>i" |
515 | 29 |
|
30 |
(*Previously used <*> in the domain and variant pairs as elements. But |
|
31 |
standard pairs work just as well. To use variant pairs, must change prefix |
|
32 |
a q/Q to the Sigma, Pair and converse rules.*) |
|
33 |
coinductive |
|
34 |
domains "lleq(A)" <= "llist(A) * llist(A)" |
|
12867 | 35 |
intros |
36 |
LNil: "<LNil, LNil> \<in> lleq(A)" |
|
37 |
LCons: "[| a \<in> A; <l,l'> \<in> lleq(A) |] |
|
38 |
==> <LCons(a,l), LCons(a,l')> \<in> lleq(A)" |
|
39 |
type_intros llist.intros |
|
515 | 40 |
|
41 |
||
42 |
(*Lazy list functions; flip is not definitional!*) |
|
43 |
consts |
|
12867 | 44 |
lconst :: "i => i" |
45 |
flip :: "i => i" |
|
515 | 46 |
|
753 | 47 |
defs |
12867 | 48 |
lconst_def: "lconst(a) == lfp(univ(a), %l. LCons(a,l))" |
49 |
||
50 |
axioms |
|
51 |
flip_LNil: "flip(LNil) = LNil" |
|
52 |
||
53 |
flip_LCons: "[| x \<in> bool; l \<in> llist(bool) |] |
|
54 |
==> flip(LCons(x,l)) = LCons(not(x), flip(l))" |
|
55 |
||
56 |
||
57 |
(*These commands cause classical reasoning to regard the subset relation |
|
58 |
as primitive, not reducing it to membership*) |
|
59 |
||
60 |
declare subsetI [rule del] |
|
61 |
subsetCE [rule del] |
|
62 |
||
63 |
declare subset_refl [intro!] |
|
64 |
cons_subsetI [intro!] |
|
65 |
subset_consI [intro!] |
|
66 |
Union_least [intro!] |
|
67 |
UN_least [intro!] |
|
68 |
Un_least [intro!] |
|
69 |
Inter_greatest [intro!] |
|
70 |
Int_greatest [intro!] |
|
71 |
RepFun_subset [intro!] |
|
72 |
Un_upper1 [intro!] |
|
73 |
Un_upper2 [intro!] |
|
74 |
Int_lower1 [intro!] |
|
75 |
Int_lower2 [intro!] |
|
76 |
||
77 |
(*An elimination rule, for type-checking*) |
|
78 |
inductive_cases LConsE: "LCons(a,l) \<in> llist(A)" |
|
79 |
||
80 |
(*Proving freeness results*) |
|
81 |
lemma LCons_iff: "LCons(a,l)=LCons(a',l') <-> a=a' & l=l'" |
|
82 |
by auto |
|
83 |
||
84 |
lemma LNil_LCons_iff: "~ LNil=LCons(a,l)" |
|
85 |
by auto |
|
86 |
||
87 |
(* |
|
88 |
lemma llist_unfold: "llist(A) = {0} <+> (A <*> llist(A))"; |
|
89 |
let open llist val rew = rewrite_rule con_defs in |
|
90 |
by (fast_tac (claset() addSIs (subsetI ::map rew intros) addEs [rew elim]) 1) |
|
91 |
end |
|
92 |
done |
|
93 |
*) |
|
94 |
||
95 |
(*** Lemmas to justify using "llist" in other recursive type definitions ***) |
|
96 |
||
97 |
lemma llist_mono: "A \<subseteq> B ==> llist(A) \<subseteq> llist(B)" |
|
98 |
apply (unfold llist.defs ) |
|
99 |
apply (rule gfp_mono) |
|
100 |
apply (rule llist.bnd_mono) |
|
101 |
apply (assumption | rule quniv_mono basic_monos)+ |
|
102 |
done |
|
103 |
||
104 |
(** Closure of quniv(A) under llist -- why so complex? Its a gfp... **) |
|
105 |
||
106 |
declare QPair_Int_Vset_subset_UN [THEN subset_trans, intro!] |
|
107 |
QPair_subset_univ [intro!] |
|
108 |
empty_subsetI [intro!] |
|
109 |
one_in_quniv [THEN qunivD, intro!] |
|
110 |
declare qunivD [dest!] |
|
111 |
declare Ord_in_Ord [elim!] |
|
112 |
||
113 |
lemma llist_quniv_lemma [rule_format]: |
|
114 |
"Ord(i) ==> \<forall>l \<in> llist(quniv(A)). l Int Vset(i) \<subseteq> univ(eclose(A))" |
|
115 |
apply (erule trans_induct) |
|
116 |
apply (rule ballI) |
|
117 |
apply (erule llist.cases) |
|
118 |
apply (simp_all add: QInl_def QInr_def llist.con_defs) |
|
119 |
(*LCons case: I simply can't get rid of the deepen_tac*) |
|
120 |
apply (tactic "deepen_tac (claset() addIs [Ord_trans] addIs [Int_lower1 RS subset_trans]) 2 1") |
|
121 |
done |
|
122 |
||
123 |
lemma llist_quniv: "llist(quniv(A)) \<subseteq> quniv(A)" |
|
124 |
apply (rule qunivI [THEN subsetI]) |
|
125 |
apply (rule Int_Vset_subset) |
|
126 |
apply (assumption | rule llist_quniv_lemma)+ |
|
127 |
done |
|
128 |
||
129 |
lemmas llist_subset_quniv = |
|
130 |
subset_trans [OF llist_mono llist_quniv] |
|
131 |
||
132 |
||
133 |
(*** Lazy List Equality: lleq ***) |
|
134 |
||
135 |
declare QPair_Int_Vset_subset_UN [THEN subset_trans, intro!] |
|
136 |
QPair_mono [intro!] |
|
137 |
||
138 |
declare Ord_in_Ord [elim!] |
|
139 |
||
140 |
(*Lemma for proving finality. Unfold the lazy list; use induction hypothesis*) |
|
141 |
lemma lleq_Int_Vset_subset [rule_format]: |
|
142 |
"Ord(i) ==> \<forall>l l'. <l,l'> \<in> lleq(A) --> l Int Vset(i) \<subseteq> l'" |
|
143 |
apply (erule trans_induct) |
|
144 |
apply (intro allI impI) |
|
145 |
apply (erule lleq.cases) |
|
13339
0f89104dd377
Fixed quantified variable name preservation for ball and bex (bounded quants)
paulson
parents:
12867
diff
changeset
|
146 |
apply (unfold QInr_def llist.con_defs, safe) |
12867 | 147 |
apply (fast elim!: Ord_trans bspec [elim_format]) |
148 |
done |
|
515 | 149 |
|
12867 | 150 |
(*lleq(A) is a symmetric relation because qconverse(lleq(A)) is a fixedpoint*) |
151 |
lemma lleq_symmetric: "<l,l'> \<in> lleq(A) ==> <l',l> \<in> lleq(A)" |
|
152 |
apply (erule lleq.coinduct [OF converseI]) |
|
13339
0f89104dd377
Fixed quantified variable name preservation for ball and bex (bounded quants)
paulson
parents:
12867
diff
changeset
|
153 |
apply (rule lleq.dom_subset [THEN converse_type], safe) |
0f89104dd377
Fixed quantified variable name preservation for ball and bex (bounded quants)
paulson
parents:
12867
diff
changeset
|
154 |
apply (erule lleq.cases, blast+) |
12867 | 155 |
done |
156 |
||
157 |
lemma lleq_implies_equal: "<l,l'> \<in> lleq(A) ==> l=l'" |
|
158 |
apply (rule equalityI) |
|
159 |
apply (assumption | rule lleq_Int_Vset_subset [THEN Int_Vset_subset] | |
|
160 |
erule lleq_symmetric)+ |
|
161 |
done |
|
162 |
||
163 |
lemma equal_llist_implies_leq: |
|
164 |
"[| l=l'; l \<in> llist(A) |] ==> <l,l'> \<in> lleq(A)" |
|
165 |
apply (rule_tac X = "{<l,l>. l \<in> llist (A) }" in lleq.coinduct) |
|
166 |
apply blast |
|
167 |
apply safe |
|
13339
0f89104dd377
Fixed quantified variable name preservation for ball and bex (bounded quants)
paulson
parents:
12867
diff
changeset
|
168 |
apply (erule_tac a=l in llist.cases, fast+) |
12867 | 169 |
done |
170 |
||
171 |
||
172 |
(*** Lazy List Functions ***) |
|
173 |
||
174 |
(*Examples of coinduction for type-checking and to prove llist equations*) |
|
175 |
||
176 |
(*** lconst -- defined directly using lfp, but equivalent to a LList_corec ***) |
|
177 |
||
178 |
lemma lconst_fun_bnd_mono: "bnd_mono(univ(a), %l. LCons(a,l))" |
|
179 |
apply (unfold llist.con_defs ) |
|
180 |
apply (rule bnd_monoI) |
|
181 |
apply (blast intro: A_subset_univ QInr_subset_univ) |
|
182 |
apply (blast intro: subset_refl QInr_mono QPair_mono) |
|
183 |
done |
|
184 |
||
185 |
(* lconst(a) = LCons(a,lconst(a)) *) |
|
186 |
lemmas lconst = def_lfp_unfold [OF lconst_def lconst_fun_bnd_mono] |
|
187 |
lemmas lconst_subset = lconst_def [THEN def_lfp_subset] |
|
188 |
lemmas member_subset_Union_eclose = arg_into_eclose [THEN Union_upper] |
|
189 |
||
190 |
lemma lconst_in_quniv: "a \<in> A ==> lconst(a) \<in> quniv(A)" |
|
191 |
apply (rule lconst_subset [THEN subset_trans, THEN qunivI]) |
|
192 |
apply (erule arg_into_eclose [THEN eclose_subset, THEN univ_mono]) |
|
193 |
done |
|
515 | 194 |
|
12867 | 195 |
lemma lconst_type: "a \<in> A ==> lconst(a): llist(A)" |
196 |
apply (rule singletonI [THEN llist.coinduct]) |
|
197 |
apply (erule lconst_in_quniv [THEN singleton_subsetI]) |
|
198 |
apply (fast intro!: lconst) |
|
199 |
done |
|
200 |
||
201 |
(*** flip --- equations merely assumed; certain consequences proved ***) |
|
202 |
||
203 |
declare flip_LNil [simp] |
|
204 |
flip_LCons [simp] |
|
205 |
not_type [simp] |
|
206 |
||
207 |
lemma bool_Int_subset_univ: "b \<in> bool ==> b Int X \<subseteq> univ(eclose(A))" |
|
208 |
by (fast intro: Int_lower1 [THEN subset_trans] elim!: boolE) |
|
209 |
||
210 |
declare not_type [intro!] |
|
211 |
declare bool_Int_subset_univ [intro] |
|
212 |
||
213 |
(*Reasoning borrowed from lleq.ML; a similar proof works for all |
|
214 |
"productive" functions -- cf Coquand's "Infinite Objects in Type Theory".*) |
|
215 |
lemma flip_llist_quniv_lemma [rule_format]: |
|
216 |
"Ord(i) ==> \<forall>l \<in> llist(bool). flip(l) Int Vset(i) \<subseteq> univ(eclose(bool))" |
|
217 |
apply (erule trans_induct) |
|
218 |
apply (rule ballI) |
|
13339
0f89104dd377
Fixed quantified variable name preservation for ball and bex (bounded quants)
paulson
parents:
12867
diff
changeset
|
219 |
apply (erule llist.cases, simp_all) |
12867 | 220 |
apply (simp_all add: QInl_def QInr_def llist.con_defs) |
221 |
(*LCons case: I simply can't get rid of the deepen_tac*) |
|
222 |
apply (tactic "deepen_tac (claset() addIs [Ord_trans] addIs [Int_lower1 RS subset_trans]) 2 1") |
|
223 |
done |
|
224 |
||
225 |
lemma flip_in_quniv: "l \<in> llist(bool) ==> flip(l) \<in> quniv(bool)" |
|
13339
0f89104dd377
Fixed quantified variable name preservation for ball and bex (bounded quants)
paulson
parents:
12867
diff
changeset
|
226 |
by (rule flip_llist_quniv_lemma [THEN Int_Vset_subset, THEN qunivI], assumption+) |
12867 | 227 |
|
228 |
lemma flip_type: "l \<in> llist(bool) ==> flip(l): llist(bool)" |
|
229 |
apply (rule_tac X = "{flip (l) . l \<in> llist (bool) }" in llist.coinduct) |
|
230 |
apply blast |
|
231 |
apply (fast intro!: flip_in_quniv) |
|
232 |
apply (erule RepFunE) |
|
13339
0f89104dd377
Fixed quantified variable name preservation for ball and bex (bounded quants)
paulson
parents:
12867
diff
changeset
|
233 |
apply (erule_tac a=la in llist.cases, auto) |
12867 | 234 |
done |
235 |
||
236 |
lemma flip_flip: "l \<in> llist(bool) ==> flip(flip(l)) = l" |
|
237 |
apply (rule_tac X1 = "{<flip (flip (l)),l> . l \<in> llist (bool) }" in |
|
238 |
lleq.coinduct [THEN lleq_implies_equal]) |
|
239 |
apply blast |
|
240 |
apply (fast intro!: flip_type) |
|
241 |
apply (erule RepFunE) |
|
13339
0f89104dd377
Fixed quantified variable name preservation for ball and bex (bounded quants)
paulson
parents:
12867
diff
changeset
|
242 |
apply (erule_tac a=la in llist.cases) |
12867 | 243 |
apply (simp_all add: flip_type not_not) |
244 |
done |
|
515 | 245 |
|
246 |
end |
|
247 |