l3lab/ntp-mathlib huggingface dataset:
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
      rw [← List.insertNth_removeNth_of_ge]
      · simp; rfl
      · simpa
      · 

Proof state:
case pos.intro.a
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : Nat.succ j < n + 2
hij : i < Nat.succ j
⊢ ↑{ val := i, isLt := (_ : i < Nat.succ (n + 1)) } ≤ j

Next tactic:
simpa [Nat.lt_succ_iff] using hij
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
      rw [← List.insertNth_removeNth_of_ge]
      · simp; rfl
      · simpa
      · simpa [Nat.lt_succ_iff] using hij
    · 

Proof state:
case neg
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : j < n + 2
hij : ¬i < j
⊢ List.removeNth (List.insertNth j a ↑v) ↑{ val := i + 1, isLt := (_ : Nat.succ i < Nat.succ (n + 1)) } =
    List.insertNth (↑{ val := j, isLt := (_ : ↑{ val := j, isLt := hj } < n + 1) }) a
      ↑(match v with
        | { val := l, property := p } =>
          { val := List.removeNth l i,
            property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) })

Next tactic:
dsimp
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
      rw [← List.insertNth_removeNth_of_ge]
      · simp; rfl
      · simpa
      · simpa [Nat.lt_succ_iff] using hij
    · dsimp
      

Proof state:
case neg
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : j < n + 2
hij : ¬i < j
⊢ List.removeNth (List.insertNth j a ↑v) (i + 1) =
    List.insertNth j a
      ↑(match v with
        | { val := l, property := p } =>
          { val := List.removeNth l i,
            property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) })

Next tactic:
rw [← List.insertNth_removeNth_of_le i j _ _ _]
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
      rw [← List.insertNth_removeNth_of_ge]
      · simp; rfl
      · simpa
      · simpa [Nat.lt_succ_iff] using hij
    · dsimp
      rw [← List.insertNth_removeNth_of_le i j _ _ _]
      · 

Proof state:
case neg
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : j < n + 2
hij : ¬i < j
⊢ List.insertNth j a (List.removeNth (↑v) i) =
    List.insertNth j a
      ↑(match v with
        | { val := l, property := p } =>
          { val := List.removeNth l i,
            property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) })

Next tactic:
rfl
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
      rw [← List.insertNth_removeNth_of_ge]
      · simp; rfl
      · simpa
      · simpa [Nat.lt_succ_iff] using hij
    · dsimp
      rw [← List.insertNth_removeNth_of_le i j _ _ _]
      · rfl
      · 

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : j < n + 2
hij : ¬i < j
⊢ i < List.length ↑v

Next tactic:
simpa
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
      rw [← List.insertNth_removeNth_of_ge]
      · simp; rfl
      · simpa
      · simpa [Nat.lt_succ_iff] using hij
    · dsimp
      rw [← List.insertNth_removeNth_of_le i j _ _ _]
      · rfl
      · simpa
      · 

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : j < n + 2
hij : ¬i < j
⊢ j ≤ i

Next tactic:
simpa [not_lt] using hij
theorem insertNth_comm (a b : α) (i j : Fin (n + 1)) (h : i ≤ j) :
    ∀ v : Vector α n,
      (v.insertNth a i).insertNth b j.succ = (v.insertNth b j).insertNth a (Fin.castSucc i)
  | ⟨l, hl⟩ => by
    

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a✝ a b : α
i j : Fin (n + 1)
h : i ≤ j
l : List α
hl : List.length l = n
⊢ insertNth b (Fin.succ j) (insertNth a i { val := l, property := hl }) =
    insertNth a (Fin.castSucc i) (insertNth b j { val := l, property := hl })

Next tactic:
refine' Subtype.eq _
theorem insertNth_comm (a b : α) (i j : Fin (n + 1)) (h : i ≤ j) :
    ∀ v : Vector α n,
      (v.insertNth a i).insertNth b j.succ = (v.insertNth b j).insertNth a (Fin.castSucc i)
  | ⟨l, hl⟩ => by
    refine' Subtype.eq _
    

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a✝ a b : α
i j : Fin (n + 1)
h : i ≤ j
l : List α
hl : List.length l = n
⊢ ↑(insertNth b (Fin.succ j) (insertNth a i { val := l, property := hl })) =
    ↑(insertNth a (Fin.castSucc i) (insertNth b j { val := l, property := hl }))

