l3lab/ntp-mathlib huggingface dataset:
/-- `cons` and `snoc` commute. We state this lemma in a non-dependent setting, as otherwise it
would involve a cast to convince Lean that the two types are equal, making it harder to use. -/
theorem cons_snoc_eq_snoc_cons {β : Type*} (a : β) (q : Fin n → β) (b : β) :
    @cons n.succ (fun _ ↦ β) a (snoc q b) = snoc (cons a q) b := by
  ext i
  by_cases h : i = 0
  · rw [h]
    -- Porting note: `refl` finished it here in Lean 3, but I had to add more.
    simp [snoc, castLT]
  set j := pred i h with ji
  have : i = j.succ := by rw [ji, succ_pred]
  rw [this, cons_succ]
  by_cases h' : j.val < n
  · set k := castLT j h' with jk
    have : j = castSucc k := by rw [jk, castSucc_castLT]
    

Proof state:
case pos
m n : ℕ
α : Fin (n + 1) → Type u
x : α (last n)
q✝ : (i : Fin (n + 1)) → α i
p : (i : Fin n) → α (castSucc i)
i✝ : Fin n
y : α (castSucc i✝)
z : α (last n)
β : Type u_1
a : β
q : Fin n → β
b : β
i : Fin (Nat.succ n + 1)
h : ¬i = 0
j : Fin (n + 1) := pred i h
ji : j = pred i h
this✝ : i = succ j
h' : ↑j < n
k : Fin n := castLT j h'
jk : k = castLT j h'
this : j = castSucc k
⊢ snoc q b j = snoc (cons a q) b (succ j)

Next tactic:
rw [this, ← castSucc_fin_succ, snoc]
/-- `cons` and `snoc` commute. We state this lemma in a non-dependent setting, as otherwise it
would involve a cast to convince Lean that the two types are equal, making it harder to use. -/
theorem cons_snoc_eq_snoc_cons {β : Type*} (a : β) (q : Fin n → β) (b : β) :
    @cons n.succ (fun _ ↦ β) a (snoc q b) = snoc (cons a q) b := by
  ext i
  by_cases h : i = 0
  · rw [h]
    -- Porting note: `refl` finished it here in Lean 3, but I had to add more.
    simp [snoc, castLT]
  set j := pred i h with ji
  have : i = j.succ := by rw [ji, succ_pred]
  rw [this, cons_succ]
  by_cases h' : j.val < n
  · set k := castLT j h' with jk
    have : j = castSucc k := by rw [jk, castSucc_castLT]
    rw [this, ← castSucc_fin_succ, snoc]
    

Proof state:
case pos
m n : ℕ
α : Fin (n + 1) → Type u
x : α (last n)
q✝ : (i : Fin (n + 1)) → α i
p : (i : Fin n) → α (castSucc i)
i✝ : Fin n
y : α (castSucc i✝)
z : α (last n)
β : Type u_1
a : β
q : Fin n → β
b : β
i : Fin (Nat.succ n + 1)
h : ¬i = 0
j : Fin (n + 1) := pred i h
ji : j = pred i h
this✝ : i = succ j
h' : ↑j < n
k : Fin n := castLT j h'
jk : k = castLT j h'
this : j = castSucc k
⊢ (if h : ↑(castSucc k) < n then
      _root_.cast (_ : (fun x => β) (succ (castSucc (castLT (castSucc k) h))) = (fun x => β) (succ (castSucc k)))
        (q (castLT (castSucc k) h))
    else _root_.cast (_ : (fun x => β) (succ (last n)) = (fun x => β) (succ (castSucc k))) b) =
    snoc (cons a q) b (castSucc (succ k))

