10 begin |
10 begin |
11 |
11 |
12 subsection {* List constructors over the datatype universe *} |
12 subsection {* List constructors over the datatype universe *} |
13 |
13 |
14 definition |
14 definition |
15 "NIL = Datatype_Universe.In0 (Datatype_Universe.Numb 0)" |
15 "NIL = Datatype.In0 (Datatype.Numb 0)" |
16 "CONS M N = Datatype_Universe.In1 (Datatype_Universe.Scons M N)" |
16 "CONS M N = Datatype.In1 (Datatype.Scons M N)" |
17 |
17 |
18 lemma CONS_not_NIL [iff]: "CONS M N \<noteq> NIL" |
18 lemma CONS_not_NIL [iff]: "CONS M N \<noteq> NIL" |
19 and NIL_not_CONS [iff]: "NIL \<noteq> CONS M N" |
19 and NIL_not_CONS [iff]: "NIL \<noteq> CONS M N" |
20 and CONS_inject [iff]: "(CONS K M) = (CONS L N) = (K = L \<and> M = N)" |
20 and CONS_inject [iff]: "(CONS K M) = (CONS L N) = (K = L \<and> M = N)" |
21 by (simp_all add: NIL_def CONS_def) |
21 by (simp_all add: NIL_def CONS_def) |
26 lemma CONS_UN1: "CONS M (\<Union>x. f x) = (\<Union>x. CONS M (f x))" |
26 lemma CONS_UN1: "CONS M (\<Union>x. f x) = (\<Union>x. CONS M (f x))" |
27 -- {* A continuity result? *} |
27 -- {* A continuity result? *} |
28 by (simp add: CONS_def In1_UN1 Scons_UN1_y) |
28 by (simp add: CONS_def In1_UN1 Scons_UN1_y) |
29 |
29 |
30 definition |
30 definition |
31 "List_case c h = Datatype_Universe.Case (\<lambda>_. c) (Datatype_Universe.Split h)" |
31 "List_case c h = Datatype.Case (\<lambda>_. c) (Datatype.Split h)" |
32 |
32 |
33 lemma List_case_NIL [simp]: "List_case c h NIL = c" |
33 lemma List_case_NIL [simp]: "List_case c h NIL = c" |
34 and List_case_CONS [simp]: "List_case c h (CONS M N) = h M N" |
34 and List_case_CONS [simp]: "List_case c h (CONS M N) = h M N" |
35 by (simp_all add: List_case_def NIL_def CONS_def) |
35 by (simp_all add: List_case_def NIL_def CONS_def) |
36 |
36 |
37 |
37 |
38 subsection {* Corecursive lists *} |
38 subsection {* Corecursive lists *} |
39 |
39 |
40 consts |
40 consts |
41 LList :: "'a Datatype_Universe.item set \<Rightarrow> 'a Datatype_Universe.item set" |
41 LList :: "'a Datatype.item set \<Rightarrow> 'a Datatype.item set" |
42 |
42 |
43 coinductive "LList A" |
43 coinductive "LList A" |
44 intros |
44 intros |
45 NIL [intro]: "NIL \<in> LList A" |
45 NIL [intro]: "NIL \<in> LList A" |
46 CONS [intro]: "a \<in> A \<Longrightarrow> M \<in> LList A \<Longrightarrow> CONS a M \<in> LList A" |
46 CONS [intro]: "a \<in> A \<Longrightarrow> M \<in> LList A \<Longrightarrow> CONS a M \<in> LList A" |
48 lemma LList_mono: "A \<subseteq> B \<Longrightarrow> LList A \<subseteq> LList B" |
48 lemma LList_mono: "A \<subseteq> B \<Longrightarrow> LList A \<subseteq> LList B" |
49 -- {* This justifies using @{text LList} in other recursive type definitions. *} |
49 -- {* This justifies using @{text LList} in other recursive type definitions. *} |
50 unfolding LList.defs by (blast intro!: gfp_mono) |
50 unfolding LList.defs by (blast intro!: gfp_mono) |
51 |
51 |
52 consts |
52 consts |
53 LList_corec_aux :: "nat \<Rightarrow> ('a \<Rightarrow> ('b Datatype_Universe.item \<times> 'a) option) \<Rightarrow> |
53 LList_corec_aux :: "nat \<Rightarrow> ('a \<Rightarrow> ('b Datatype.item \<times> 'a) option) \<Rightarrow> |
54 'a \<Rightarrow> 'b Datatype_Universe.item" |
54 'a \<Rightarrow> 'b Datatype.item" |
55 primrec |
55 primrec |
56 "LList_corec_aux 0 f x = {}" |
56 "LList_corec_aux 0 f x = {}" |
57 "LList_corec_aux (Suc k) f x = |
57 "LList_corec_aux (Suc k) f x = |
58 (case f x of |
58 (case f x of |
59 None \<Rightarrow> NIL |
59 None \<Rightarrow> NIL |
115 |
115 |
116 |
116 |
117 subsection {* Abstract type definition *} |
117 subsection {* Abstract type definition *} |
118 |
118 |
119 typedef 'a llist = |
119 typedef 'a llist = |
120 "LList (range Datatype_Universe.Leaf) :: 'a Datatype_Universe.item set" |
120 "LList (range Datatype.Leaf) :: 'a Datatype.item set" |
121 proof |
121 proof |
122 show "NIL \<in> ?llist" .. |
122 show "NIL \<in> ?llist" .. |
123 qed |
123 qed |
124 |
124 |
125 lemma NIL_type: "NIL \<in> llist" |
125 lemma NIL_type: "NIL \<in> llist" |
126 unfolding llist_def by (rule LList.NIL) |
126 unfolding llist_def by (rule LList.NIL) |
127 |
127 |
128 lemma CONS_type: "a \<in> range Datatype_Universe.Leaf \<Longrightarrow> |
128 lemma CONS_type: "a \<in> range Datatype.Leaf \<Longrightarrow> |
129 M \<in> llist \<Longrightarrow> CONS a M \<in> llist" |
129 M \<in> llist \<Longrightarrow> CONS a M \<in> llist" |
130 unfolding llist_def by (rule LList.CONS) |
130 unfolding llist_def by (rule LList.CONS) |
131 |
131 |
132 lemma llistI: "x \<in> LList (range Datatype_Universe.Leaf) \<Longrightarrow> x \<in> llist" |
132 lemma llistI: "x \<in> LList (range Datatype.Leaf) \<Longrightarrow> x \<in> llist" |
133 by (simp add: llist_def) |
133 by (simp add: llist_def) |
134 |
134 |
135 lemma llistD: "x \<in> llist \<Longrightarrow> x \<in> LList (range Datatype_Universe.Leaf)" |
135 lemma llistD: "x \<in> llist \<Longrightarrow> x \<in> LList (range Datatype.Leaf)" |
136 by (simp add: llist_def) |
136 by (simp add: llist_def) |
137 |
137 |
138 lemma Rep_llist_UNIV: "Rep_llist x \<in> LList UNIV" |
138 lemma Rep_llist_UNIV: "Rep_llist x \<in> LList UNIV" |
139 proof - |
139 proof - |
140 have "Rep_llist x \<in> llist" by (rule Rep_llist) |
140 have "Rep_llist x \<in> llist" by (rule Rep_llist) |
141 then have "Rep_llist x \<in> LList (range Datatype_Universe.Leaf)" |
141 then have "Rep_llist x \<in> LList (range Datatype.Leaf)" |
142 by (simp add: llist_def) |
142 by (simp add: llist_def) |
143 also have "\<dots> \<subseteq> LList UNIV" by (rule LList_mono) simp |
143 also have "\<dots> \<subseteq> LList UNIV" by (rule LList_mono) simp |
144 finally show ?thesis . |
144 finally show ?thesis . |
145 qed |
145 qed |
146 |
146 |
147 definition |
147 definition |
148 "LNil = Abs_llist NIL" |
148 "LNil = Abs_llist NIL" |
149 "LCons x xs = Abs_llist (CONS (Datatype_Universe.Leaf x) (Rep_llist xs))" |
149 "LCons x xs = Abs_llist (CONS (Datatype.Leaf x) (Rep_llist xs))" |
150 |
150 |
151 lemma LCons_not_LNil [iff]: "LCons x xs \<noteq> LNil" |
151 lemma LCons_not_LNil [iff]: "LCons x xs \<noteq> LNil" |
152 apply (simp add: LNil_def LCons_def) |
152 apply (simp add: LNil_def LCons_def) |
153 apply (subst Abs_llist_inject) |
153 apply (subst Abs_llist_inject) |
154 apply (auto intro: NIL_type CONS_type Rep_llist) |
154 apply (auto intro: NIL_type CONS_type Rep_llist) |
165 |
165 |
166 lemma Rep_llist_LNil: "Rep_llist LNil = NIL" |
166 lemma Rep_llist_LNil: "Rep_llist LNil = NIL" |
167 by (simp add: LNil_def add: Abs_llist_inverse NIL_type) |
167 by (simp add: LNil_def add: Abs_llist_inverse NIL_type) |
168 |
168 |
169 lemma Rep_llist_LCons: "Rep_llist (LCons x l) = |
169 lemma Rep_llist_LCons: "Rep_llist (LCons x l) = |
170 CONS (Datatype_Universe.Leaf x) (Rep_llist l)" |
170 CONS (Datatype.Leaf x) (Rep_llist l)" |
171 by (simp add: LCons_def Abs_llist_inverse CONS_type Rep_llist) |
171 by (simp add: LCons_def Abs_llist_inverse CONS_type Rep_llist) |
172 |
172 |
173 lemma llist_cases [cases type: llist]: |
173 lemma llist_cases [cases type: llist]: |
174 obtains |
174 obtains |
175 (LNil) "l = LNil" |
175 (LNil) "l = LNil" |
176 | (LCons) x l' where "l = LCons x l'" |
176 | (LCons) x l' where "l = LCons x l'" |
177 proof (cases l) |
177 proof (cases l) |
178 case (Abs_llist L) |
178 case (Abs_llist L) |
179 from `L \<in> llist` have "L \<in> LList (range Datatype_Universe.Leaf)" by (rule llistD) |
179 from `L \<in> llist` have "L \<in> LList (range Datatype.Leaf)" by (rule llistD) |
180 then show ?thesis |
180 then show ?thesis |
181 proof cases |
181 proof cases |
182 case NIL |
182 case NIL |
183 with Abs_llist have "l = LNil" by (simp add: LNil_def) |
183 with Abs_llist have "l = LNil" by (simp add: LNil_def) |
184 with LNil show ?thesis . |
184 with LNil show ?thesis . |
215 definition |
215 definition |
216 "llist_corec a f = |
216 "llist_corec a f = |
217 Abs_llist (LList_corec a |
217 Abs_llist (LList_corec a |
218 (\<lambda>z. |
218 (\<lambda>z. |
219 case f z of None \<Rightarrow> None |
219 case f z of None \<Rightarrow> None |
220 | Some (v, w) \<Rightarrow> Some (Datatype_Universe.Leaf v, w)))" |
220 | Some (v, w) \<Rightarrow> Some (Datatype.Leaf v, w)))" |
221 |
221 |
222 lemma LList_corec_type2: |
222 lemma LList_corec_type2: |
223 "LList_corec a |
223 "LList_corec a |
224 (\<lambda>z. case f z of None \<Rightarrow> None |
224 (\<lambda>z. case f z of None \<Rightarrow> None |
225 | Some (v, w) \<Rightarrow> Some (Datatype_Universe.Leaf v, w)) \<in> llist" |
225 | Some (v, w) \<Rightarrow> Some (Datatype.Leaf v, w)) \<in> llist" |
226 (is "?corec a \<in> _") |
226 (is "?corec a \<in> _") |
227 proof (unfold llist_def) |
227 proof (unfold llist_def) |
228 let "LList_corec a ?g" = "?corec a" |
228 let "LList_corec a ?g" = "?corec a" |
229 have "?corec a \<in> {?corec x | x. True}" by blast |
229 have "?corec a \<in> {?corec x | x. True}" by blast |
230 then show "?corec a \<in> LList (range Datatype_Universe.Leaf)" |
230 then show "?corec a \<in> LList (range Datatype.Leaf)" |
231 proof coinduct |
231 proof coinduct |
232 case (LList L) |
232 case (LList L) |
233 then obtain x where L: "L = ?corec x" by blast |
233 then obtain x where L: "L = ?corec x" by blast |
234 show ?case |
234 show ?case |
235 proof (cases "f x") |
235 proof (cases "f x") |
261 |
261 |
262 let "?corec a" = "llist_corec a f" |
262 let "?corec a" = "llist_corec a f" |
263 let "?rep_corec a" = |
263 let "?rep_corec a" = |
264 "LList_corec a |
264 "LList_corec a |
265 (\<lambda>z. case f z of None \<Rightarrow> None |
265 (\<lambda>z. case f z of None \<Rightarrow> None |
266 | Some (v, w) \<Rightarrow> Some (Datatype_Universe.Leaf v, w))" |
266 | Some (v, w) \<Rightarrow> Some (Datatype.Leaf v, w))" |
267 |
267 |
268 have "?corec a = Abs_llist (?rep_corec a)" |
268 have "?corec a = Abs_llist (?rep_corec a)" |
269 by (simp only: llist_corec_def) |
269 by (simp only: llist_corec_def) |
270 also from Some have "?rep_corec a = |
270 also from Some have "?rep_corec a = |
271 CONS (Datatype_Universe.Leaf (fst p)) (?rep_corec (snd p))" |
271 CONS (Datatype.Leaf (fst p)) (?rep_corec (snd p))" |
272 by (simp add: split_def LList_corec) |
272 by (simp add: split_def LList_corec) |
273 also have "?rep_corec (snd p) = Rep_llist (?corec (snd p))" |
273 also have "?rep_corec (snd p) = Rep_llist (?corec (snd p))" |
274 by (simp only: llist_corec_def Abs_llist_inverse LList_corec_type2) |
274 by (simp only: llist_corec_def Abs_llist_inverse LList_corec_type2) |
275 finally have "?corec a = LCons (fst p) (?corec (snd p))" |
275 finally have "?corec a = LCons (fst p) (?corec (snd p))" |
276 by (simp only: LCons_def) |
276 by (simp only: LCons_def) |
279 |
279 |
280 |
280 |
281 subsection {* Equality as greatest fixed-point; the bisimulation principle. *} |
281 subsection {* Equality as greatest fixed-point; the bisimulation principle. *} |
282 |
282 |
283 consts |
283 consts |
284 EqLList :: "('a Datatype_Universe.item \<times> 'a Datatype_Universe.item) set \<Rightarrow> |
284 EqLList :: "('a Datatype.item \<times> 'a Datatype.item) set \<Rightarrow> |
285 ('a Datatype_Universe.item \<times> 'a Datatype_Universe.item) set" |
285 ('a Datatype.item \<times> 'a Datatype.item) set" |
286 |
286 |
287 coinductive "EqLList r" |
287 coinductive "EqLList r" |
288 intros |
288 intros |
289 EqNIL: "(NIL, NIL) \<in> EqLList r" |
289 EqNIL: "(NIL, NIL) \<in> EqLList r" |
290 EqCONS: "(a, b) \<in> r \<Longrightarrow> (M, N) \<in> EqLList r \<Longrightarrow> |
290 EqCONS: "(a, b) \<in> r \<Longrightarrow> (M, N) \<in> EqLList r \<Longrightarrow> |
291 (CONS a M, CONS b N) \<in> EqLList r" |
291 (CONS a M, CONS b N) \<in> EqLList r" |
292 |
292 |
293 lemma EqLList_unfold: |
293 lemma EqLList_unfold: |
294 "EqLList r = dsum (diag {Datatype_Universe.Numb 0}) (dprod r (EqLList r))" |
294 "EqLList r = dsum (diag {Datatype.Numb 0}) (dprod r (EqLList r))" |
295 by (fast intro!: EqLList.intros [unfolded NIL_def CONS_def] |
295 by (fast intro!: EqLList.intros [unfolded NIL_def CONS_def] |
296 elim: EqLList.cases [unfolded NIL_def CONS_def]) |
296 elim: EqLList.cases [unfolded NIL_def CONS_def]) |
297 |
297 |
298 lemma EqLList_implies_ntrunc_equality: |
298 lemma EqLList_implies_ntrunc_equality: |
299 "(M, N) \<in> EqLList (diag A) \<Longrightarrow> ntrunc k M = ntrunc k N" |
299 "(M, N) \<in> EqLList (diag A) \<Longrightarrow> ntrunc k M = ntrunc k N" |
610 shows "Lmap (f o g) M = Lmap f (Lmap g M)" (is "?lhs M = ?rhs M") |
610 shows "Lmap (f o g) M = Lmap f (Lmap g M)" (is "?lhs M = ?rhs M") |
611 proof - |
611 proof - |
612 have "(?lhs M, ?rhs M) \<in> {(?lhs N, ?rhs N) | N. N \<in> LList A}" |
612 have "(?lhs M, ?rhs M) \<in> {(?lhs N, ?rhs N) | N. N \<in> LList A}" |
613 using M by blast |
613 using M by blast |
614 then show ?thesis |
614 then show ?thesis |
615 proof (coinduct taking: "range (\<lambda>N :: 'a Datatype_Universe.item. N)" |
615 proof (coinduct taking: "range (\<lambda>N :: 'a Datatype.item. N)" |
616 rule: LList_equalityI) |
616 rule: LList_equalityI) |
617 case (EqLList q) |
617 case (EqLList q) |
618 then obtain N where q: "q = (?lhs N, ?rhs N)" and N: "N \<in> LList A" by blast |
618 then obtain N where q: "q = (?lhs N, ?rhs N)" and N: "N \<in> LList A" by blast |
619 from N show ?case |
619 from N show ?case |
620 proof cases |
620 proof cases |
633 assumes M: "M \<in> LList A" |
633 assumes M: "M \<in> LList A" |
634 shows "Lmap (\<lambda>x. x) M = M" (is "?lmap M = _") |
634 shows "Lmap (\<lambda>x. x) M = M" (is "?lmap M = _") |
635 proof - |
635 proof - |
636 have "(?lmap M, M) \<in> {(?lmap N, N) | N. N \<in> LList A}" using M by blast |
636 have "(?lmap M, M) \<in> {(?lmap N, N) | N. N \<in> LList A}" using M by blast |
637 then show ?thesis |
637 then show ?thesis |
638 proof (coinduct taking: "range (\<lambda>N :: 'a Datatype_Universe.item. N)" |
638 proof (coinduct taking: "range (\<lambda>N :: 'a Datatype.item. N)" |
639 rule: LList_equalityI) |
639 rule: LList_equalityI) |
640 case (EqLList q) |
640 case (EqLList q) |
641 then obtain N where q: "q = (?lmap N, N)" and N: "N \<in> LList A" by blast |
641 then obtain N where q: "q = (?lmap N, N)" and N: "N \<in> LList A" by blast |
642 from N show ?case |
642 from N show ?case |
643 proof cases |
643 proof cases |