99 by (induct w) auto |
99 by (induct w) auto |
100 |
100 |
101 lemma sset_streams: |
101 lemma sset_streams: |
102 assumes "sset s \<subseteq> A" |
102 assumes "sset s \<subseteq> A" |
103 shows "s \<in> streams A" |
103 shows "s \<in> streams A" |
104 proof (coinduct rule: streams.coinduct[of "\<lambda>s'. \<exists>a s. s' = a ## s \<and> a \<in> A \<and> sset s \<subseteq> A"]) |
104 using assms proof (coinduction arbitrary: s) |
105 case streams from assms show ?case by (cases s) auto |
105 case streams then show ?case by (cases s) simp |
106 next |
|
107 fix s' assume "\<exists>a s. s' = a ## s \<and> a \<in> A \<and> sset s \<subseteq> A" |
|
108 then guess a s by (elim exE) |
|
109 with assms show "\<exists>a l. s' = a ## l \<and> |
|
110 a \<in> A \<and> ((\<exists>a s. l = a ## s \<and> a \<in> A \<and> sset s \<subseteq> A) \<or> l \<in> streams A)" |
|
111 by (cases s) auto |
|
112 qed |
106 qed |
113 |
107 |
114 |
108 |
115 subsection {* nth, take, drop for streams *} |
109 subsection {* nth, take, drop for streams *} |
116 |
110 |
173 by (subst stake_sdrop[symmetric, of _ i]) (metis sdrop_simps stream.collapse) |
167 by (subst stake_sdrop[symmetric, of _ i]) (metis sdrop_simps stream.collapse) |
174 |
168 |
175 lemma smap_alt: "smap f s = s' \<longleftrightarrow> (\<forall>n. f (s !! n) = s' !! n)" (is "?L = ?R") |
169 lemma smap_alt: "smap f s = s' \<longleftrightarrow> (\<forall>n. f (s !! n) = s' !! n)" (is "?L = ?R") |
176 proof |
170 proof |
177 assume ?R |
171 assume ?R |
178 thus ?L |
172 then have "\<And>n. smap f (sdrop n s) = sdrop n s'" |
179 by (coinduct rule: stream.coinduct[of "\<lambda>s1 s2. \<exists>n. s1 = smap f (sdrop n s) \<and> s2 = sdrop n s'", consumes 0]) |
173 by coinduction (auto intro: exI[of _ 0] simp del: sdrop.simps(2)) |
180 (auto intro: exI[of _ 0] simp del: sdrop.simps(2)) |
174 then show ?L using sdrop.simps(1) by metis |
181 qed auto |
175 qed auto |
182 |
176 |
183 lemma stake_invert_Nil[iff]: "stake n s = [] \<longleftrightarrow> n = 0" |
177 lemma stake_invert_Nil[iff]: "stake n s = [] \<longleftrightarrow> n = 0" |
184 by (induct n) auto |
178 by (induct n) auto |
185 |
179 |
216 moreover from Suc(3) have "\<not> (P (s !! 0))" by blast |
210 moreover from Suc(3) have "\<not> (P (s !! 0))" by blast |
217 ultimately show ?case by (subst sdrop_while.simps) simp |
211 ultimately show ?case by (subst sdrop_while.simps) simp |
218 qed (metis comp_apply sdrop.simps(1) sdrop_while.simps snth.simps(1)) |
212 qed (metis comp_apply sdrop.simps(1) sdrop_while.simps snth.simps(1)) |
219 qed |
213 qed |
220 |
214 |
221 definition "sfilter P = stream_unfold (shd o sdrop_while (Not o P)) (stl o sdrop_while (Not o P))" |
215 primcorec sfilter where |
|
216 "shd (sfilter P s) = shd (sdrop_while (Not o P) s)" |
|
217 | "stl (sfilter P s) = sfilter P (stl (sdrop_while (Not o P) s))" |
222 |
218 |
223 lemma sfilter_Stream: "sfilter P (x ## s) = (if P x then x ## sfilter P s else sfilter P s)" |
219 lemma sfilter_Stream: "sfilter P (x ## s) = (if P x then x ## sfilter P s else sfilter P s)" |
224 proof (cases "P x") |
220 proof (cases "P x") |
225 case True thus ?thesis unfolding sfilter_def |
221 case True thus ?thesis by (subst sfilter.ctr) (simp add: sdrop_while_Stream) |
226 by (subst stream.unfold) (simp add: sdrop_while_Stream) |
|
227 next |
222 next |
228 case False thus ?thesis unfolding sfilter_def |
223 case False thus ?thesis by (subst (1 2) sfilter.ctr) (simp add: sdrop_while_Stream) |
229 by (subst (1 2) stream.unfold) (simp add: sdrop_while_Stream) |
|
230 qed |
224 qed |
231 |
225 |
232 |
226 |
233 subsection {* unary predicates lifted to streams *} |
227 subsection {* unary predicates lifted to streams *} |
234 |
228 |
241 unfolding stream_all_iff list_all_iff by auto |
235 unfolding stream_all_iff list_all_iff by auto |
242 |
236 |
243 |
237 |
244 subsection {* recurring stream out of a list *} |
238 subsection {* recurring stream out of a list *} |
245 |
239 |
246 definition cycle :: "'a list \<Rightarrow> 'a stream" where |
240 primcorec cycle :: "'a list \<Rightarrow> 'a stream" where |
247 "cycle = stream_unfold hd (\<lambda>xs. tl xs @ [hd xs])" |
241 "shd (cycle xs) = hd xs" |
248 |
242 | "stl (cycle xs) = cycle (tl xs @ [hd xs])" |
249 lemma cycle_simps[simp]: |
|
250 "shd (cycle u) = hd u" |
|
251 "stl (cycle u) = cycle (tl u @ [hd u])" |
|
252 by (auto simp: cycle_def) |
|
253 |
|
254 lemma cycle_decomp: "u \<noteq> [] \<Longrightarrow> cycle u = u @- cycle u" |
243 lemma cycle_decomp: "u \<noteq> [] \<Longrightarrow> cycle u = u @- cycle u" |
255 proof (coinduct rule: stream.coinduct[of "\<lambda>s1 s2. \<exists>u. s1 = cycle u \<and> s2 = u @- cycle u \<and> u \<noteq> []", consumes 0, case_names _ Eq_stream]) |
244 proof (coinduction arbitrary: u) |
256 case (Eq_stream s1 s2) |
245 case Eq_stream then show ?case using stream.collapse[of "cycle u"] |
257 then obtain u where "s1 = cycle u \<and> s2 = u @- cycle u \<and> u \<noteq> []" by blast |
246 by (auto intro!: exI[of _ "tl u @ [hd u]"]) |
258 thus ?case using stream.unfold[of hd "\<lambda>xs. tl xs @ [hd xs]" u] by (auto simp: cycle_def) |
247 qed |
259 qed auto |
|
260 |
248 |
261 lemma cycle_Cons[code]: "cycle (x # xs) = x ## cycle (xs @ [x])" |
249 lemma cycle_Cons[code]: "cycle (x # xs) = x ## cycle (xs @ [x])" |
262 proof (coinduct rule: stream.coinduct[of "\<lambda>s1 s2. \<exists>x xs. s1 = cycle (x # xs) \<and> s2 = x ## cycle (xs @ [x])", consumes 0, case_names _ Eq_stream]) |
250 by (subst cycle.ctr) simp |
263 case (Eq_stream s1 s2) |
|
264 then obtain x xs where "s1 = cycle (x # xs) \<and> s2 = x ## cycle (xs @ [x])" by blast |
|
265 thus ?case |
|
266 by (auto simp: cycle_def intro!: exI[of _ "hd (xs @ [x])"] exI[of _ "tl (xs @ [x])"] stream.unfold) |
|
267 qed auto |
|
268 |
251 |
269 lemma cycle_rotated: "\<lbrakk>v \<noteq> []; cycle u = v @- s\<rbrakk> \<Longrightarrow> cycle (tl u @ [hd u]) = tl v @- s" |
252 lemma cycle_rotated: "\<lbrakk>v \<noteq> []; cycle u = v @- s\<rbrakk> \<Longrightarrow> cycle (tl u @ [hd u]) = tl v @- s" |
270 by (auto dest: arg_cong[of _ _ stl]) |
253 by (auto dest: arg_cong[of _ _ stl]) |
271 |
254 |
272 lemma stake_append: "stake n (u @- s) = take (min (length u) n) u @ stake (n - length u) s" |
255 lemma stake_append: "stake n (u @- s) = take (min (length u) n) u @ stake (n - length u) s" |
302 by (induct n arbitrary: u) (auto simp: rotate1_rotate_swap rotate1_hd_tl rotate_conv_mod[symmetric]) |
285 by (induct n arbitrary: u) (auto simp: rotate1_rotate_swap rotate1_hd_tl rotate_conv_mod[symmetric]) |
303 |
286 |
304 |
287 |
305 subsection {* stream repeating a single element *} |
288 subsection {* stream repeating a single element *} |
306 |
289 |
307 definition "same x = stream_unfold (\<lambda>_. x) id ()" |
290 primcorec same where |
308 |
291 "shd (same x) = x" |
309 lemma same_simps[simp]: "shd (same x) = x" "stl (same x) = same x" |
292 | "stl (same x) = same x" |
310 unfolding same_def by auto |
|
311 |
|
312 lemma same_unfold[code]: "same x = x ## same x" |
|
313 by (metis same_simps stream.collapse) |
|
314 |
293 |
315 lemma snth_same[simp]: "same x !! n = x" |
294 lemma snth_same[simp]: "same x !! n = x" |
316 unfolding same_def by (induct n) auto |
295 unfolding same_def by (induct n) auto |
317 |
296 |
318 lemma stake_same[simp]: "stake n (same x) = replicate n x" |
297 lemma stake_same[simp]: "stake n (same x) = replicate n x" |
326 |
305 |
327 lemma stream_all_same[simp]: "stream_all P (same x) \<longleftrightarrow> P x" |
306 lemma stream_all_same[simp]: "stream_all P (same x) \<longleftrightarrow> P x" |
328 unfolding stream_all_def by auto |
307 unfolding stream_all_def by auto |
329 |
308 |
330 lemma same_cycle: "same x = cycle [x]" |
309 lemma same_cycle: "same x = cycle [x]" |
331 by (coinduct rule: stream.coinduct[of "\<lambda>s1 s2. s1 = same x \<and> s2 = cycle [x]"]) auto |
310 by coinduction auto |
332 |
311 |
333 |
312 |
334 subsection {* stream of natural numbers *} |
313 subsection {* stream of natural numbers *} |
335 |
314 |
336 definition "fromN n = stream_unfold id Suc n" |
315 primcorec fromN :: "nat \<Rightarrow> nat stream" where |
337 |
316 "fromN n = n ## fromN (n + 1)" |
338 lemma fromN_simps[simp]: "shd (fromN n) = n" "stl (fromN n) = fromN (Suc n)" |
|
339 unfolding fromN_def by auto |
|
340 |
|
341 lemma fromN_unfold[code]: "fromN n = n ## fromN (Suc n)" |
|
342 unfolding fromN_def by (metis id_def stream.unfold) |
|
343 |
317 |
344 lemma snth_fromN[simp]: "fromN n !! m = n + m" |
318 lemma snth_fromN[simp]: "fromN n !! m = n + m" |
345 unfolding fromN_def by (induct m arbitrary: n) auto |
319 unfolding fromN_def by (induct m arbitrary: n) auto |
346 |
320 |
347 lemma stake_fromN[simp]: "stake m (fromN n) = [n ..< m + n]" |
321 lemma stake_fromN[simp]: "stake m (fromN n) = [n ..< m + n]" |
350 lemma sdrop_fromN[simp]: "sdrop m (fromN n) = fromN (n + m)" |
324 lemma sdrop_fromN[simp]: "sdrop m (fromN n) = fromN (n + m)" |
351 unfolding fromN_def by (induct m arbitrary: n) auto |
325 unfolding fromN_def by (induct m arbitrary: n) auto |
352 |
326 |
353 lemma sset_fromN[simp]: "sset (fromN n) = {n ..}" (is "?L = ?R") |
327 lemma sset_fromN[simp]: "sset (fromN n) = {n ..}" (is "?L = ?R") |
354 proof safe |
328 proof safe |
355 fix m assume "m : ?L" |
329 fix m assume "m \<in> ?L" |
356 moreover |
330 moreover |
357 { fix s assume "m \<in> sset s" "\<exists>n'\<ge>n. s = fromN n'" |
331 { fix s assume "m \<in> sset s" "\<exists>n'\<ge>n. s = fromN n'" |
358 hence "n \<le> m" by (induct arbitrary: n rule: sset_induct1) fastforce+ |
332 hence "n \<le> m" by (induct arbitrary: n rule: sset_induct1) fastforce+ |
359 } |
333 } |
360 ultimately show "n \<le> m" by blast |
334 ultimately show "n \<le> m" by auto |
361 next |
335 next |
362 fix m assume "n \<le> m" thus "m \<in> ?L" by (metis le_iff_add snth_fromN snth_sset) |
336 fix m assume "n \<le> m" thus "m \<in> ?L" by (metis le_iff_add snth_fromN snth_sset) |
363 qed |
337 qed |
364 |
338 |
365 abbreviation "nats \<equiv> fromN 0" |
339 abbreviation "nats \<equiv> fromN 0" |
366 |
340 |
367 |
341 |
368 subsection {* flatten a stream of lists *} |
342 subsection {* flatten a stream of lists *} |
369 |
343 |
370 definition flat where |
344 primcorec flat where |
371 "flat \<equiv> stream_unfold (hd o shd) (\<lambda>s. if tl (shd s) = [] then stl s else tl (shd s) ## stl s)" |
|
372 |
|
373 lemma flat_simps[simp]: |
|
374 "shd (flat ws) = hd (shd ws)" |
345 "shd (flat ws) = hd (shd ws)" |
375 "stl (flat ws) = flat (if tl (shd ws) = [] then stl ws else tl (shd ws) ## stl ws)" |
346 | "stl (flat ws) = flat (if tl (shd ws) = [] then stl ws else tl (shd ws) ## stl ws)" |
376 unfolding flat_def by auto |
|
377 |
347 |
378 lemma flat_Cons[simp, code]: "flat ((x # xs) ## ws) = x ## flat (if xs = [] then ws else xs ## ws)" |
348 lemma flat_Cons[simp, code]: "flat ((x # xs) ## ws) = x ## flat (if xs = [] then ws else xs ## ws)" |
379 unfolding flat_def using stream.unfold[of "hd o shd" _ "(x # xs) ## ws"] by auto |
349 by (subst flat.ctr) simp |
380 |
350 |
381 lemma flat_Stream[simp]: "xs \<noteq> [] \<Longrightarrow> flat (xs ## ws) = xs @- flat ws" |
351 lemma flat_Stream[simp]: "xs \<noteq> [] \<Longrightarrow> flat (xs ## ws) = xs @- flat ws" |
382 by (induct xs) auto |
352 by (induct xs) auto |
383 |
353 |
384 lemma flat_unfold: "shd ws \<noteq> [] \<Longrightarrow> flat ws = shd ws @- flat (stl ws)" |
354 lemma flat_unfold: "shd ws \<noteq> [] \<Longrightarrow> flat ws = shd ws @- flat (stl ws)" |
463 unfolding sproduct_def sset_smerge by (auto simp: stream.set_map) |
433 unfolding sproduct_def sset_smerge by (auto simp: stream.set_map) |
464 |
434 |
465 |
435 |
466 subsection {* interleave two streams *} |
436 subsection {* interleave two streams *} |
467 |
437 |
468 definition sinterleave :: "'a stream \<Rightarrow> 'a stream \<Rightarrow> 'a stream" where |
438 primcorec sinterleave where |
469 [code del]: "sinterleave s1 s2 = |
439 "shd (sinterleave s1 s2) = shd s1" |
470 stream_unfold (\<lambda>(s1, s2). shd s1) (\<lambda>(s1, s2). (s2, stl s1)) (s1, s2)" |
440 | "stl (sinterleave s1 s2) = sinterleave s2 (stl s1)" |
471 |
|
472 lemma sinterleave_simps[simp]: |
|
473 "shd (sinterleave s1 s2) = shd s1" "stl (sinterleave s1 s2) = sinterleave s2 (stl s1)" |
|
474 unfolding sinterleave_def by auto |
|
475 |
441 |
476 lemma sinterleave_code[code]: |
442 lemma sinterleave_code[code]: |
477 "sinterleave (x ## s1) s2 = x ## sinterleave s2 s1" |
443 "sinterleave (x ## s1) s2 = x ## sinterleave s2 s1" |
478 by (metis sinterleave_simps stream.exhaust stream.sel) |
444 by (subst sinterleave.ctr) simp |
479 |
445 |
480 lemma sinterleave_snth[simp]: |
446 lemma sinterleave_snth[simp]: |
481 "even n \<Longrightarrow> sinterleave s1 s2 !! n = s1 !! (n div 2)" |
447 "even n \<Longrightarrow> sinterleave s1 s2 !! n = s1 !! (n div 2)" |
482 "odd n \<Longrightarrow> sinterleave s1 s2 !! n = s2 !! (n div 2)" |
448 "odd n \<Longrightarrow> sinterleave s1 s2 !! n = s2 !! (n div 2)" |
483 by (induct n arbitrary: s1 s2) |
449 by (induct n arbitrary: s1 s2) |
505 qed |
471 qed |
506 |
472 |
507 |
473 |
508 subsection {* zip *} |
474 subsection {* zip *} |
509 |
475 |
510 definition "szip s1 s2 = |
476 primcorec szip where |
511 stream_unfold (map_pair shd shd) (map_pair stl stl) (s1, s2)" |
477 "shd (szip s1 s2) = (shd s1, shd s2)" |
512 |
478 | "stl (szip s1 s2) = szip (stl s1) (stl s2)" |
513 lemma szip_simps[simp]: |
|
514 "shd (szip s1 s2) = (shd s1, shd s2)" "stl (szip s1 s2) = szip (stl s1) (stl s2)" |
|
515 unfolding szip_def by auto |
|
516 |
479 |
517 lemma szip_unfold[code]: "szip (Stream a s1) (Stream b s2) = Stream (a, b) (szip s1 s2)" |
480 lemma szip_unfold[code]: "szip (Stream a s1) (Stream b s2) = Stream (a, b) (szip s1 s2)" |
518 unfolding szip_def by (subst stream.unfold) simp |
481 by (subst szip.ctr) simp |
519 |
482 |
520 lemma snth_szip[simp]: "szip s1 s2 !! n = (s1 !! n, s2 !! n)" |
483 lemma snth_szip[simp]: "szip s1 s2 !! n = (s1 !! n, s2 !! n)" |
521 by (induct n arbitrary: s1 s2) auto |
484 by (induct n arbitrary: s1 s2) auto |
522 |
485 |
523 |
486 |
524 subsection {* zip via function *} |
487 subsection {* zip via function *} |
525 |
488 |
526 definition "smap2 f s1 s2 = |
489 primcorec smap2 where |
527 stream_unfold (\<lambda>(s1,s2). f (shd s1) (shd s2)) (map_pair stl stl) (s1, s2)" |
|
528 |
|
529 lemma smap2_simps[simp]: |
|
530 "shd (smap2 f s1 s2) = f (shd s1) (shd s2)" |
490 "shd (smap2 f s1 s2) = f (shd s1) (shd s2)" |
531 "stl (smap2 f s1 s2) = smap2 f (stl s1) (stl s2)" |
491 | "stl (smap2 f s1 s2) = smap2 f (stl s1) (stl s2)" |
532 unfolding smap2_def by auto |
|
533 |
492 |
534 lemma smap2_unfold[code]: |
493 lemma smap2_unfold[code]: |
535 "smap2 f (Stream a s1) (Stream b s2) = Stream (f a b) (smap2 f s1 s2)" |
494 "smap2 f (Stream a s1) (Stream b s2) = Stream (f a b) (smap2 f s1 s2)" |
536 unfolding smap2_def by (subst stream.unfold) simp |
495 by (subst smap2.ctr) simp |
537 |
496 |
538 lemma smap2_szip: |
497 lemma smap2_szip: |
539 "smap2 f s1 s2 = smap (split f) (szip s1 s2)" |
498 "smap2 f s1 s2 = smap (split f) (szip s1 s2)" |
540 by (coinduct rule: stream.coinduct[of |
499 by (coinduction arbitrary: s1 s2) auto |
541 "\<lambda>s1 s2. \<exists>s1' s2'. s1 = smap2 f s1' s2' \<and> s2 = smap (split f) (szip s1' s2')"]) |
|
542 fastforce+ |
|
543 |
500 |
544 |
501 |
545 subsection {* iterated application of a function *} |
502 subsection {* iterated application of a function *} |
546 |
503 |
547 definition siterate :: "('a \<Rightarrow> 'a) \<Rightarrow> 'a \<Rightarrow> 'a stream" where |
504 primcorec siterate where |
548 "siterate f x = x ## stream_unfold f f x" |
505 "shd (siterate f x) = x" |
549 |
506 | "stl (siterate f x) = siterate f (f x)" |
550 lemma siterate_simps[simp]: "shd (siterate f x) = x" "stl (siterate f x) = siterate f (f x)" |
|
551 unfolding siterate_def by (auto intro: stream.unfold) |
|
552 |
|
553 lemma siterate_code[code]: "siterate f x = x ## siterate f (f x)" |
|
554 by (metis siterate_def stream.unfold) |
|
555 |
507 |
556 lemma stake_Suc: "stake (Suc n) s = stake n s @ [s !! n]" |
508 lemma stake_Suc: "stake (Suc n) s = stake n s @ [s !! n]" |
557 by (induct n arbitrary: s) auto |
509 by (induct n arbitrary: s) auto |
558 |
510 |
559 lemma snth_siterate[simp]: "siterate f x !! n = (f^^n) x" |
511 lemma snth_siterate[simp]: "siterate f x !! n = (f^^n) x" |