Next tactic:
simp [pred, snoc, cons]
/-- `cons` and `snoc` commute. We state this lemma in a non-dependent setting, as otherwise it
would involve a cast to convince Lean that the two types are equal, making it harder to use. -/
theorem cons_snoc_eq_snoc_cons {β : Type*} (a : β) (q : Fin n → β) (b : β) :
    @cons n.succ (fun _ ↦ β) a (snoc q b) = snoc (cons a q) b := by
  ext i
  by_cases h : i = 0
  · rw [h]
    -- Porting note: `refl` finished it here in Lean 3, but I had to add more.
    simp [snoc, castLT]
  set j := pred i h with ji
  have : i = j.succ := by rw [ji, succ_pred]
  rw [this, cons_succ]
  by_cases h' : j.val < n
  · set k := castLT j h' with jk
    have : j = castSucc k := by rw [jk, castSucc_castLT]
    rw [this, ← castSucc_fin_succ, snoc]
    simp [pred, snoc, cons]
    

Proof state:
case pos
m n : ℕ
α : Fin (n + 1) → Type u
x : α (last n)
q✝ : (i : Fin (n + 1)) → α i
p : (i : Fin n) → α (castSucc i)
i✝ : Fin n
y : α (castSucc i✝)
z : α (last n)
β : Type u_1
a : β
q : Fin n → β
b : β
i : Fin (Nat.succ n + 1)
h : ¬i = 0
j : Fin (n + 1) := pred i h
ji : j = pred i h
this✝ : i = succ j
h' : ↑j < n
k : Fin n := castLT j h'
jk : k = castLT j h'
this : j = castSucc k
⊢ (if h_1 : ↑i - 1 < n then q (castLT (subNat 1 i (_ : 0 < ↑i)) (_ : ↑(subNat 1 i (_ : 0 < ↑i)) < n)) else b) =
    if ↑i - 1 < n then q (castLT (subNat 1 i (_ : 0 < ↑i)) (_ : ↑(subNat 1 i (_ : 0 < ↑i)) < n)) else b

Next tactic:
rfl
/-- `cons` and `snoc` commute. We state this lemma in a non-dependent setting, as otherwise it
would involve a cast to convince Lean that the two types are equal, making it harder to use. -/
theorem cons_snoc_eq_snoc_cons {β : Type*} (a : β) (q : Fin n → β) (b : β) :
    @cons n.succ (fun _ ↦ β) a (snoc q b) = snoc (cons a q) b := by
  ext i
  by_cases h : i = 0
  · rw [h]
    -- Porting note: `refl` finished it here in Lean 3, but I had to add more.
    simp [snoc, castLT]
  set j := pred i h with ji
  have : i = j.succ := by rw [ji, succ_pred]
  rw [this, cons_succ]
  by_cases h' : j.val < n
  · set k := castLT j h' with jk
    have : j = castSucc k := by rw [jk, castSucc_castLT]
    rw [this, ← castSucc_fin_succ, snoc]
    simp [pred, snoc, cons]
    rfl
  

Proof state:
case neg
m n : ℕ
α : Fin (n + 1) → Type u
x : α (last n)
q✝ : (i : Fin (n + 1)) → α i
p : (i : Fin n) → α (castSucc i)
i✝ : Fin n
y : α (castSucc i✝)
z : α (last n)
β : Type u_1
a : β
q : Fin n → β
b : β
i : Fin (Nat.succ n + 1)
h : ¬i = 0
j : Fin (n + 1) := pred i h
ji : j = pred i h
this : i = succ j
h' : ¬↑j < n
⊢ snoc q b j = snoc (cons a q) b (succ j)