Next tactic:
simp only [insertNth_val, Fin.val_succ, Fin.castSucc, Fin.coe_castAdd]
theorem insertNth_comm (a b : α) (i j : Fin (n + 1)) (h : i ≤ j) :
    ∀ v : Vector α n,
      (v.insertNth a i).insertNth b j.succ = (v.insertNth b j).insertNth a (Fin.castSucc i)
  | ⟨l, hl⟩ => by
    refine' Subtype.eq _
    simp only [insertNth_val, Fin.val_succ, Fin.castSucc, Fin.coe_castAdd]
    

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a✝ a b : α
i j : Fin (n + 1)
h : i ≤ j
l : List α
hl : List.length l = n
⊢ List.insertNth (↑j + 1) b (List.insertNth (↑i) a l) = List.insertNth (↑i) a (List.insertNth (↑j) b l)

Next tactic:
apply List.insertNth_comm
theorem insertNth_comm (a b : α) (i j : Fin (n + 1)) (h : i ≤ j) :
    ∀ v : Vector α n,
      (v.insertNth a i).insertNth b j.succ = (v.insertNth b j).insertNth a (Fin.castSucc i)
  | ⟨l, hl⟩ => by
    refine' Subtype.eq _
    simp only [insertNth_val, Fin.val_succ, Fin.castSucc, Fin.coe_castAdd]
    apply List.insertNth_comm
    · 

Proof state:
case x
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a✝ a b : α
i j : Fin (n + 1)
h : i ≤ j
l : List α
hl : List.length l = n
⊢ ↑i ≤ ↑j

Next tactic:
assumption
theorem insertNth_comm (a b : α) (i j : Fin (n + 1)) (h : i ≤ j) :
    ∀ v : Vector α n,
      (v.insertNth a i).insertNth b j.succ = (v.insertNth b j).insertNth a (Fin.castSucc i)
  | ⟨l, hl⟩ => by
    refine' Subtype.eq _
    simp only [insertNth_val, Fin.val_succ, Fin.castSucc, Fin.coe_castAdd]
    apply List.insertNth_comm
    · assumption
    · 

Proof state:
case x
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a✝ a b : α
i j : Fin (n + 1)
h : i ≤ j
l : List α
hl : List.length l = n
⊢ ↑j ≤ List.length l

Next tactic:
rw [hl]
theorem insertNth_comm (a b : α) (i j : Fin (n + 1)) (h : i ≤ j) :
    ∀ v : Vector α n,
      (v.insertNth a i).insertNth b j.succ = (v.insertNth b j).insertNth a (Fin.castSucc i)
  | ⟨l, hl⟩ => by
    refine' Subtype.eq _
    simp only [insertNth_val, Fin.val_succ, Fin.castSucc, Fin.coe_castAdd]
    apply List.insertNth_comm
    · assumption
    · rw [hl]
      

Proof state:
case x
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a✝ a b : α
i j : Fin (n + 1)
h : i ≤ j
l : List α
hl : List.length l = n
⊢ ↑j ≤ n

Next tactic:
exact Nat.le_of_succ_le_succ j.2
/-- `set v n a` replaces the `n`th element of `v` with `a` -/
def set (v : Vector α n) (i : Fin n) (a : α) : Vector α n :=
  ⟨v.1.set i.1 a, by 

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
v : Vector α n
i : Fin n
a : α
⊢ List.length (List.set (↑v) (↑i) a) = n

Next tactic:
simp
@[simp]
theorem get_set_same (v : Vector α n) (i : Fin n) (a : α) : (v.set i a).get i = a := by
  

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
v : Vector α n
i : Fin n
a : α
⊢ get (set v i a) i = a

Next tactic:
cases v
@[simp]
theorem get_set_same (v : Vector α n) (i : Fin n) (a : α) : (v.set i a).get i = a := by
  cases v; 

Proof state:
case mk
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
i : Fin n
a : α
val✝ : List α
property✝ : List.length val✝ = n
⊢ get (set { val := val✝, property := property✝ } i a) i = a

Next tactic:
cases i
@[simp]
theorem get_set_same (v : Vector α n) (i : Fin n) (a : α) : (v.set i a).get i = a := by
  cases v; cases i; 

