Theorem: Std.Range.forIn'_eq_forIn_range'
File: Std/Data/Range/Lemmas.lean

tactic: let ⟨start, stop, step⟩ := r
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
f : (a : Nat) → a ∈ r → β → m (ForInStep β)
⊢ forIn' r init f =
    forIn
      (List.pmap Subtype.mk (List.range' r.start (numElems r) r.step)
        (_ : ∀ (x : Nat), x ∈ List.range' r.start (numElems r) r.step → x ∈ r))
      init fun x =>
      match (motive := { x // x ∈ r } → β → m (ForInStep β)) x with
      | { val := a, property := h } => f a h

tactic: let L := List.range' start (numElems ⟨start, stop, step⟩) step
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
⊢ forIn' { start := start, stop := stop, step := step } init f =
    forIn
      (List.pmap Subtype.mk
        (List.range' { start := start, stop := stop, step := step }.start
          (numElems { start := start, stop := stop, step := step }) { start := start, stop := stop, step := step }.step)
        (_ :
          ∀ (x : Nat),
            x ∈
                List.range' { start := start, stop := stop, step := step }.start
                  (numElems { start := start, stop := stop, step := step })
                  { start := start, stop := stop, step := step }.step →
              x ∈ { start := start, stop := stop, step := step }))
      init fun x =>
      match (motive := { x // x ∈ { start := start, stop := stop, step := step } } → β → m (ForInStep β)) x with
      | { val := a, property := h } => f a h

tactic: let f' : { a // start ≤ a ∧ a < stop } → _ := fun ⟨a, h⟩ => f a h
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
⊢ forIn' { start := start, stop := stop, step := step } init f =
    forIn
      (List.pmap Subtype.mk
        (List.range' { start := start, stop := stop, step := step }.start
          (numElems { start := start, stop := stop, step := step }) { start := start, stop := stop, step := step }.step)
        (_ :
          ∀ (x : Nat),
            x ∈
                List.range' { start := start, stop := stop, step := step }.start
                  (numElems { start := start, stop := stop, step := step })
                  { start := start, stop := stop, step := step }.step →
              x ∈ { start := start, stop := stop, step := step }))
      init fun x =>
      match (motive := { x // x ∈ { start := start, stop := stop, step := step } } → β → m (ForInStep β)) x with
      | { val := a, property := h } => f a h

tactic: suffices ∀ H, forIn' [start:stop:step] init f = forIn (L.pmap Subtype.mk H) init f' from this _
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
⊢ forIn' { start := start, stop := stop, step := step } init f =
    forIn
      (List.pmap Subtype.mk
        (List.range' { start := start, stop := stop, step := step }.start
          (numElems { start := start, stop := stop, step := step }) { start := start, stop := stop, step := step }.step)
        (_ :
          ∀ (x : Nat),
            x ∈
                List.range' { start := start, stop := stop, step := step }.start
                  (numElems { start := start, stop := stop, step := step })
                  { start := start, stop := stop, step := step }.step →
              x ∈ { start := start, stop := stop, step := step }))
      init fun x =>
      match (motive := { x // x ∈ { start := start, stop := stop, step := step } } → β → m (ForInStep β)) x with
      | { val := a, property := h } => f a h

tactic: intro H
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
⊢ ∀ (H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop),
    forIn' { start := start, stop := stop, step := step } init f = forIn (List.pmap Subtype.mk L H) init f'

tactic: dsimp only [forIn', Range.forIn']
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
⊢ forIn' { start := start, stop := stop, step := step } init f = forIn (List.pmap Subtype.mk L H) init f'

tactic: simp [numElems, Nat.not_le.2 h]
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
⊢ forIn'.loop start stop step f stop start
      (_ : { start := start, stop := stop, step := step }.start ≤ { start := start, stop := stop, step := step }.start)
      init =
    forIn (List.pmap Subtype.mk (List.range' start (numElems { start := start, stop := stop, step := step }) step) H)
      init fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: split
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
⊢ forIn'.loop start stop step f stop start
      (_ : { start := start, stop := stop, step := step }.start ≤ { start := start, stop := stop, step := step }.start)
      init =
    forIn
      (List.pmap Subtype.mk (List.range' start (if step = 0 then stop else (stop - start + step - 1) / step) step)
        (_ :
          ∀ (a : Nat),
            a ∈ List.range' start (if step = 0 then stop else (stop - start + step - 1) / step) step →
              (fun a => start ≤ a ∧ a < stop) a))
      init fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: subst step
state_before: case inl
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
h✝ : step = 0
⊢ forIn'.loop start stop step f stop start
      (_ : { start := start, stop := stop, step := step }.start ≤ { start := start, stop := stop, step := step }.start)
      init =
    forIn
      (List.pmap Subtype.mk (List.range' start stop step)
        (_ : ∀ (a : Nat), a ∈ List.range' start stop step → (fun a => start ≤ a ∧ a < stop) a))
      init fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: suffices ∀ n H init,
    forIn'.loop start stop 0 f n start (Nat.le_refl _) init =
    forIn ((List.range' start n 0).pmap Subtype.mk H) init f' from this _ ..
state_before: case inl
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop : Nat
h : start < stop
f : (a : Nat) → a ∈ { start := start, stop := stop, step := 0 } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := 0 }) 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
⊢ forIn'.loop start stop 0 f stop start
      (_ : { start := start, stop := stop, step := 0 }.start ≤ { start := start, stop := stop, step := 0 }.start) init =
    forIn
      (List.pmap Subtype.mk (List.range' start stop 0)
        (_ : ∀ (a : Nat), a ∈ List.range' start stop 0 → (fun a => start ≤ a ∧ a < stop) a))
      init fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: intro n
state_before: case inl
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop : Nat
h : start < stop
f : (a : Nat) → a ∈ { start := start, stop := stop, step := 0 } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := 0 }) 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
⊢ ∀ (n : Nat) (H : ∀ (a : Nat), a ∈ List.range' start n 0 → start ≤ a ∧ a < stop) (init : β),
    forIn'.loop start stop 0 f n start (_ : start ≤ start) init =
      forIn (List.pmap Subtype.mk (List.range' start n 0) H) init f'

tactic: induction n with (intro H init; unfold forIn'.loop; simp [*])
| succ n ih => simp [ih (List.forall_mem_cons.1 H).2]; rfl
state_before: case inl
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop : Nat
h : start < stop
f : (a : Nat) → a ∈ { start := start, stop := stop, step := 0 } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := 0 }) 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
n : Nat
⊢ ∀ (H : ∀ (a : Nat), a ∈ List.range' start n 0 → start ≤ a ∧ a < stop) (init : β),
    forIn'.loop start stop 0 f n start (_ : start ≤ start) init =
      forIn (List.pmap Subtype.mk (List.range' start n 0) H) init f'

tactic: intro H init
state_before: case inl.zero
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop : Nat
h : start < stop
f : (a : Nat) → a ∈ { start := start, stop := stop, step := 0 } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := 0 }) 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
⊢ ∀ (H : ∀ (a : Nat), a ∈ List.range' start Nat.zero 0 → start ≤ a ∧ a < stop) (init : β),
    forIn'.loop start stop 0 f Nat.zero start (_ : start ≤ start) init =
      forIn (List.pmap Subtype.mk (List.range' start Nat.zero 0) H) init f'

tactic: unfold forIn'.loop
state_before: case inl.zero
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop : Nat
h : start < stop
f : (a : Nat) → a ∈ { start := start, stop := stop, step := 0 } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := 0 }) 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
H : ∀ (a : Nat), a ∈ List.range' start Nat.zero 0 → start ≤ a ∧ a < stop
init : β
⊢ forIn'.loop start stop 0 f Nat.zero start (_ : start ≤ start) init =
    forIn (List.pmap Subtype.mk (List.range' start Nat.zero 0) H) init f'

tactic: simp [*]
state_before: case inl.zero
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop : Nat
h : start < stop
f : (a : Nat) → a ∈ { start := start, stop := stop, step := 0 } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := 0 }) 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
H : ∀ (a : Nat), a ∈ List.range' start Nat.zero 0 → start ≤ a ∧ a < stop
init : β
⊢ (if hu : start < stop then
      match Nat.zero with
      | 0 => pure init
      | Nat.succ fuel => do
        let __do_lift ← f start (_ : start ≤ start ∧ start < stop) init
        match __do_lift with
          | ForInStep.done b => pure b
          | ForInStep.yield b => forIn'.loop start stop 0 f fuel (start + 0) (_ : start ≤ start + 0) b
    else pure init) =
    forIn (List.pmap Subtype.mk (List.range' start Nat.zero 0) H) init f'

tactic: simp [ih (List.forall_mem_cons.1 H).2]
state_before: case inl.succ
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop : Nat
h : start < stop
f : (a : Nat) → a ∈ { start := start, stop := stop, step := 0 } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := 0 }) 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
n : Nat
ih :
  ∀ (H : ∀ (a : Nat), a ∈ List.range' start n 0 → start ≤ a ∧ a < stop) (init : β),
    forIn'.loop start stop 0 f n start (_ : start ≤ start) init =
      forIn (List.pmap Subtype.mk (List.range' start n 0) H) init f'
H : ∀ (a : Nat), a ∈ List.range' start (Nat.succ n) 0 → start ≤ a ∧ a < stop
init : β
⊢ (do
      let __do_lift ← f start (_ : start ≤ start ∧ start < stop) init
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn'.loop start stop 0 f n start (_ : start ≤ start) b) =
    do
    let x ←
      f start
          (_ :
            start ≤ { val := start, property := (_ : start ≤ start ∧ start < stop) }.val ∧
              { val := start, property := (_ : start ≤ start ∧ start < stop) }.val < stop)
          init
    match x with
      | ForInStep.done b => pure b
      | ForInStep.yield b =>
        forIn
          (List.pmap Subtype.mk (List.range' start n 0)
            (_ : ∀ (a : Nat), a ∈ List.range' start n 0 → (fun a => (fun a => start ≤ a ∧ a < stop) a) a))
          b fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: rfl
state_before: case inl.succ
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop : Nat
h : start < stop
f : (a : Nat) → a ∈ { start := start, stop := stop, step := 0 } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := 0 }) 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
n : Nat
ih :
  ∀ (H : ∀ (a : Nat), a ∈ List.range' start n 0 → start ≤ a ∧ a < stop) (init : β),
    forIn'.loop start stop 0 f n start (_ : start ≤ start) init =
      forIn (List.pmap Subtype.mk (List.range' start n 0) H) init f'
H : ∀ (a : Nat), a ∈ List.range' start (Nat.succ n) 0 → start ≤ a ∧ a < stop
init : β
⊢ (do
      let __do_lift ← f start (_ : start ≤ start ∧ start < stop) init
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b =>
          forIn
            (List.pmap Subtype.mk (List.range' start n 0)
              (_ : ∀ (x : Nat), x ∈ List.range' (start + 0) n 0 → start ≤ x ∧ x < stop))
            b fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)) =
    do
    let x ←
      f start
          (_ :
            start ≤ { val := start, property := (_ : start ≤ start ∧ start < stop) }.val ∧
              { val := start, property := (_ : start ≤ start ∧ start < stop) }.val < stop)
          init
    match x with
      | ForInStep.done b => pure b
      | ForInStep.yield b =>
        forIn
          (List.pmap Subtype.mk (List.range' start n 0)
            (_ : ∀ (a : Nat), a ∈ List.range' start n 0 → (fun a => (fun a => start ≤ a ∧ a < stop) a) a))
          b fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: next step0 =>
have hstep := Nat.pos_of_ne_zero step0
suffices ∀ fuel l i hle H, l ≤ fuel →
    (∀ j, stop ≤ i + step * j ↔ l ≤ j) → ∀ init,
    forIn'.loop start stop step f fuel i hle init =
    List.forIn ((List.range' i l step).pmap Subtype.mk H) init f' by
  refine this _ _ _ _ _
    ((numElems_le_iff hstep).2 (Nat.le_trans ?_ (Nat.le_add_left ..)))
    (fun _ => (numElems_le_iff hstep).symm) _
  conv => lhs; rw [← Nat.one_mul stop]
  exact Nat.mul_le_mul_right stop hstep
intro fuel; induction fuel with intro l i hle H h1 h2 init
| zero => simp [forIn'.loop, Nat.le_zero.1 h1]; split <;> simp
| succ fuel ih =>
  cases l with
  | zero => rw [forIn'.loop]; simp [Nat.not_lt.2 <| by simpa using (h2 0).2 (Nat.le_refl _)]
  | succ l =>
    have ih := ih _ _ (Nat.le_trans hle (Nat.le_add_right ..))
      (List.forall_mem_cons.1 H).2 (Nat.le_of_succ_le_succ h1) fun i => by
        rw [Nat.add_right_comm, Nat.add_assoc, ← Nat.mul_succ, h2, Nat.succ_le_succ_iff]
    have := h2 0; simp at this
    rw [forIn'.loop]; simp [List.forIn, this, ih]; rfl
state_before: case inr
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
h✝ : ¬step = 0
⊢ forIn'.loop start stop step f stop start
      (_ : { start := start, stop := stop, step := step }.start ≤ { start := start, stop := stop, step := step }.start)
      init =
    forIn
      (List.pmap Subtype.mk (List.range' start ((stop - start + step - 1) / step) step)
        (_ :
          ∀ (a : Nat),
            a ∈ List.range' start ((stop - start + step - 1) / step) step → (fun a => start ≤ a ∧ a < stop) a))
      init fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: have hstep := Nat.pos_of_ne_zero step0
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
⊢ forIn'.loop start stop step f stop start
      (_ : { start := start, stop := stop, step := step }.start ≤ { start := start, stop := stop, step := step }.start)
      init =
    forIn
      (List.pmap Subtype.mk (List.range' start ((stop - start + step - 1) / step) step)
        (_ :
          ∀ (a : Nat),
            a ∈ List.range' start ((stop - start + step - 1) / step) step → (fun a => start ≤ a ∧ a < stop) a))
      init fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: suffices ∀ fuel l i hle H, l ≤ fuel →
    (∀ j, stop ≤ i + step * j ↔ l ≤ j) → ∀ init,
    forIn'.loop start stop step f fuel i hle init =
    List.forIn ((List.range' i l step).pmap Subtype.mk H) init f' by
  refine this _ _ _ _ _
    ((numElems_le_iff hstep).2 (Nat.le_trans ?_ (Nat.le_add_left ..)))
    (fun _ => (numElems_le_iff hstep).symm) _
  conv => lhs; rw [← Nat.one_mul stop]
  exact Nat.mul_le_mul_right stop hstep
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
⊢ forIn'.loop start stop step f stop start
      (_ : { start := start, stop := stop, step := step }.start ≤ { start := start, stop := stop, step := step }.start)
      init =
    forIn
      (List.pmap Subtype.mk (List.range' start ((stop - start + step - 1) / step) step)
        (_ :
          ∀ (a : Nat),
            a ∈ List.range' start ((stop - start + step - 1) / step) step → (fun a => start ≤ a ∧ a < stop) a))
      init fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: intro fuel
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
⊢ ∀ (fuel l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'

tactic: induction fuel with intro l i hle H h1 h2 init
| zero => simp [forIn'.loop, Nat.le_zero.1 h1]; split <;> simp
| succ fuel ih =>
cases l with
| zero => rw [forIn'.loop]; simp [Nat.not_lt.2 <| by simpa using (h2 0).2 (Nat.le_refl _)]
| succ l =>
have ih := ih _ _ (Nat.le_trans hle (Nat.le_add_right ..))
(List.forall_mem_cons.1 H).2 (Nat.le_of_succ_le_succ h1) fun i => by
rw [Nat.add_right_comm, Nat.add_assoc, ← Nat.mul_succ, h2, Nat.succ_le_succ_iff]
have := h2 0; simp at this
rw [forIn'.loop]; simp [List.forIn, this, ih]; rfl
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
⊢ ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'

tactic: refine this _ _ _ _ _
  ((numElems_le_iff hstep).2 (Nat.le_trans ?_ (Nat.le_add_left ..)))
  (fun _ => (numElems_le_iff hstep).symm) _
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
this :
  ∀ (fuel l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
⊢ forIn'.loop start stop step f stop start
      (_ : { start := start, stop := stop, step := step }.start ≤ { start := start, stop := stop, step := step }.start)
      init =
    forIn
      (List.pmap Subtype.mk (List.range' start ((stop - start + step - 1) / step) step)
        (_ :
          ∀ (a : Nat),
            a ∈ List.range' start ((stop - start + step - 1) / step) step → (fun a => start ≤ a ∧ a < stop) a))
      init fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: conv => lhs; rw [← Nat.one_mul stop]
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
this :
  ∀ (fuel l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
⊢ stop ≤ step * stop

tactic: exact Nat.mul_le_mul_right stop hstep
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
this :
  ∀ (fuel l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
⊢ 1 * stop ≤ step * stop

tactic: simp [forIn'.loop, Nat.le_zero.1 h1]
state_before: case zero
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
l i : Nat
hle : start ≤ i
H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop
h1 : l ≤ Nat.zero
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j
init : β
⊢ forIn'.loop start stop step f Nat.zero i hle init = List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'

tactic: split <;> simp
state_before: case zero
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
l i : Nat
hle : start ≤ i
H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop
h1 : l ≤ Nat.zero
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j
init : β
⊢ (if hu : i < stop then pure init else pure init) = pure init

tactic: cases l with
| zero => rw [forIn'.loop]; simp [Nat.not_lt.2 <| by simpa using (h2 0).2 (Nat.le_refl _)]
| succ l =>
  have ih := ih _ _ (Nat.le_trans hle (Nat.le_add_right ..))
    (List.forall_mem_cons.1 H).2 (Nat.le_of_succ_le_succ h1) fun i => by
      rw [Nat.add_right_comm, Nat.add_assoc, ← Nat.mul_succ, h2, Nat.succ_le_succ_iff]
  have := h2 0; simp at this
  rw [forIn'.loop]; simp [List.forIn, this, ih]; rfl
state_before: case succ
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
l i : Nat
hle : start ≤ i
H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop
h1 : l ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j
init : β
⊢ forIn'.loop start stop step f (Nat.succ fuel) i hle init =
    List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'

tactic: rw [forIn'.loop]
state_before: case succ.zero
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
i : Nat
hle : start ≤ i
init : β
H : ∀ (a : Nat), a ∈ List.range' i Nat.zero step → start ≤ a ∧ a < stop
h1 : Nat.zero ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ Nat.zero ≤ j
⊢ forIn'.loop start stop step f (Nat.succ fuel) i hle init =
    List.forIn (List.pmap Subtype.mk (List.range' i Nat.zero step) H) init f'

tactic: simp [Nat.not_lt.2 <| by simpa using (h2 0).2 (Nat.le_refl _)]
state_before: case succ.zero
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
i : Nat
hle : start ≤ i
init : β
H : ∀ (a : Nat), a ∈ List.range' i Nat.zero step → start ≤ a ∧ a < stop
h1 : Nat.zero ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ Nat.zero ≤ j
⊢ (if hu : i < stop then
      match Nat.succ fuel with
      | 0 => pure init
      | Nat.succ fuel => do
        let __do_lift ← f i (_ : start ≤ i ∧ i < stop) init
        match __do_lift with
          | ForInStep.done b => pure b
          | ForInStep.yield b => forIn'.loop start stop step f fuel (i + step) (_ : start ≤ i + step) b
    else pure init) =
    List.forIn (List.pmap Subtype.mk (List.range' i Nat.zero step) H) init f'

tactic: simpa using (h2 0).2 (Nat.le_refl _)
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
i : Nat
hle : start ≤ i
init : β
H : ∀ (a : Nat), a ∈ List.range' i Nat.zero step → start ≤ a ∧ a < stop
h1 : Nat.zero ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ Nat.zero ≤ j
⊢ ?m.23409 ≤ ?m.23408

tactic: have ih := ih _ _ (Nat.le_trans hle (Nat.le_add_right ..))
  (List.forall_mem_cons.1 H).2 (Nat.le_of_succ_le_succ h1) fun i => by
    rw [Nat.add_right_comm, Nat.add_assoc, ← Nat.mul_succ, h2, Nat.succ_le_succ_iff]
state_before: case succ.succ
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (Nat.succ l) step → start ≤ a ∧ a < stop
h1 : Nat.succ l ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ Nat.succ l ≤ j
⊢ forIn'.loop start stop step f (Nat.succ fuel) i hle init =
    List.forIn (List.pmap Subtype.mk (List.range' i (Nat.succ l) step) H) init f'

tactic: have := h2 0
state_before: case succ.succ
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih✝ :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (Nat.succ l) step → start ≤ a ∧ a < stop
h1 : Nat.succ l ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ Nat.succ l ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) (_ : start ≤ i + step) init =
      List.forIn
        (List.pmap Subtype.mk (List.range' (i + step) l step)
          (_ : ∀ (x : Nat), x ∈ List.range' (i + step) l step → start ≤ x ∧ x < stop))
        init f'
⊢ forIn'.loop start stop step f (Nat.succ fuel) i hle init =
    List.forIn (List.pmap Subtype.mk (List.range' i (Nat.succ l) step) H) init f'

tactic: simp at this
state_before: case succ.succ
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih✝ :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (Nat.succ l) step → start ≤ a ∧ a < stop
h1 : Nat.succ l ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ Nat.succ l ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) (_ : start ≤ i + step) init =
      List.forIn
        (List.pmap Subtype.mk (List.range' (i + step) l step)
          (_ : ∀ (x : Nat), x ∈ List.range' (i + step) l step → start ≤ x ∧ x < stop))
        init f'
this : stop ≤ i + step * 0 ↔ Nat.succ l ≤ 0
⊢ forIn'.loop start stop step f (Nat.succ fuel) i hle init =
    List.forIn (List.pmap Subtype.mk (List.range' i (Nat.succ l) step) H) init f'

tactic: rw [forIn'.loop]
state_before: case succ.succ
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih✝ :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (Nat.succ l) step → start ≤ a ∧ a < stop
h1 : Nat.succ l ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ Nat.succ l ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) (_ : start ≤ i + step) init =
      List.forIn
        (List.pmap Subtype.mk (List.range' (i + step) l step)
          (_ : ∀ (x : Nat), x ∈ List.range' (i + step) l step → start ≤ x ∧ x < stop))
        init f'
this : i < stop
⊢ forIn'.loop start stop step f (Nat.succ fuel) i hle init =
    List.forIn (List.pmap Subtype.mk (List.range' i (Nat.succ l) step) H) init f'

tactic: simp [List.forIn, this, ih]
state_before: case succ.succ
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih✝ :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (Nat.succ l) step → start ≤ a ∧ a < stop
h1 : Nat.succ l ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ Nat.succ l ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) (_ : start ≤ i + step) init =
      List.forIn
        (List.pmap Subtype.mk (List.range' (i + step) l step)
          (_ : ∀ (x : Nat), x ∈ List.range' (i + step) l step → start ≤ x ∧ x < stop))
        init f'
this : i < stop
⊢ (if hu : i < stop then
      match Nat.succ fuel with
      | 0 => pure init
      | Nat.succ fuel => do
        let __do_lift ← f i (_ : start ≤ i ∧ i < stop) init
        match __do_lift with
          | ForInStep.done b => pure b
          | ForInStep.yield b => forIn'.loop start stop step f fuel (i + step) (_ : start ≤ i + step) b
    else pure init) =
    List.forIn (List.pmap Subtype.mk (List.range' i (Nat.succ l) step) H) init f'

tactic: rfl
state_before: case succ.succ
m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih✝ :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (Nat.succ l) step → start ≤ a ∧ a < stop
h1 : Nat.succ l ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ Nat.succ l ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) (_ : start ≤ i + step) init =
      List.forIn
        (List.pmap Subtype.mk (List.range' (i + step) l step)
          (_ : ∀ (x : Nat), x ∈ List.range' (i + step) l step → start ≤ x ∧ x < stop))
        init f'
this : i < stop
⊢ (do
      let __do_lift ← f i (_ : start ≤ i ∧ i < stop) init
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b =>
          List.forIn.loop (fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop))
            (List.pmap Subtype.mk (List.range' (i + step) l step)
              (_ : ∀ (x : Nat), x ∈ List.range' (i + step) l step → start ≤ x ∧ x < stop))
            b) =
    do
    let __do_lift ←
      f i
          (_ :
            start ≤ { val := i, property := (_ : start ≤ i ∧ i < stop) }.val ∧
              { val := i, property := (_ : start ≤ i ∧ i < stop) }.val < stop)
          init
    match __do_lift with
      | ForInStep.done b => pure b
      | ForInStep.yield b =>
        List.forIn.loop (fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop))
          (List.pmap Subtype.mk (List.range' (i + step) l step)
            (_ : ∀ (x : Nat), x ∈ List.range' (i + step) l step → start ≤ x ∧ x < stop))
          b

tactic: rw [Nat.add_right_comm, Nat.add_assoc, ← Nat.mul_succ, h2, Nat.succ_le_succ_iff]
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init✝ : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
step0 : ¬step = 0
hstep : 0 < step
fuel : Nat
ih :
  ∀ (l i : Nat) (hle : start ≤ i) (H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop),
    l ≤ fuel →
      (∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j) →
        ∀ (init : β),
          forIn'.loop start stop step f fuel i hle init =
            List.forIn (List.pmap Subtype.mk (List.range' i l step) H) init f'
i✝ : Nat
hle : start ≤ i✝
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i✝ (Nat.succ l) step → start ≤ a ∧ a < stop
h1 : Nat.succ l ≤ Nat.succ fuel
h2 : ∀ (j : Nat), stop ≤ i✝ + step * j ↔ Nat.succ l ≤ j
i : Nat
⊢ stop ≤ i✝ + step + step * i ↔ l ≤ i

tactic: simp [List.range', h, numElems_stop_le_start ⟨start, stop, step⟩ (Nat.not_lt.1 h)]
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : ¬start < stop
⊢ forIn'.loop start stop step f stop start
      (_ : { start := start, stop := stop, step := step }.start ≤ { start := start, stop := stop, step := step }.start)
      init =
    forIn (List.pmap Subtype.mk (List.range' start (numElems { start := start, stop := stop, step := step }) step) H)
      init fun x => f x.val (_ : start ≤ x.val ∧ x.val < stop)

tactic: cases stop <;> unfold forIn'.loop <;> simp [List.forIn', h]
state_before: m : Type u_1 → Type u_2
β : Type u_1
inst✝ : Monad m
r : Range
init : β
start stop step : Nat
f : (a : Nat) → a ∈ { start := start, stop := stop, step := step } → β → m (ForInStep β)
L : List Nat := List.range' start (numElems { start := start, stop := stop, step := step }) step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | { val := a, property := h } => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : ¬start < stop
⊢ forIn'.loop start stop step f stop start
      (_ : { start := start, stop := stop, step := step }.start ≤ { start := start, stop := stop, step := step }.start)
      init =
    pure init