Next tactic:
rw [eq_last_of_not_lt h', succ_last]
/-- `cons` and `snoc` commute. We state this lemma in a non-dependent setting, as otherwise it
would involve a cast to convince Lean that the two types are equal, making it harder to use. -/
theorem cons_snoc_eq_snoc_cons {β : Type*} (a : β) (q : Fin n → β) (b : β) :
    @cons n.succ (fun _ ↦ β) a (snoc q b) = snoc (cons a q) b := by
  ext i
  by_cases h : i = 0
  · rw [h]
    -- Porting note: `refl` finished it here in Lean 3, but I had to add more.
    simp [snoc, castLT]
  set j := pred i h with ji
  have : i = j.succ := by rw [ji, succ_pred]
  rw [this, cons_succ]
  by_cases h' : j.val < n
  · set k := castLT j h' with jk
    have : j = castSucc k := by rw [jk, castSucc_castLT]
    rw [this, ← castSucc_fin_succ, snoc]
    simp [pred, snoc, cons]
    rfl
  rw [eq_last_of_not_lt h', succ_last]
  

Proof state:
case neg
m n : ℕ
α : Fin (n + 1) → Type u
x : α (last n)
q✝ : (i : Fin (n + 1)) → α i
p : (i : Fin n) → α (castSucc i)
i✝ : Fin n
y : α (castSucc i✝)
z : α (last n)
β : Type u_1
a : β
q : Fin n → β
b : β
i : Fin (Nat.succ n + 1)
h : ¬i = 0
j : Fin (n + 1) := pred i h
ji : j = pred i h
this : i = succ j
h' : ¬↑j < n
⊢ snoc q b (last n) = snoc (cons a q) b (last (Nat.succ n))

Next tactic:
simp
theorem comp_snoc {α : Type*} {β : Type*} (g : α → β) (q : Fin n → α) (y : α) :
    g ∘ snoc q y = snoc (g ∘ q) (g y) := by
  

Proof state:
m n : ℕ
α✝ : Fin (n + 1) → Type u
x : α✝ (last n)
q✝ : (i : Fin (n + 1)) → α✝ i
p : (i : Fin n) → α✝ (castSucc i)
i : Fin n
y✝ : α✝ (castSucc i)
z : α✝ (last n)
α : Type u_1
β : Type u_2
g : α → β
q : Fin n → α
y : α
⊢ g ∘ snoc q y = snoc (g ∘ q) (g y)

Next tactic:
ext j
theorem comp_snoc {α : Type*} {β : Type*} (g : α → β) (q : Fin n → α) (y : α) :
    g ∘ snoc q y = snoc (g ∘ q) (g y) := by
  ext j
  

Proof state:
case h
m n : ℕ
α✝ : Fin (n + 1) → Type u
x : α✝ (last n)
q✝ : (i : Fin (n + 1)) → α✝ i
p : (i : Fin n) → α✝ (castSucc i)
i : Fin n
y✝ : α✝ (castSucc i)
z : α✝ (last n)
α : Type u_1
β : Type u_2
g : α → β
q : Fin n → α
y : α
j : Fin (n + 1)
⊢ (g ∘ snoc q y) j = snoc (g ∘ q) (g y) j

Next tactic:
by_cases h : j.val < n
theorem comp_snoc {α : Type*} {β : Type*} (g : α → β) (q : Fin n → α) (y : α) :
    g ∘ snoc q y = snoc (g ∘ q) (g y) := by
  ext j
  by_cases h : j.val < n
  · 

Proof state:
case pos
m n : ℕ
α✝ : Fin (n + 1) → Type u
x : α✝ (last n)
q✝ : (i : Fin (n + 1)) → α✝ i
p : (i : Fin n) → α✝ (castSucc i)
i : Fin n
y✝ : α✝ (castSucc i)
z : α✝ (last n)
α : Type u_1
β : Type u_2
g : α → β
q : Fin n → α
y : α
j : Fin (n + 1)
h : ↑j < n
⊢ (g ∘ snoc q y) j = snoc (g ∘ q) (g y) j

Next tactic:
simp [h, snoc, castSucc_castLT]
theorem comp_snoc {α : Type*} {β : Type*} (g : α → β) (q : Fin n → α) (y : α) :
    g ∘ snoc q y = snoc (g ∘ q) (g y) := by
  ext j
  by_cases h : j.val < n
  · simp [h, snoc, castSucc_castLT]
  · 

Proof state:
case neg
m n : ℕ
α✝ : Fin (n + 1) → Type u
x : α✝ (last n)
q✝ : (i : Fin (n + 1)) → α✝ i
p : (i : Fin n) → α✝ (castSucc i)
i : Fin n
y✝ : α✝ (castSucc i)
z : α✝ (last n)
α : Type u_1
β : Type u_2
g : α → β
q : Fin n → α
y : α
j : Fin (n + 1)
h : ¬↑j < n
⊢ (g ∘ snoc q y) j = snoc (g ∘ q) (g y) j

Next tactic:
rw [eq_last_of_not_lt h]
theorem comp_snoc {α : Type*} {β : Type*} (g : α → β) (q : Fin n → α) (y : α) :
    g ∘ snoc q y = snoc (g ∘ q) (g y) := by
  ext j
  by_cases h : j.val < n
  · simp [h, snoc, castSucc_castLT]
  · rw [eq_last_of_not_lt h]
    

Proof state:
case neg
m n : ℕ
α✝ : Fin (n + 1) → Type u
x : α✝ (last n)
q✝ : (i : Fin (n + 1)) → α✝ i
p : (i : Fin n) → α✝ (castSucc i)
i : Fin n
y✝ : α✝ (castSucc i)
z : α✝ (last n)
α : Type u_1
β : Type u_2
g : α → β
q : Fin n → α
y : α
j : Fin (n + 1)
h : ¬↑j < n
⊢ (g ∘ snoc q y) (last n) = snoc (g ∘ q) (g y) (last n)

Next tactic:
simp
/-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/
theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) :
    Fin.append x x₀ = Fin.snoc x (x₀ 0) := by
  

Proof state:
m n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i : Fin n✝
y : α✝ (castSucc i)
z : α✝ (last n✝)
α : Type u_1
n : ℕ
x : Fin n → α
x₀ : Fin 1 → α
⊢ append x x₀ = snoc x (x₀ 0)

Next tactic:
ext i
/-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/
theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) :
    Fin.append x x₀ = Fin.snoc x (x₀ 0) := by
  ext i
  