Proof state:
case mk.mk
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
val✝¹ : List α
property✝ : List.length val✝¹ = n
val✝ : ℕ
isLt✝ : val✝ < n
⊢ get (set { val := val✝¹, property := property✝ } { val := val✝, isLt := isLt✝ } a) { val := val✝, isLt := isLt✝ } = a

Next tactic:
simp [Vector.set, get_eq_get]
theorem get_set_of_ne {v : Vector α n} {i j : Fin n} (h : i ≠ j) (a : α) :
    (v.set i a).get j = v.get j := by
  

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
v : Vector α n
i j : Fin n
h : i ≠ j
a : α
⊢ get (set v i a) j = get v j

Next tactic:
cases v
theorem get_set_of_ne {v : Vector α n} {i j : Fin n} (h : i ≠ j) (a : α) :
    (v.set i a).get j = v.get j := by
  cases v; 

Proof state:
case mk
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
i j : Fin n
h : i ≠ j
a : α
val✝ : List α
property✝ : List.length val✝ = n
⊢ get (set { val := val✝, property := property✝ } i a) j = get { val := val✝, property := property✝ } j

Next tactic:
cases i
theorem get_set_of_ne {v : Vector α n} {i j : Fin n} (h : i ≠ j) (a : α) :
    (v.set i a).get j = v.get j := by
  cases v; cases i; 

Proof state:
case mk.mk
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
j : Fin n
a : α
val✝¹ : List α
property✝ : List.length val✝¹ = n
val✝ : ℕ
isLt✝ : val✝ < n
h : { val := val✝, isLt := isLt✝ } ≠ j
⊢ get (set { val := val✝¹, property := property✝ } { val := val✝, isLt := isLt✝ } a) j =
    get { val := val✝¹, property := property✝ } j

Next tactic:
cases j
theorem get_set_of_ne {v : Vector α n} {i j : Fin n} (h : i ≠ j) (a : α) :
    (v.set i a).get j = v.get j := by
  cases v; cases i; cases j
  

Proof state:
case mk.mk.mk
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
val✝² : List α
property✝ : List.length val✝² = n
val✝¹ : ℕ
isLt✝¹ : val✝¹ < n
val✝ : ℕ
isLt✝ : val✝ < n
h : { val := val✝¹, isLt := isLt✝¹ } ≠ { val := val✝, isLt := isLt✝ }
⊢ get (set { val := val✝², property := property✝ } { val := val✝¹, isLt := isLt✝¹ } a) { val := val✝, isLt := isLt✝ } =
    get { val := val✝², property := property✝ } { val := val✝, isLt := isLt✝ }

Next tactic:
simp only [set, get_eq_get, toList_mk, Fin.cast_mk, ne_eq]
theorem get_set_of_ne {v : Vector α n} {i j : Fin n} (h : i ≠ j) (a : α) :
    (v.set i a).get j = v.get j := by
  cases v; cases i; cases j
  simp only [set, get_eq_get, toList_mk, Fin.cast_mk, ne_eq]
  

Proof state:
case mk.mk.mk
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
val✝² : List α
property✝ : List.length val✝² = n
val✝¹ : ℕ
isLt✝¹ : val✝¹ < n
val✝ : ℕ
isLt✝ : val✝ < n
h : { val := val✝¹, isLt := isLt✝¹ } ≠ { val := val✝, isLt := isLt✝ }
⊢ List.get (List.set val✝² val✝¹ a)
      { val := val✝,
        isLt :=
          (_ :
            val✝ <
              List.length
                (toList
                  { val := List.set val✝² val✝¹ a,
                    property :=
                      (_ :
                        List.length
                            (List.set (↑{ val := val✝², property := property✝ }) (↑{ val := val✝¹, isLt := isLt✝¹ })
                              a) =
                          n) })) } =
    List.get val✝² { val := val✝, isLt := (_ : val✝ < List.length (toList { val := val✝², property := property✝ })) }

Next tactic:
rw [List.get_set_of_ne]
theorem get_set_of_ne {v : Vector α n} {i j : Fin n} (h : i ≠ j) (a : α) :
    (v.set i a).get j = v.get j := by
  cases v; cases i; cases j
  simp only [set, get_eq_get, toList_mk, Fin.cast_mk, ne_eq]
  rw [List.get_set_of_ne]
  · 

