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

Commit e00bfc1

Browse files
committed
feat(data/fin/tuple/basic): injectivity of fin.cons x xs (#17779)
1 parent c9bcaa7 commit e00bfc1

File tree

3 files changed

+67
-14
lines changed

3 files changed

+67
-14
lines changed

src/data/fin/tuple/basic.lean

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,19 +120,58 @@ end
120120

121121
/-- Recurse on an `n+1`-tuple by splitting it into a single element and an `n`-tuple. -/
122122
@[elab_as_eliminator]
123-
def cons_induction {P : (Π i : fin n.succ, α i) → Sort v}
123+
def cons_cases {P : (Π i : fin n.succ, α i) → Sort v}
124124
(h : ∀ x₀ x, P (fin.cons x₀ x)) (x : (Π i : fin n.succ, α i)) : P x :=
125125
_root_.cast (by rw cons_self_tail) $ h (x 0) (tail x)
126126

127-
@[simp] lemma cons_induction_cons {P : (Π i : fin n.succ, α i) → Sort v}
127+
@[simp] lemma cons_cases_cons {P : (Π i : fin n.succ, α i) → Sort v}
128128
(h : Π x₀ x, P (fin.cons x₀ x)) (x₀ : α 0) (x : Π i : fin n, α i.succ) :
129-
@cons_induction _ _ _ h (cons x₀ x) = h x₀ x :=
129+
@cons_cases _ _ _ h (cons x₀ x) = h x₀ x :=
130130
begin
131-
rw [cons_induction, cast_eq],
131+
rw [cons_cases, cast_eq],
132132
congr',
133133
exact tail_cons _ _
134134
end
135135

136+
/-- Recurse on an tuple by splitting into `fin.elim0` and `fin.cons`. -/
137+
@[elab_as_eliminator]
138+
def cons_induction {α : Type*} {P : Π {n : ℕ}, (fin n → α) → Sort v}
139+
(h0 : P fin.elim0)
140+
(h : ∀ {n} x₀ (x : fin n → α), P x → P (fin.cons x₀ x)) : Π {n : ℕ} (x : fin n → α), P x
141+
| 0 x := by convert h0
142+
| (n + 1) x := cons_cases (λ x₀ x, h _ _ $ cons_induction _) x
143+
144+
lemma cons_injective_of_injective {α} {x₀ : α} {x : fin n → α} (hx₀ : x₀ ∉ set.range x)
145+
(hx : function.injective x) :
146+
function.injective (cons x₀ x : fin n.succ → α) :=
147+
begin
148+
refine fin.cases _ _,
149+
{ refine fin.cases _ _,
150+
{ intro _,
151+
refl },
152+
{ intros j h,
153+
rw [cons_zero, cons_succ] at h,
154+
exact hx₀.elim ⟨_, h.symm⟩ } },
155+
{ intro i,
156+
refine fin.cases _ _,
157+
{ intro h,
158+
rw [cons_zero, cons_succ] at h,
159+
exact hx₀.elim ⟨_, h⟩ },
160+
{ intros j h,
161+
rw [cons_succ, cons_succ] at h,
162+
exact congr_arg _ (hx h), } },
163+
end
164+
165+
lemma cons_injective_iff {α} {x₀ : α} {x : fin n → α} :
166+
function.injective (cons x₀ x : fin n.succ → α) ↔ x₀ ∉ set.range x ∧ function.injective x :=
167+
begin
168+
refine ⟨λ h, ⟨_, _⟩, and.rec cons_injective_of_injective⟩,
169+
{ rintros ⟨i, hi⟩,
170+
replace h := @h i.succ 0,
171+
simpa [hi, succ_ne_zero] using h, },
172+
{ simpa [function.comp] using h.comp (fin.succ_injective _) },
173+
end
174+
136175
@[simp] lemma forall_fin_zero_pi {α : fin 0Sort*} {P : (Π i, α i) → Prop} :
137176
(∀ x, P x) ↔ P fin_zero_elim :=
138177
⟨λ h, h _, λ h x, subsingleton.elim fin_zero_elim x ▸ h⟩
@@ -143,7 +182,7 @@ end
143182

144183
lemma forall_fin_succ_pi {P : (Π i, α i) → Prop} :
145184
(∀ x, P x) ↔ (∀ a v, P (fin.cons a v)) :=
146-
⟨λ h a v, h (fin.cons a v), cons_induction
185+
⟨λ h a v, h (fin.cons a v), cons_cases
147186

148187
lemma exists_fin_succ_pi {P : (Π i, α i) → Prop} :
149188
(∃ x, P x) ↔ (∃ a v, P (fin.cons a v)) :=

src/data/fin/tuple/nat_antidiagonal.lean

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,17 @@ def antidiagonal_tuple : Π k, ℕ → list (fin k → ℕ)
6868
lemma mem_antidiagonal_tuple {n : ℕ} {k : ℕ} {x : fin k → ℕ} :
6969
x ∈ antidiagonal_tuple k n ↔ ∑ i, x i = n :=
7070
begin
71-
induction k with k ih generalizing n,
72-
{ cases n,
71+
revert n,
72+
refine fin.cons_induction _ _ x,
73+
{ intro n,
74+
cases n,
7375
{ simp },
74-
{ simp [eq_comm] }, },
75-
{ refine fin.cons_induction (λ x₀ x, _) x,
76+
{ simp [eq_comm] } },
77+
{ intros k x₀ x ih n,
7678
simp_rw [fin.sum_cons, antidiagonal_tuple, list.mem_bind, list.mem_map,
77-
list.nat.mem_antidiagonal, fin.cons_eq_cons, exists_eq_right_right, ih, prod.exists],
78-
split,
79-
{ rintros ⟨a, b, rfl, rfl, rfl⟩, refl },
80-
{ rintro rfl, exact ⟨_, _, rfl, rfl, rfl⟩, } },
79+
list.nat.mem_antidiagonal, fin.cons_eq_cons, exists_eq_right_right, ih,
80+
@eq_comm _ _ (prod.snd _), and_comm (prod.snd _ = _), ←prod.mk.inj_iff, prod.mk.eta,
81+
exists_prop, exists_eq_right] },
8182
end
8283

8384
/-- The antidiagonal of `n` does not contain duplicate entries. -/

src/data/list/range.lean

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,21 @@ theorem of_fn_eq_map {α n} {f : fin n → α} :
301301
of_fn f = (fin_range n).map f :=
302302
by rw [← of_fn_id, map_of_fn, function.right_id]
303303

304-
theorem nodup_of_fn {α n} {f : fin n → α} (hf : function.injective f) :
304+
theorem nodup_of_fn_of_injective {α n} {f : fin n → α} (hf : function.injective f) :
305305
nodup (of_fn f) :=
306306
by { rw of_fn_eq_pmap, exact (nodup_range n).pmap (λ _ _ _ _ H, fin.veq_of_eq $ hf H) }
307307

308+
theorem nodup_of_fn {α n} {f : fin n → α} :
309+
nodup (of_fn f) ↔ function.injective f :=
310+
begin
311+
refine ⟨_, nodup_of_fn_of_injective⟩,
312+
refine fin.cons_induction _ (λ n x₀ xs ih, _) f,
313+
{ intro h,
314+
exact function.injective_of_subsingleton _ },
315+
{ intro h,
316+
rw fin.cons_injective_iff,
317+
simp_rw [of_fn_succ, fin.cons_succ, nodup_cons, fin.cons_zero, mem_of_fn] at h,
318+
exact h.imp_right ih }
319+
end
320+
308321
end list

0 commit comments

Comments
 (0)