Proof state:
case h
m n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i✝ : Fin n✝
y : α✝ (castSucc i✝)
z : α✝ (last n✝)
α : Type u_1
n : ℕ
x : Fin n → α
x₀ : Fin 1 → α
i : Fin (n + 1)
⊢ append x x₀ i = snoc x (x₀ 0) i

Next tactic:
refine' Fin.addCases _ _ i
/-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/
theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) :
    Fin.append x x₀ = Fin.snoc x (x₀ 0) := by
  ext i
  refine' Fin.addCases _ _ i <;> 

Proof state:
case h.refine'_1
m n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i✝ : Fin n✝
y : α✝ (castSucc i✝)
z : α✝ (last n✝)
α : Type u_1
n : ℕ
x : Fin n → α
x₀ : Fin 1 → α
i : Fin (n + 1)
⊢ ∀ (i : Fin n), append x x₀ (castAdd 1 i) = snoc x (x₀ 0) (castAdd 1 i)

Next tactic:
clear i
/-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/
theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) :
    Fin.append x x₀ = Fin.snoc x (x₀ 0) := by
  ext i
  refine' Fin.addCases _ _ i <;> 

Proof state:
case h.refine'_2
m n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i✝ : Fin n✝
y : α✝ (castSucc i✝)
z : α✝ (last n✝)
α : Type u_1
n : ℕ
x : Fin n → α
x₀ : Fin 1 → α
i : Fin (n + 1)
⊢ ∀ (i : Fin 1), append x x₀ (natAdd n i) = snoc x (x₀ 0) (natAdd n i)

Next tactic:
clear i
/-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/
theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) :
    Fin.append x x₀ = Fin.snoc x (x₀ 0) := by
  ext i
  refine' Fin.addCases _ _ i <;> clear i
  · 

Proof state:
case h.refine'_1
m n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i : Fin n✝
y : α✝ (castSucc i)
z : α✝ (last n✝)
α : Type u_1
n : ℕ
x : Fin n → α
x₀ : Fin 1 → α
⊢ ∀ (i : Fin n), append x x₀ (castAdd 1 i) = snoc x (x₀ 0) (castAdd 1 i)

Next tactic:
intro i
/-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/
theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) :
    Fin.append x x₀ = Fin.snoc x (x₀ 0) := by
  ext i
  refine' Fin.addCases _ _ i <;> clear i
  · intro i
    

Proof state:
case h.refine'_1
m n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i✝ : Fin n✝
y : α✝ (castSucc i✝)
z : α✝ (last n✝)
α : Type u_1
n : ℕ
x : Fin n → α
x₀ : Fin 1 → α
i : Fin n
⊢ append x x₀ (castAdd 1 i) = snoc x (x₀ 0) (castAdd 1 i)