Proof state:
case mk.mk.mk.h
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
val✝² : List α
property✝ : List.length val✝² = n
val✝¹ : ℕ
isLt✝¹ : val✝¹ < n
val✝ : ℕ
isLt✝ : val✝ < n
h : { val := val✝¹, isLt := isLt✝¹ } ≠ { val := val✝, isLt := isLt✝ }
⊢ val✝¹ ≠ val✝

Next tactic:
simpa using h
theorem get_set_eq_if {v : Vector α n} {i j : Fin n} (a : α) :
    (v.set i a).get j = if i = j then a else v.get j := by
  

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
v : Vector α n
i j : Fin n
a : α
⊢ get (set v i a) j = if i = j then a else get v j

Next tactic:
split_ifs
theorem get_set_eq_if {v : Vector α n} {i j : Fin n} (a : α) :
    (v.set i a).get j = if i = j then a else v.get j := by
  split_ifs <;> (

Proof state:
case pos
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
v : Vector α n
i j : Fin n
a : α
h✝ : i = j
⊢ get (set v i a) j = a

Next tactic:
try simp [*]
theorem get_set_eq_if {v : Vector α n} {i j : Fin n} (a : α) :
    (v.set i a).get j = if i = j then a else v.get j := by
  split_ifs <;> (try 

Proof state:
case pos
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
v : Vector α n
i j : Fin n
a : α
h✝ : i = j
⊢ get (set v i a) j = a

Next tactic:
simp [*]
theorem get_set_eq_if {v : Vector α n} {i j : Fin n} (a : α) :
    (v.set i a).get j = if i = j then a else v.get j := by
  split_ifs <;> (

Proof state:
case neg
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
v : Vector α n
i j : Fin n
a : α
h✝ : ¬i = j
⊢ get (set v i a) j = get v j

Next tactic:
try simp [*]
theorem get_set_eq_if {v : Vector α n} {i j : Fin n} (a : α) :
    (v.set i a).get j = if i = j then a else v.get j := by
  split_ifs <;> (try 

Proof state:
case neg
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
v : Vector α n
i j : Fin n
a : α
h✝ : ¬i = j
⊢ get (set v i a) j = get v j

Next tactic:
simp [*]
theorem get_set_eq_if {v : Vector α n} {i j : Fin n} (a : α) :
    (v.set i a).get j = if i = j then a else v.get j := by
  split_ifs <;> (try simp [*]); 

Proof state:
case neg
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
v : Vector α n
i j : Fin n
a : α
h✝ : ¬i = j
⊢ get (set v i a) j = get v j

Next tactic:
rwa [get_set_of_ne]
@[to_additive]
theorem prod_set [Monoid α] (v : Vector α n) (i : Fin n) (a : α) :
    (v.set i a).toList.prod = (v.take i).toList.prod * a * (v.drop (i + 1)).toList.prod := by
  

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Monoid α
v : Vector α n
i : Fin n
a : α
⊢ List.prod (toList (set v i a)) = List.prod (toList (take (↑i) v)) * a * List.prod (toList (drop (↑i + 1) v))

Next tactic:
refine' (List.prod_set v.toList i a).trans _
@[to_additive]
theorem prod_set [Monoid α] (v : Vector α n) (i : Fin n) (a : α) :
    (v.set i a).toList.prod = (v.take i).toList.prod * a * (v.drop (i + 1)).toList.prod := by
  refine' (List.prod_set v.toList i a).trans _
  

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Monoid α
v : Vector α n
i : Fin n
a : α
⊢ (List.prod (List.take (↑i) (toList v)) * if ↑i < List.length (toList v) then a else 1) *
      List.prod (List.drop (↑i + 1) (toList v)) =
    List.prod (toList (take (↑i) v)) * a * List.prod (toList (drop (↑i + 1) v))

Next tactic:
simp_all
@[to_additive]
theorem prod_set' [CommGroup α] (v : Vector α n) (i : Fin n) (a : α) :
    (v.set i a).toList.prod = v.toList.prod * (v.get i)⁻¹ * a := by
  

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : CommGroup α
v : Vector α n
i : Fin n
a : α
⊢ List.prod (toList (set v i a)) = List.prod (toList v) * (get v i)⁻¹ * a

Next tactic:
refine' (List.prod_set' v.toList i a).trans _
@[to_additive]
theorem prod_set' [CommGroup α] (v : Vector α n) (i : Fin n) (a : α) :
    (v.set i a).toList.prod = v.toList.prod * (v.get i)⁻¹ * a := by
  refine' (List.prod_set' v.toList i a).trans _
  

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : CommGroup α
v : Vector α n
i : Fin n
a : α
⊢ (List.prod (toList v) *
      if hn : ↑i < List.length (toList v) then (List.get (toList v) { val := ↑i, isLt := hn })⁻¹ * a else 1) =
    List.prod (toList v) * (get v i)⁻¹ * a

Next tactic:
simp [get_eq_get, mul_assoc]
@[to_additive]
theorem prod_set' [CommGroup α] (v : Vector α n) (i : Fin n) (a : α) :
    (v.set i a).toList.prod = v.toList.prod * (v.get i)⁻¹ * a := by
  refine' (List.prod_set' v.toList i a).trans _
  simp [get_eq_get, mul_assoc]; 

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : CommGroup α
v : Vector α n
i : Fin n
a : α
⊢ List.get (toList v) { val := ↑i, isLt := (_ : ↑i < List.length (toList v)) } =
    List.get (toList v) (Fin.cast (_ : n = List.length (toList v)) i)

Next tactic:
rfl
/-- Apply an applicative function to each component of a vector. -/
protected def traverse {α β : Type u} (f : α → F β) : Vector α n → F (Vector β n)
  | ⟨v, Hv⟩ => cast (by 

Proof state:
n : ℕ
F G : Type u → Type u
inst✝¹ : Applicative F
inst✝ : Applicative G
α β : Type u
f : α → F β
v : List α
Hv : List.length v = n
⊢ F (Vector β (List.length v)) = F (Vector β n)

Next tactic:
rw [Hv]
@[simp]
protected theorem traverse_def (f : α → F β) (x : α) :
    ∀ xs : Vector α n, (x ::ᵥ xs).traverse f = cons <$> f x <*> xs.traverse f := by
  

Proof state:
n : ℕ
F G : Type u → Type u
inst✝¹ : Applicative F
inst✝ : Applicative G
α β : Type u
f : α → F β
x : α
⊢ ∀ (xs : Vector α n), Vector.traverse f (x ::ᵥ xs) = Seq.seq (cons <$> f x) fun x => Vector.traverse f xs

Next tactic:
rintro ⟨xs, rfl⟩
@[simp]
protected theorem traverse_def (f : α → F β) (x : α) :
    ∀ xs : Vector α n, (x ::ᵥ xs).traverse f = cons <$> f x <*> xs.traverse f := by
  rintro ⟨xs, rfl⟩; 

Proof state:
case mk
F G : Type u → Type u
inst✝¹ : Applicative F
inst✝ : Applicative G
α β : Type u
f : α → F β
x : α
xs : List α
⊢ Vector.traverse f (x ::ᵥ { val := xs, property := (_ : List.length xs = List.length xs) }) =
    Seq.seq (cons <$> f x) fun x => Vector.traverse f { val := xs, property := (_ : List.length xs = List.length xs) }

Next tactic:
rfl
protected theorem id_traverse : ∀ x : Vector α n, x.traverse (pure : _ → Id _) = x := by
  

Proof state:
n : ℕ
F G : Type u → Type u
inst✝¹ : Applicative F
inst✝ : Applicative G
α β : Type u
⊢ ∀ (x : Vector α n), Vector.traverse pure x = x

Next tactic:
rintro ⟨x, rfl⟩
protected theorem id_traverse : ∀ x : Vector α n, x.traverse (pure : _ → Id _) = x := by
  rintro ⟨x, rfl⟩; 

Proof state:
case mk
F G : Type u → Type u
inst✝¹ : Applicative F
inst✝ : Applicative G
α β : Type u
x : List α
⊢ Vector.traverse pure { val := x, property := (_ : List.length x = List.length x) } =
    { val := x, property := (_ : List.length x = List.length x) }

Next tactic:
dsimp [Vector.traverse, cast]
protected theorem id_traverse : ∀ x : Vector α n, x.traverse (pure : _ → Id _) = x := by
  rintro ⟨x, rfl⟩; dsimp [Vector.traverse, cast]
  

Proof state:
case mk
F G : Type u → Type u
inst✝¹ : Applicative F
inst✝ : Applicative G
α β : Type u
x : List α
⊢ Vector.traverseAux pure x = { val := x, property := (_ : List.length x = List.length x) }

Next tactic:
induction' x with x xs IH
protected theorem id_traverse : ∀ x : Vector α n, x.traverse (pure : _ → Id _) = x := by
  rintro ⟨x, rfl⟩; dsimp [Vector.traverse, cast]
  induction' x with x xs IH; · 

Proof state:
case mk.nil
F G : Type u → Type u
inst✝¹ : Applicative F
inst✝ : Applicative G
α β : Type u
⊢ Vector.traverseAux pure [] = { val := [], property := (_ : List.length [] = List.length []) }

Next tactic:
rfl
protected theorem id_traverse : ∀ x : Vector α n, x.traverse (pure : _ → Id _) = x := by
  rintro ⟨x, rfl⟩; dsimp [Vector.traverse, cast]
  induction' x with x xs IH; · rfl
  

Proof state:
case mk.cons
F G : Type u → Type u
inst✝¹ : Applicative F
inst✝ : Applicative G
α β : Type u
x : α
xs : List α
IH : Vector.traverseAux pure xs = { val := xs, property := (_ : List.length xs = List.length xs) }
⊢ Vector.traverseAux pure (x :: xs) =
    { val := x :: xs, property := (_ : List.length (x :: xs) = List.length (x :: xs)) }

Next tactic:
simp! [IH]
protected theorem id_traverse : ∀ x : Vector α n, x.traverse (pure : _ → Id _) = x := by
  rintro ⟨x, rfl⟩; dsimp [Vector.traverse, cast]
  induction' x with x xs IH; · rfl
  simp! [IH]; 

Proof state:
case mk.cons
F G : Type u → Type u
inst✝¹ : Applicative F
inst✝ : Applicative G
α β : Type u
x : α
xs : List α
IH : Vector.traverseAux pure xs = { val := xs, property := (_ : List.length xs = List.length xs) }
⊢ (Seq.seq (cons x) fun x => { val := xs, property := (_ : List.length xs = List.length xs) }) =
    { val := x :: xs, property := (_ : List.length (x :: xs) = List.length (x :: xs)) }

Next tactic:
rfl
@[nolint unusedArguments]
protected theorem comp_traverse (f : β → F γ) (g : α → G β) (x : Vector α n) :
    Vector.traverse (Comp.mk ∘ Functor.map f ∘ g) x =
      Comp.mk (Vector.traverse f <$> Vector.traverse g x) := by
  

Proof state:
n : ℕ
F G : Type u → Type u
inst✝³ : Applicative F
inst✝² : Applicative G
inst✝¹ : LawfulApplicative F
inst✝ : LawfulApplicative G
α β γ : Type u
f : β → F γ
g : α → G β
x : Vector α n
⊢ Vector.traverse (Comp.mk ∘ Functor.map f ∘ g) x = Comp.mk (Vector.traverse f <$> Vector.traverse g x)

Next tactic:
induction' x using Vector.inductionOn with n x xs ih
@[nolint unusedArguments]
protected theorem comp_traverse (f : β → F γ) (g : α → G β) (x : Vector α n) :
    Vector.traverse (Comp.mk ∘ Functor.map f ∘ g) x =
      Comp.mk (Vector.traverse f <$> Vector.traverse g x) := by
  induction' x using Vector.inductionOn with n x xs ih
  

Proof state:
case h_nil
n : ℕ
F G : Type u → Type u
inst✝³ : Applicative F
inst✝² : Applicative G
inst✝¹ : LawfulApplicative F
inst✝ : LawfulApplicative G
α β γ : Type u
f : β → F γ
g : α → G β
⊢ Vector.traverse (Comp.mk ∘ Functor.map f ∘ g) nil = Comp.mk (Vector.traverse f <$> Vector.traverse g nil)
case h_cons
n✝ : ℕ
F G : Type u → Type u
inst✝³ : Applicative F
inst✝² : Applicative G
inst✝¹ : LawfulApplicative F
inst✝ : LawfulApplicative G
α β γ : Type u
f : β → F γ
g : α → G β
n : ℕ
x : α
xs : Vector α n
ih : Vector.traverse (Comp.mk ∘ Functor.map f ∘ g) xs = Comp.mk (Vector.traverse f <$> Vector.traverse g xs)
⊢ Vector.traverse (Comp.mk ∘ Functor.map f ∘ g) (x ::ᵥ xs) =
    Comp.mk (Vector.traverse f <$> Vector.traverse g (x ::ᵥ xs))

Next tactic:
simp! [cast, *, functor_norm]