Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 0d66c87

Browse files
kappelmannmergify[bot]
authored andcommitted
feat(data/seq): add ext proof, nats def, zip_with lemmas, and extract seq property (#1278)
1 parent 49be50f commit 0d66c87

File tree

2 files changed

+83
-5
lines changed

2 files changed

+83
-5
lines changed

src/data/seq/seq.lean

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@ coinductive seq (α : Type u) : Type u
1414
| cons : α → seq α → seq α
1515
-/
1616

17+
/--
18+
A stream `s : option α` is a sequence if `s.nth n = none` implies `s.nth (n + 1) = none`.
19+
-/
20+
def stream.is_seq {α : Type u} (s : stream (option α)) : Prop :=
21+
∀ {n : ℕ}, s n = none → s (n + 1) = none
22+
1723
/-- `seq α` is the type of possibly infinite lists (referred here as sequences).
1824
It is encoded as an infinite stream of options such that if `f n = none`, then
1925
`f m = none` for all `m ≥ n`. -/
20-
def seq (α : Type u) : Type u := { f : stream (option α) // ∀ {n}, f n = none → f (n+1) = none }
26+
def seq (α : Type u) : Type u := { f : stream (option α) // f.is_seq }
2127

2228
/-- `seq1 α` is the type of nonempty sequences. -/
2329
def seq1 (α) := α × seq α
@@ -56,6 +62,17 @@ theorem le_stable (s : seq α) {m n} (h : m ≤ n) :
5662
s.1 m = none → s.1 n = none :=
5763
by {cases s with f al, induction h with n h IH, exacts [id, λ h2, al (IH h2)]}
5864

65+
/--
66+
If `s.nth n = some aₙ` for some value `aₙ`, then there is also some value `aₘ` such
67+
that `s.nth = some aₘ` for `m ≤ n`.
68+
-/
69+
lemma ge_stable (s : seq α) {aₙ : α} {n m : ℕ} (m_le_n : m ≤ n)
70+
(s_nth_eq_some : s.nth n = some aₙ) :
71+
∃ (aₘ : α), s.nth m = some aₘ :=
72+
have s.nth n ≠ none, by simp [s_nth_eq_some],
73+
have s.nth m ≠ none, from mt (s.le_stable m_le_n) this,
74+
with_one.ne_one_iff_exists.elim_left this
75+
5976
theorem not_mem_nil (a : α) : a ∉ @nil α :=
6077
λ ⟨n, (h : some a = none)⟩, by injection h
6178

@@ -281,6 +298,12 @@ end
281298
run on an infinite sequence. -/
282299
meta def force_to_list (s : seq α) : list α := (to_lazy_list s).to_list
283300

301+
/-- The sequence of natural numbers some 0, some 1, ... -/
302+
def nats : seq ℕ := stream.nats
303+
304+
@[simp]
305+
lemma nats_nth (n : ℕ) : nats.nth n = some n := rfl
306+
284307
/-- Append two sequences. If `s₁` is infinite, then `s₁ ++ s₂ = s₁`,
285308
otherwise it puts `s₂` at the location of the `nil` in `s₁`. -/
286309
def append (s₁ s₂ : seq α) : seq α :=
@@ -335,6 +358,8 @@ def split_at : ℕ → seq α → list α × seq α
335358
| some (x, s') := let (l, r) := split_at n s' in (list.cons x l, r)
336359
end
337360

361+
section zip_with
362+
338363
/-- Combine two sequences with a function -/
339364
def zip_with (f : α → β → γ) : seq α → seq β → seq γ
340365
| ⟨f₁, a₁⟩ ⟨f₂, a₂⟩ := ⟨λn,
@@ -344,12 +369,47 @@ def zip_with (f : α → β → γ) : seq α → seq β → seq γ
344369
end,
345370
λn, begin
346371
induction h1 : f₁ n,
347-
{ intro H, rw a₁ h1, refl },
372+
{ intro H, simp only [(a₁ h1)], refl },
348373
induction h2 : f₂ n; dsimp [seq.zip_with._match_1]; intro H,
349-
{ rw a₂ h2, cases f₁ (n + 1); refl },
350-
{ contradiction }
374+
{ rw (a₂ h2), cases f₁ (n + 1); refl },
375+
{ rw [h1, h2] at H, contradiction }
351376
end
352377

378+
variables {s : seq α} {s' : seq β} {n : ℕ}
379+
380+
lemma zip_with_nth_some {a : α} {b : β} (s_nth_eq_some : s.nth n = some a)
381+
(s_nth_eq_some' : s'.nth n = some b) (f : α → β → γ) :
382+
(zip_with f s s').nth n = some (f a b) :=
383+
begin
384+
cases s with st,
385+
have : st n = some a, from s_nth_eq_some,
386+
cases s' with st',
387+
have : st' n = some b, from s_nth_eq_some',
388+
simp only [zip_with, seq.nth, *]
389+
end
390+
391+
lemma zip_with_nth_none (s_nth_eq_none : s.nth n = none) (f : α → β → γ) :
392+
(zip_with f s s').nth n = none :=
393+
begin
394+
cases s with st,
395+
have : st n = none, from s_nth_eq_none,
396+
cases s' with st',
397+
cases st'_nth_eq : st' n;
398+
simp only [zip_with, seq.nth, *]
399+
end
400+
401+
lemma zip_with_nth_none' (s'_nth_eq_none : s'.nth n = none) (f : α → β → γ) :
402+
(zip_with f s s').nth n = none :=
403+
begin
404+
cases s' with st',
405+
have : st' n = none, from s'_nth_eq_none,
406+
cases s with st,
407+
cases st_nth_eq : st n;
408+
simp only [zip_with, seq.nth, *]
409+
end
410+
411+
end zip_with
412+
353413
/-- Pair two sequences into a sequence of pairs -/
354414
def zip : seq α → seq β → seq (α × β) := zip_with prod.mk
355415

@@ -549,6 +609,24 @@ by rw add_comm; symmetry; apply dropn_add
549609
theorem nth_tail : ∀ (s : seq α) n, nth (tail s) n = nth s (n + 1)
550610
| ⟨f, al⟩ n := rfl
551611

612+
@[extensionality]
613+
protected lemma ext (s s': seq α) (hyp : ∀ (n : ℕ), s.nth n = s'.nth n) : s = s' :=
614+
begin
615+
let ext := (λ (s s' : seq α), ∀ n, s.nth n = s'.nth n),
616+
apply seq.eq_of_bisim ext _ hyp,
617+
-- we have to show that ext is a bisimulation
618+
clear hyp s s',
619+
assume s s' (hyp : ext s s'),
620+
unfold seq.destruct,
621+
rw (hyp 0),
622+
cases (s'.nth 0),
623+
{ simp [seq.bisim_o] }, -- option.none
624+
{ -- option.some
625+
suffices : ext s.tail s'.tail, by simpa,
626+
assume n,
627+
simp only [seq.nth_tail _ n, (hyp $ n + 1)] }
628+
end
629+
552630
@[simp] theorem head_dropn (s : seq α) (n) : head (drop s n) = nth s n :=
553631
begin
554632
induction n with n IH generalizing s, { refl },

src/data/seq/wseq.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ instance productive_dropn (s : wseq α) [productive s] (n) : productive (drop s
621621
def to_seq (s : wseq α) [productive s] : seq α :=
622622
⟨λ n, (nth s n).get, λn h,
623623
begin
624-
induction e : computation.get (nth s (n + 1)), {trivial},
624+
cases e : computation.get (nth s (n + 1)), {assumption},
625625
have := mem_of_get_eq _ e,
626626
simp [nth] at this h, cases head_some_of_head_tail_some this with a' h',
627627
have := mem_unique h' (@mem_of_get_eq _ _ _ _ h),

0 commit comments

Comments
 (0)