Next tactic:
rw [Fin.append_left]
/-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/
theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) :
    Fin.append x x₀ = Fin.snoc x (x₀ 0) := by
  ext i
  refine' Fin.addCases _ _ i <;> clear i
  · intro i
    rw [Fin.append_left]
    

Proof state:
case h.refine'_1
m n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i✝ : Fin n✝
y : α✝ (castSucc i✝)
z : α✝ (last n✝)
α : Type u_1
n : ℕ
x : Fin n → α
x₀ : Fin 1 → α
i : Fin n
⊢ x i = snoc x (x₀ 0) (castAdd 1 i)

Next tactic:
exact (@snoc_castSucc _ (fun _ => α) _ _ i).symm
/-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/
theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) :
    Fin.append x x₀ = Fin.snoc x (x₀ 0) := by
  ext i
  refine' Fin.addCases _ _ i <;> clear i
  · intro i
    rw [Fin.append_left]
    exact (@snoc_castSucc _ (fun _ => α) _ _ i).symm
  · 

Proof state:
case h.refine'_2
m n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i : Fin n✝
y : α✝ (castSucc i)
z : α✝ (last n✝)
α : Type u_1
n : ℕ
x : Fin n → α
x₀ : Fin 1 → α
⊢ ∀ (i : Fin 1), append x x₀ (natAdd n i) = snoc x (x₀ 0) (natAdd n i)

Next tactic:
intro i
/-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/
theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) :
    Fin.append x x₀ = Fin.snoc x (x₀ 0) := by
  ext i
  refine' Fin.addCases _ _ i <;> clear i
  · intro i
    rw [Fin.append_left]
    exact (@snoc_castSucc _ (fun _ => α) _ _ i).symm
  · intro i
    

Proof state:
case h.refine'_2
m n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i✝ : Fin n✝
y : α✝ (castSucc i✝)
z : α✝ (last n✝)
α : Type u_1
n : ℕ
x : Fin n → α
x₀ : Fin 1 → α
i : Fin 1
⊢ append x x₀ (natAdd n i) = snoc x (x₀ 0) (natAdd n i)

Next tactic:
rw [Subsingleton.elim i 0, Fin.append_right]
/-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/
theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) :
    Fin.append x x₀ = Fin.snoc x (x₀ 0) := by
  ext i
  refine' Fin.addCases _ _ i <;> clear i
  · intro i
    rw [Fin.append_left]
    exact (@snoc_castSucc _ (fun _ => α) _ _ i).symm
  · intro i
    rw [Subsingleton.elim i 0, Fin.append_right]
    

Proof state:
case h.refine'_2
m n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i✝ : Fin n✝
y : α✝ (castSucc i✝)
z : α✝ (last n✝)
α : Type u_1
n : ℕ
x : Fin n → α
x₀ : Fin 1 → α
i : Fin 1
⊢ x₀ 0 = snoc x (x₀ 0) (natAdd n 0)

Next tactic:
exact (@snoc_last _ (fun _ => α) _ _).symm
theorem append_left_snoc {n m} {α : Type*} (xs : Fin n → α) (x : α) (ys : Fin m → α) :
    Fin.append (Fin.snoc xs x) ys =
      Fin.append xs (Fin.cons x ys) ∘ Fin.cast (Nat.succ_add_eq_add_succ ..) := by
  

Proof state:
m✝ n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i : Fin n✝
y : α✝ (castSucc i)
z : α✝ (last n✝)
n m : ℕ
α : Type u_1
xs : Fin n → α
x : α
ys : Fin m → α
⊢ append (snoc xs x) ys = append xs (cons x ys) ∘ cast (_ : Nat.succ n + m = n + Nat.succ m)

Next tactic:
rw [snoc_eq_append, append_assoc, append_left_eq_cons, append_cast_right]
theorem append_left_snoc {n m} {α : Type*} (xs : Fin n → α) (x : α) (ys : Fin m → α) :
    Fin.append (Fin.snoc xs x) ys =
      Fin.append xs (Fin.cons x ys) ∘ Fin.cast (Nat.succ_add_eq_add_succ ..) := by
  rw [snoc_eq_append, append_assoc, append_left_eq_cons, append_cast_right]; 

