Theorem: Std.Range.forIn'_eq_forIn_range'
File: .lake/packages/batteries/Batteries/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 r.numElems r.step) ⋯) init fun x =>
      match (motive := { x // x ∈ r } → β → m (ForInStep β)) x with
      | ⟨a, h⟩ => f a h
state_after: 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
          { start := start, stop := stop, step := step }.numElems { start := start, stop := stop, step := step }.step)
        ⋯)
      init fun x =>
      match (motive := { x // x ∈ { start := start, stop := stop, step := step } } → β → m (ForInStep β)) x with
      | ⟨a, 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
          { start := start, stop := stop, step := step }.numElems { start := start, stop := stop, step := step }.step)
        ⋯)
      init fun x =>
      match (motive := { x // x ∈ { start := start, stop := stop, step := step } } → β → m (ForInStep β)) x with
      | ⟨a, h⟩ => f a h
state_after: 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 { start := start, stop := stop, step := step }.numElems step
⊢ forIn' { start := start, stop := stop, step := step } init f =
    forIn
      (List.pmap Subtype.mk
        (List.range' { start := start, stop := stop, step := step }.start
          { start := start, stop := stop, step := step }.numElems { start := start, stop := stop, step := step }.step)
        ⋯)
      init fun x =>
      match (motive := { x // x ∈ { start := start, stop := stop, step := step } } → β → m (ForInStep β)) x with
      | ⟨a, 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 { start := start, stop := stop, step := step }.numElems step
⊢ forIn' { start := start, stop := stop, step := step } init f =
    forIn
      (List.pmap Subtype.mk
        (List.range' { start := start, stop := stop, step := step }.start
          { start := start, stop := stop, step := step }.numElems { start := start, stop := stop, step := step }.step)
        ⋯)
      init fun x =>
      match (motive := { x // x ∈ { start := start, stop := stop, step := step } } → β → m (ForInStep β)) x with
      | ⟨a, h⟩ => f a h
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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
          { start := start, stop := stop, step := step }.numElems { start := start, stop := stop, step := step }.step)
        ⋯)
      init fun x =>
      match (motive := { x // x ∈ { start := start, stop := stop, step := step } } → β → m (ForInStep β)) x with
      | ⟨a, 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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
          { start := start, stop := stop, step := step }.numElems { start := start, stop := stop, step := step }.step)
        ⋯)
      init fun x =>
      match (motive := { x // x ∈ { start := start, stop := stop, step := step } } → β → m (ForInStep β)) x with
      | ⟨a, h⟩ => f a h
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
⊢ forIn'.loop start stop step f stop start ⋯ init = forIn (List.pmap Subtype.mk L H) init f'

tactic: simp [numElems, Nat.not_le.2 h, L]
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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
⊢ forIn'.loop start stop step f stop start ⋯ init = forIn (List.pmap Subtype.mk L H) init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
⊢ forIn'.loop start stop step f stop start ⋯ init =
    forIn
      (List.pmap Subtype.mk (List.range' start (if step = 0 then stop else (stop - start + step - 1) / step) step) ⋯)
      init f'

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : start < stop
⊢ forIn'.loop start stop step f stop start ⋯ init =
    forIn
      (List.pmap Subtype.mk (List.range' start (if step = 0 then stop else (stop - start + step - 1) / step) step) ⋯)
      init f'
state_after: case isTrue
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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init = forIn (List.pmap Subtype.mk (List.range' start stop step) ⋯) init f'

case isFalse
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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init =
    forIn (List.pmap Subtype.mk (List.range' start ((stop - start + step - 1) / step) step) ⋯) init f'

tactic: subst step
state_before: case isTrue
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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init = forIn (List.pmap Subtype.mk (List.range' start stop step) ⋯) init f'
state_after: case isTrue
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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
⊢ forIn'.loop start stop 0 f stop start ⋯ init = forIn (List.pmap Subtype.mk (List.range' start stop 0) ⋯) init f'

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 isTrue
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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
⊢ forIn'.loop start stop 0 f stop start ⋯ init = forIn (List.pmap Subtype.mk (List.range' start stop 0) ⋯) init f'
state_after: case isTrue
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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init = forIn (List.pmap Subtype.mk (List.range' start n 0) H) init f'

tactic: intro n
state_before: case isTrue
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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init = forIn (List.pmap Subtype.mk (List.range' start n 0) H) init f'
state_after: case isTrue
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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ 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 isTrue
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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init = forIn (List.pmap Subtype.mk (List.range' start n 0) H) init f'
state_after: no goals

tactic: intro H init
state_before: case isTrue.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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
⊢ ∀ (H : ∀ (a : Nat), a ∈ List.range' start 0 0 → start ≤ a ∧ a < stop) (init : β),
    forIn'.loop start stop 0 f 0 start ⋯ init = forIn (List.pmap Subtype.mk (List.range' start 0 0) H) init f'
state_after: case isTrue.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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
H : ∀ (a : Nat), a ∈ List.range' start 0 0 → start ≤ a ∧ a < stop
init : β
⊢ forIn'.loop start stop 0 f 0 start ⋯ init = forIn (List.pmap Subtype.mk (List.range' start 0 0) H) init f'

tactic: unfold forIn'.loop
state_before: case isTrue.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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
H : ∀ (a : Nat), a ∈ List.range' start 0 0 → start ≤ a ∧ a < stop
init : β
⊢ forIn'.loop start stop 0 f 0 start ⋯ init = forIn (List.pmap Subtype.mk (List.range' start 0 0) H) init f'
state_after: case isTrue.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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
H : ∀ (a : Nat), a ∈ List.range' start 0 0 → start ≤ a ∧ a < stop
init : β
⊢ (if hu : start < stop then
      match 0 with
      | 0 => pure init
      | fuel.succ => do
        let __do_lift ← f start ⋯ init
        match __do_lift with
          | ForInStep.done b => pure b
          | ForInStep.yield b => forIn'.loop start stop 0 f fuel (start + 0) ⋯ b
    else pure init) =
    forIn (List.pmap Subtype.mk (List.range' start 0 0) H) init f'

tactic: simp [*]
state_before: case isTrue.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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H✝ : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
H : ∀ (a : Nat), a ∈ List.range' start 0 0 → start ≤ a ∧ a < stop
init : β
⊢ (if hu : start < stop then
      match 0 with
      | 0 => pure init
      | fuel.succ => do
        let __do_lift ← f start ⋯ init
        match __do_lift with
          | ForInStep.done b => pure b
          | ForInStep.yield b => forIn'.loop start stop 0 f fuel (start + 0) ⋯ b
    else pure init) =
    forIn (List.pmap Subtype.mk (List.range' start 0 0) H) init f'
state_after: no goals

tactic: simp [ih (List.forall_mem_cons.1 H).2]
state_before: case isTrue.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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init = forIn (List.pmap Subtype.mk (List.range' start n 0) H) init f'
H : ∀ (a : Nat), a ∈ List.range' start (n + 1) 0 → start ≤ a ∧ a < stop
init : β
⊢ (do
      let __do_lift ← f start ⋯ init
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn'.loop start stop 0 f n start ⋯ b) =
    do
    let x ← f' ⟨start, ⋯⟩ init
    match x with
      | ForInStep.done b => pure b
      | ForInStep.yield b => forIn (List.pmap Subtype.mk (List.range' start n 0) ⋯) b f'
state_after: case isTrue.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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init = forIn (List.pmap Subtype.mk (List.range' start n 0) H) init f'
H : ∀ (a : Nat), a ∈ List.range' start (n + 1) 0 → start ≤ a ∧ a < stop
init : β
⊢ (do
      let __do_lift ← f start ⋯ init
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn (List.pmap Subtype.mk (List.range' start n 0) ⋯) b f') =
    do
    let x ← f' ⟨start, ⋯⟩ init
    match x with
      | ForInStep.done b => pure b
      | ForInStep.yield b => forIn (List.pmap Subtype.mk (List.range' start n 0) ⋯) b f'

tactic: rfl
state_before: case isTrue.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 { start := start, stop := stop, step := 0 }.numElems 0
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init = forIn (List.pmap Subtype.mk (List.range' start n 0) H) init f'
H : ∀ (a : Nat), a ∈ List.range' start (n + 1) 0 → start ≤ a ∧ a < stop
init : β
⊢ (do
      let __do_lift ← f start ⋯ init
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => forIn (List.pmap Subtype.mk (List.range' start n 0) ⋯) b f') =
    do
    let x ← f' ⟨start, ⋯⟩ init
    match x with
      | ForInStep.done b => pure b
      | ForInStep.yield b => forIn (List.pmap Subtype.mk (List.range' start n 0) ⋯) b f'
state_after: no goals

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]
| 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 isFalse
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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init =
    forIn (List.pmap Subtype.mk (List.range' start ((stop - start + step - 1) / step) step) ⋯) init f'
state_after: no goals

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init =
    forIn (List.pmap Subtype.mk (List.range' start ((stop - start + step - 1) / step) step) ⋯) init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init =
    forIn (List.pmap Subtype.mk (List.range' start ((stop - start + step - 1) / step) step) ⋯) init f'

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ⋯ init =
    forIn (List.pmap Subtype.mk (List.range' start ((stop - start + step - 1) / step) step) ⋯) init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'

tactic: induction fuel with intro l i hle H h1 h2 init
| zero => simp [forIn'.loop, Nat.le_zero.1 h1]
| 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
state_after: no goals

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
⊢ forIn'.loop start stop step f stop start ⋯ init =
    forIn (List.pmap Subtype.mk (List.range' start ((stop - start + step - 1) / step) step) ⋯) init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
⊢ stop ≤ step * 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
⊢ stop ≤ step * stop
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
⊢ 1 * 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
⊢ 1 * stop ≤ step * stop
state_after: no goals

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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 ≤ 0
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j
init : β
⊢ forIn'.loop start stop step f 0 i hle init = (List.pmap Subtype.mk (List.range' i l step) H).forIn init f'
state_after: no goals

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
l i : Nat
hle : start ≤ i
H : ∀ (a : Nat), a ∈ List.range' i l step → start ≤ a ∧ a < stop
h1 : l ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l ≤ j
init : β
⊢ forIn'.loop start stop step f (fuel + 1) i hle init = (List.pmap Subtype.mk (List.range' i l step) H).forIn init f'
state_after: no goals

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
H : ∀ (a : Nat), a ∈ List.range' i 0 step → start ≤ a ∧ a < stop
h1 : 0 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ 0 ≤ j
⊢ forIn'.loop start stop step f (fuel + 1) i hle init = (List.pmap Subtype.mk (List.range' i 0 step) H).forIn init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
H : ∀ (a : Nat), a ∈ List.range' i 0 step → start ≤ a ∧ a < stop
h1 : 0 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ 0 ≤ j
⊢ (if hu : i < stop then
      match fuel + 1 with
      | 0 => pure init
      | fuel.succ => do
        let __do_lift ← f i ⋯ init
        match __do_lift with
          | ForInStep.done b => pure b
          | ForInStep.yield b => forIn'.loop start stop step f fuel (i + step) ⋯ b
    else pure init) =
    (List.pmap Subtype.mk (List.range' i 0 step) H).forIn 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
H : ∀ (a : Nat), a ∈ List.range' i 0 step → start ≤ a ∧ a < stop
h1 : 0 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ 0 ≤ j
⊢ (if hu : i < stop then
      match fuel + 1 with
      | 0 => pure init
      | fuel.succ => do
        let __do_lift ← f i ⋯ init
        match __do_lift with
          | ForInStep.done b => pure b
          | ForInStep.yield b => forIn'.loop start stop step f fuel (i + step) ⋯ b
    else pure init) =
    (List.pmap Subtype.mk (List.range' i 0 step) H).forIn init f'
state_after: no goals

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
H : ∀ (a : Nat), a ∈ List.range' i 0 step → start ≤ a ∧ a < stop
h1 : 0 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ 0 ≤ j
⊢ ?m.17812 ≤ ?m.17811
state_after: no goals

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
⊢ forIn'.loop start stop step f (fuel + 1) i hle init =
    (List.pmap Subtype.mk (List.range' i (l + 1) step) H).forIn init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) ⋯ init =
      (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯).forIn init f'
⊢ forIn'.loop start stop step f (fuel + 1) i hle init =
    (List.pmap Subtype.mk (List.range' i (l + 1) step) H).forIn 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) ⋯ init =
      (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯).forIn init f'
⊢ forIn'.loop start stop step f (fuel + 1) i hle init =
    (List.pmap Subtype.mk (List.range' i (l + 1) step) H).forIn init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) ⋯ init =
      (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯).forIn init f'
this : stop ≤ i + step * 0 ↔ l + 1 ≤ 0
⊢ forIn'.loop start stop step f (fuel + 1) i hle init =
    (List.pmap Subtype.mk (List.range' i (l + 1) step) H).forIn 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) ⋯ init =
      (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯).forIn init f'
this : stop ≤ i + step * 0 ↔ l + 1 ≤ 0
⊢ forIn'.loop start stop step f (fuel + 1) i hle init =
    (List.pmap Subtype.mk (List.range' i (l + 1) step) H).forIn init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) ⋯ init =
      (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯).forIn init f'
this : i < stop
⊢ forIn'.loop start stop step f (fuel + 1) i hle init =
    (List.pmap Subtype.mk (List.range' i (l + 1) step) H).forIn 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) ⋯ init =
      (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯).forIn init f'
this : i < stop
⊢ forIn'.loop start stop step f (fuel + 1) i hle init =
    (List.pmap Subtype.mk (List.range' i (l + 1) step) H).forIn init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) ⋯ init =
      (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯).forIn init f'
this : i < stop
⊢ (if hu : i < stop then
      match fuel + 1 with
      | 0 => pure init
      | fuel.succ => do
        let __do_lift ← f i ⋯ init
        match __do_lift with
          | ForInStep.done b => pure b
          | ForInStep.yield b => forIn'.loop start stop step f fuel (i + step) ⋯ b
    else pure init) =
    (List.pmap Subtype.mk (List.range' i (l + 1) step) H).forIn 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) ⋯ init =
      (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯).forIn init f'
this : i < stop
⊢ (if hu : i < stop then
      match fuel + 1 with
      | 0 => pure init
      | fuel.succ => do
        let __do_lift ← f i ⋯ init
        match __do_lift with
          | ForInStep.done b => pure b
          | ForInStep.yield b => forIn'.loop start stop step f fuel (i + step) ⋯ b
    else pure init) =
    (List.pmap Subtype.mk (List.range' i (l + 1) step) H).forIn init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) ⋯ init =
      (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯).forIn init f'
this : i < stop
⊢ (do
      let __do_lift ← f i ⋯ init
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => List.forIn.loop f' (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯) b) =
    List.forIn.loop f' (⟨i, ⋯⟩ :: List.pmap Subtype.mk (List.range' (i + step) l step) ⋯) init

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i : Nat
hle : start ≤ i
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i + step * j ↔ l + 1 ≤ j
ih :
  ∀ (init : β),
    forIn'.loop start stop step f fuel (i + step) ⋯ init =
      (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯).forIn init f'
this : i < stop
⊢ (do
      let __do_lift ← f i ⋯ init
      match __do_lift with
        | ForInStep.done b => pure b
        | ForInStep.yield b => List.forIn.loop f' (List.pmap Subtype.mk (List.range' (i + step) l step) ⋯) b) =
    List.forIn.loop f' (⟨i, ⋯⟩ :: List.pmap Subtype.mk (List.range' (i + step) l step) ⋯) init
state_after: no goals

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, 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.pmap Subtype.mk (List.range' i l step) H).forIn init f'
i✝ : Nat
hle : start ≤ i✝
init : β
l : Nat
H : ∀ (a : Nat), a ∈ List.range' i✝ (l + 1) step → start ≤ a ∧ a < stop
h1 : l + 1 ≤ fuel + 1
h2 : ∀ (j : Nat), stop ≤ i✝ + step * j ↔ l + 1 ≤ j
i : Nat
⊢ stop ≤ i✝ + step + step * i ↔ l ≤ i
state_after: no goals

tactic: simp [List.range', h, numElems_stop_le_start ⟨start, stop, step⟩ (Nat.not_lt.1 h), L]
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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : ¬start < stop
⊢ forIn'.loop start stop step f stop start ⋯ init = forIn (List.pmap Subtype.mk L H) init f'
state_after: 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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : ¬start < stop
⊢ forIn'.loop start stop step f stop start ⋯ init = pure init

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 { start := start, stop := stop, step := step }.numElems step
f' : { a // start ≤ a ∧ a < stop } → β → m (ForInStep β) :=
  fun x =>
    match (motive := { a // start ≤ a ∧ a < stop } → β → m (ForInStep β)) x with
    | ⟨a, h⟩ => f a h
H : ∀ (a : Nat), a ∈ L → start ≤ a ∧ a < stop
h : ¬start < stop
⊢ forIn'.loop start stop step f stop start ⋯ init = pure init
state_after: no goals