Theorem: Array.forIn_eq_data_forIn
File: .lake/packages/batteries/Batteries/Data/Array/Lemmas.lean

tactic: conv => lhs; simp only [forIn, Array.forIn]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
⊢ forIn as b f = forIn as.data b f
state_after: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
⊢ forIn.loop as f as.size ⋯ b = forIn as.data b f

tactic: rw [loop (Nat.zero_add _)]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
⊢ forIn.loop as f as.size ⋯ b = forIn as.data b f
state_after: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
⊢ forIn (List.drop 0 as.data) b f = forIn as.data b f

tactic: rfl
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
⊢ forIn (List.drop 0 as.data) b f = forIn as.data b f
state_after: no goals

tactic: rw [List.drop_length]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
x✝¹ : 0 ≤ as.size
x✝ : β
⊢ forIn.loop as f 0 x✝¹ x✝ = forIn (List.drop as.data.length as.data) x✝ f
state_after: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
x✝¹ : 0 ≤ as.size
x✝ : β
⊢ forIn.loop as f 0 x✝¹ x✝ = forIn [] x✝ f

tactic: rfl
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
x✝¹ : 0 ≤ as.size
x✝ : β
⊢ forIn.loop as f 0 x✝¹ x✝ = forIn [] x✝ f
state_after: no goals

tactic: simp only [forIn.loop, Nat.add]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
⊢ forIn.loop as f (i + 1) x✝¹ x✝ = forIn (List.drop j as.data) x✝ f
state_after: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
⊢ (do
      let __do_lift ← f as[as.size - 1 - i] x✝
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    forIn (List.drop j as.data) x✝ f

tactic: have j_eq : j = size as - 1 - i := by simp [← ij, ← Nat.add_assoc]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
⊢ (do
      let __do_lift ← f as[as.size - 1 - i] x✝
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    forIn (List.drop j as.data) x✝ f
state_after: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
⊢ (do
      let __do_lift ← f as[as.size - 1 - i] x✝
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    forIn (List.drop j as.data) x✝ f

tactic: have : as.size - 1 - i < as.size := j_eq ▸ ij ▸ Nat.lt_succ_of_le (Nat.le_add_right ..)
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
⊢ (do
      let __do_lift ← f as[as.size - 1 - i] x✝
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    forIn (List.drop j as.data) x✝ f
state_after: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this : as.size - 1 - i < as.size
⊢ (do
      let __do_lift ← f as[as.size - 1 - i] x✝
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    forIn (List.drop j as.data) x✝ f

tactic: have : as[size as - 1 - i] :: as.data.drop (j + 1) = as.data.drop j := by
  rw [j_eq]; exact List.getElem_cons_drop _ _ this
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this : as.size - 1 - i < as.size
⊢ (do
      let __do_lift ← f as[as.size - 1 - i] x✝
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    forIn (List.drop j as.data) x✝ f
state_after: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
⊢ (do
      let __do_lift ← f as[as.size - 1 - i] x✝
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    forIn (List.drop j as.data) x✝ f

tactic: simp only [← this, List.forIn_cons]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
⊢ (do
      let __do_lift ← f as[as.size - 1 - i] x✝
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    forIn (List.drop j as.data) x✝ f
state_after: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
⊢ (do
      let __do_lift ← f as[as.size - 1 - i] x✝
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    do
    let x ← f as[as.size - 1 - i] x✝
    match x with
      | ForInStep.done b => pure b
      | ForInStep.yield b => forIn (List.drop (j + 1) as.data) b f

tactic: congr
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
⊢ (do
      let __do_lift ← f as[as.size - 1 - i] x✝
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    do
    let x ← f as[as.size - 1 - i] x✝
    match x with
      | ForInStep.done b => pure b
      | ForInStep.yield b => forIn (List.drop (j + 1) as.data) b f
state_after: case e_a
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
⊢ (fun __do_lift =>
      match __do_lift with
      | ForInStep.done b => pure b
      | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    fun x =>
    match x with
    | ForInStep.done b => pure b
    | ForInStep.yield b => forIn (List.drop (j + 1) as.data) b f

tactic: funext x
state_before: case e_a
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
⊢ (fun __do_lift =>
      match __do_lift with
      | ForInStep.done b => pure b
      | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    fun x =>
    match x with
    | ForInStep.done b => pure b
    | ForInStep.yield b => forIn (List.drop (j + 1) as.data) b f
state_after: case e_a.h
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
x : ForInStep β
⊢ (match x with
    | ForInStep.done b => pure b
    | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    match x with
    | ForInStep.done b => pure b
    | ForInStep.yield b => forIn (List.drop (j + 1) as.data) b f

tactic: congr
state_before: case e_a.h
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
x : ForInStep β
⊢ (match x with
    | ForInStep.done b => pure b
    | ForInStep.yield b => forIn.loop as f i ⋯ b) =
    match x with
    | ForInStep.done b => pure b
    | ForInStep.yield b => forIn (List.drop (j + 1) as.data) b f
state_after: case e_a.h.e_h_2
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
x : ForInStep β
⊢ (fun b => forIn.loop as f i ⋯ b) = fun b => forIn (List.drop (j + 1) as.data) b f

tactic: funext b
state_before: case e_a.h.e_h_2
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
x : ForInStep β
⊢ (fun b => forIn.loop as f i ⋯ b) = fun b => forIn (List.drop (j + 1) as.data) b f
state_after: case e_a.h.e_h_2.h
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b✝ : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
x : ForInStep β
b : β
⊢ forIn.loop as f i ⋯ b = forIn (List.drop (j + 1) as.data) b f

tactic: rw [loop (i := i)]
state_before: case e_a.h.e_h_2.h
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b✝ : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
x : ForInStep β
b : β
⊢ forIn.loop as f i ⋯ b = forIn (List.drop (j + 1) as.data) b f
state_after: case e_a.h.e_h_2.h
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b✝ : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
x : ForInStep β
b : β
⊢ j + 1 + i = as.size

tactic: rw [← ij, Nat.succ_add]
state_before: case e_a.h.e_h_2.h
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b✝ : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
x : ForInStep β
b : β
⊢ j + 1 + i = as.size
state_after: case e_a.h.e_h_2.h
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b✝ : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
x : ForInStep β
b : β
⊢ (j + i).succ = j + (i + 1)

tactic: rfl
state_before: case e_a.h.e_h_2.h
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b✝ : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this✝ : as.size - 1 - i < as.size
this : as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
x : ForInStep β
b : β
⊢ (j + i).succ = j + (i + 1)
state_after: no goals

tactic: simp [← ij, ← Nat.add_assoc]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
⊢ j = as.size - 1 - i
state_after: no goals

tactic: rw [j_eq]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this : as.size - 1 - i < as.size
⊢ as[as.size - 1 - i] :: List.drop (j + 1) as.data = List.drop j as.data
state_after: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this : as.size - 1 - i < as.size
⊢ as[as.size - 1 - i] :: List.drop (as.size - 1 - i + 1) as.data = List.drop (as.size - 1 - i) as.data

tactic: exact List.getElem_cons_drop _ _ this
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝ : Monad m
as : Array α
b : β
f : α → β → m (ForInStep β)
i : Nat
x✝¹ : i + 1 ≤ as.size
x✝ : β
j : Nat
ij : j + (i + 1) = as.size
j_eq : j = as.size - 1 - i
this : as.size - 1 - i < as.size
⊢ as[as.size - 1 - i] :: List.drop (as.size - 1 - i + 1) as.data = List.drop (as.size - 1 - i) as.data
state_after: no goals