Proof state:
m✝ n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x✝ : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i : Fin n✝
y : α✝ (castSucc i)
z : α✝ (last n✝)
n m : ℕ
α : Type u_1
xs : Fin n → α
x : α
ys : Fin m → α
⊢ (append xs (cons (cons x elim0 0) ys) ∘ cast (_ : n + (0 + 1 + m) = n + (m + 1))) ∘
      cast (_ : n + (0 + 1) + m = n + (0 + 1 + m)) =
    append xs (cons x ys) ∘ cast (_ : Nat.succ n + m = n + Nat.succ m)

Next tactic:
rfl
theorem append_right_cons {n m} {α : Type*} (xs : Fin n → α) (y : α) (ys : Fin m → α) :
    Fin.append xs (Fin.cons y ys) =
      Fin.append (Fin.snoc xs y) ys ∘ Fin.cast (Nat.succ_add_eq_add_succ ..).symm := by
  

Proof state:
m✝ n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i : Fin n✝
y✝ : α✝ (castSucc i)
z : α✝ (last n✝)
n m : ℕ
α : Type u_1
xs : Fin n → α
y : α
ys : Fin m → α
⊢ append xs (cons y ys) = append (snoc xs y) ys ∘ cast (_ : n + Nat.succ m = Nat.succ n + m)

Next tactic:
rw [append_left_snoc]
theorem append_right_cons {n m} {α : Type*} (xs : Fin n → α) (y : α) (ys : Fin m → α) :
    Fin.append xs (Fin.cons y ys) =
      Fin.append (Fin.snoc xs y) ys ∘ Fin.cast (Nat.succ_add_eq_add_succ ..).symm := by
  rw [append_left_snoc]; 

Proof state:
m✝ n✝ : ℕ
α✝ : Fin (n✝ + 1) → Type u
x : α✝ (last n✝)
q : (i : Fin (n✝ + 1)) → α✝ i
p : (i : Fin n✝) → α✝ (castSucc i)
i : Fin n✝
y✝ : α✝ (castSucc i)
z : α✝ (last n✝)
n m : ℕ
α : Type u_1
xs : Fin n → α
y : α
ys : Fin m → α
⊢ append xs (cons y ys) =
    (append xs (cons y ys) ∘ cast (_ : Nat.succ n + m = n + Nat.succ m)) ∘ cast (_ : n + Nat.succ m = Nat.succ n + m)

Next tactic:
rfl
theorem comp_init {α : Type*} {β : Type*} (g : α → β) (q : Fin n.succ → α) :
    g ∘ init q = init (g ∘ q) := by
  

Proof state:
m n : ℕ
α✝ : Fin (n + 1) → Type u
x : α✝ (last n)
q✝ : (i : Fin (n + 1)) → α✝ i
p : (i : Fin n) → α✝ (castSucc i)
i : Fin n
y : α✝ (castSucc i)
z : α✝ (last n)
α : Type u_1
β : Type u_2
g : α → β
q : Fin (Nat.succ n) → α
⊢ g ∘ init q = init (g ∘ q)

Next tactic:
ext j
theorem comp_init {α : Type*} {β : Type*} (g : α → β) (q : Fin n.succ → α) :
    g ∘ init q = init (g ∘ q) := by
  ext j
  

Proof state:
case h
m n : ℕ
α✝ : Fin (n + 1) → Type u
x : α✝ (last n)
q✝ : (i : Fin (n + 1)) → α✝ i
p : (i : Fin n) → α✝ (castSucc i)
i : Fin n
y : α✝ (castSucc i)
z : α✝ (last n)
α : Type u_1
β : Type u_2
g : α → β
q : Fin (Nat.succ n) → α
j : Fin n
⊢ (g ∘ init q) j = init (g ∘ q) j

Next tactic:
simp [init]
/-- Recurse on an `n+1`-tuple by splitting it its initial `n`-tuple and its last element. -/
@[elab_as_elim, inline]
def snocCases {P : (∀ i : Fin n.succ, α i) → Sort*}
    (h : ∀ xs x, P (Fin.snoc xs x))
    (x : ∀ i : Fin n.succ, α i) : P x :=
  _root_.cast (by 

Proof state:
m n : ℕ
α : Fin (n + 1) → Type u
x✝ : α (last n)
q : (i : Fin (n + 1)) → α i
p : (i : Fin n) → α (castSucc i)
i : Fin n
y : α (castSucc i)
z : α (last n)
P : ((i : Fin (Nat.succ n)) → α i) → Sort u_1
h : (xs : (i : Fin n) → α (castSucc i)) → (x : α (last n)) → P (snoc xs x)
x : (i : Fin (Nat.succ n)) → α i
⊢ P (snoc (init x) (x (last n))) = P x

Next tactic:
rw [Fin.snoc_init_self]
@[simp] lemma snocCases_snoc
    {P : (∀ i : Fin (n+1), α i) → Sort*} (h : ∀ x x₀, P (Fin.snoc x x₀))
    (x : ∀ i : Fin n, (Fin.init α) i) (x₀ : α (Fin.last _)) :
    snocCases h (Fin.snoc x x₀) = h x x₀ := by
  

Proof state:
m n : ℕ
α : Fin (n + 1) → Type u
x✝ : α (last n)
q : (i : Fin (n + 1)) → α i
p : (i : Fin n) → α (castSucc i)
i : Fin n
y : α (castSucc i)
z : α (last n)
P : ((i : Fin (n + 1)) → α i) → Sort u_1
h : (x : (i : Fin n) → α (castSucc i)) → (x₀ : α (last n)) → P (snoc x x₀)
x : (i : Fin n) → init α i
x₀ : α (last n)
⊢ snocCases h (snoc x x₀) = h x x₀

Next tactic:
rw [snocCases, cast_eq_iff_heq, Fin.init_snoc, Fin.snoc_last]
/-- Recurse on a tuple by splitting into `Fin.elim0` and `Fin.snoc`. -/
@[elab_as_elim]
def snocInduction {α : Type*}
    {P : ∀ {n : ℕ}, (Fin n → α) → Sort*}
    (h0 : P Fin.elim0)
    (h : ∀ {n} (x : Fin n → α) (x₀), P x → P (Fin.snoc x x₀)) : ∀ {n : ℕ} (x : Fin n → α), P x
  | 0, x => by 

Proof state:
m n : ℕ
α✝ : Fin (n + 1) → Type u
x✝ : α✝ (last n)
q : (i : Fin (n + 1)) → α✝ i
p : (i : Fin n) → α✝ (castSucc i)
i : Fin n
y : α✝ (castSucc i)
z : α✝ (last n)
α : Type u_1
P : {n : ℕ} → (Fin n → α) → Sort u_2
h0 : P elim0
h : {n : ℕ} → (x : Fin n → α) → (x₀ : α) → P x → P (snoc x x₀)
x : Fin 0 → α
⊢ P x

Next tactic:
convert h0
@[simp]
theorem insertNth_apply_same (i : Fin (n + 1)) (x : α i) (p : ∀ j, α (i.succAbove j)) :
    insertNth i x p i = x := by 

Proof state:
m n : ℕ
α : Fin (n + 1) → Type u
β : Type v
i : Fin (n + 1)
x : α i
p : (j : Fin n) → α (succAbove i j)
⊢ insertNth i x p i = x

Next tactic:
simp [insertNth, succAboveCases]
@[simp]
theorem insertNth_apply_succAbove (i : Fin (n + 1)) (x : α i) (p : ∀ j, α (i.succAbove j))
    (j : Fin n) : insertNth i x p (i.succAbove j) = p j := by
  

Proof state:
m n : ℕ
α : Fin (n + 1) → Type u
β : Type v
i : Fin (n + 1)
x : α i
p : (j : Fin n) → α (succAbove i j)
j : Fin n
⊢ insertNth i x p (succAbove i j) = p j

Next tactic:
simp only [insertNth, succAboveCases, dif_neg (succAbove_ne _ _), succAbove_lt_iff]
@[simp]
theorem insertNth_apply_succAbove (i : Fin (n + 1)) (x : α i) (p : ∀ j, α (i.succAbove j))
    (j : Fin n) : insertNth i x p (i.succAbove j) = p j := by
  simp only [insertNth, succAboveCases, dif_neg (succAbove_ne _ _), succAbove_lt_iff]
  

Proof state:
m n : ℕ
α : Fin (n + 1) → Type u
β : Type v
i : Fin (n + 1)
x : α i
p : (j : Fin n) → α (succAbove i j)
j : Fin n
⊢ (if h : castSucc j < i then
      (_ : succAbove i (castLT (succAbove i j) (_ : ↑(succAbove i j) < n)) = succAbove i j) ▸
        p (castLT (succAbove i j) (_ : ↑(succAbove i j) < n))
    else
      (_ : succAbove i (pred (succAbove i j) (_ : succAbove i j ≠ 0)) = succAbove i j) ▸
        p (pred (succAbove i j) (_ : succAbove i j ≠ 0))) =
    p j

Next tactic:
split_ifs with hlt
@[simp]
theorem insertNth_apply_succAbove (i : Fin (n + 1)) (x : α i) (p : ∀ j, α (i.succAbove j))
    (j : Fin n) : insertNth i x p (i.succAbove j) = p j := by
  simp only [insertNth, succAboveCases, dif_neg (succAbove_ne _ _), succAbove_lt_iff]
  split_ifs with hlt
  · 

Proof state:
case pos
m n : ℕ
α : Fin (n + 1) → Type u
β : Type v
i : Fin (n + 1)
x : α i
p : (j : Fin n) → α (succAbove i j)
j : Fin n
hlt : castSucc j < i
⊢ (_ : succAbove i (castLT (succAbove i j) (_ : ↑(succAbove i j) < n)) = succAbove i j) ▸
      p (castLT (succAbove i j) (_ : ↑(succAbove i j) < n)) =
    p j

Next tactic:
generalize_proofs H₁ H₂
@[simp]
theorem insertNth_apply_succAbove (i : Fin (n + 1)) (x : α i) (p : ∀ j, α (i.succAbove j))
    (j : Fin n) : insertNth i x p (i.succAbove j) = p j := by
  simp only [insertNth, succAboveCases, dif_neg (succAbove_ne _ _), succAbove_lt_iff]
  split_ifs with hlt
  · generalize_proofs H₁ H₂; 

Proof state:
case pos
m n : ℕ
α : Fin (n + 1) → Type u
β : Type v
i : Fin (n + 1)
x : α i
p : (j : Fin n) → α (succAbove i j)
j : Fin n
hlt : castSucc j < i
H₁ : ↑(succAbove i j) < n
H₂ : succAbove i (castLT (succAbove i j) (_ : ↑(succAbove i j) < n)) = succAbove i j
⊢ H₂ ▸ p (castLT (succAbove i j) H₁) = p j

Next tactic:
revert H₂
@[simp]
theorem insertNth_apply_succAbove (i : Fin (n + 1)) (x : α i) (p : ∀ j, α (i.succAbove j))
    (j : Fin n) : insertNth i x p (i.succAbove j) = p j := by
  simp only [insertNth, succAboveCases, dif_neg (succAbove_ne _ _), succAbove_lt_iff]
  split_ifs with hlt
  · generalize_proofs H₁ H₂; revert H₂
    

Proof state:
case pos
m n : ℕ
α : Fin (n + 1) → Type u
β : Type v
i : Fin (n + 1)
x : α i
p : (j : Fin n) → α (succAbove i j)
j : Fin n
hlt : castSucc j < i
H₁ : ↑(succAbove i j) < n
⊢ ∀ (H₂ : succAbove i (castLT (succAbove i j) (_ : ↑(succAbove i j) < n)) = succAbove i j),
    H₂ ▸ p (castLT (succAbove i j) H₁) = p j

Next tactic:
generalize hk : castLT ((succAbove i) j) H₁ = k