Theorem: Array.SatisfiesM_foldlM
File: Std/Data/Array/Init/Lemmas.lean

tactic: simp [foldlM]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
⊢ SatisfiesM (motive (size as)) (foldlM f init as 0 (size as))

tactic: exact go (Nat.zero_le _) (Nat.le_refl _) h0
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
⊢ SatisfiesM (motive (size as)) (foldlM.loop f as (size as) (_ : size as ≤ size as) (size as) 0 init)

tactic: unfold foldlM.loop
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
i j : Nat
b : β
h₁ : j ≤ size as
h₂ : size as ≤ i + j
H : motive j b
⊢ SatisfiesM (motive (size as)) (foldlM.loop f as (size as) (_ : size as ≤ size as) i j b)

tactic: split
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
i j : Nat
b : β
h₁ : j ≤ size as
h₂ : size as ≤ i + j
H : motive j b
⊢ SatisfiesM (motive (size as))
    (if hlt : j < size as then
      match i with
      | 0 => pure b
      | Nat.succ i' =>
        let_fun this := (_ : j < size as);
        do
        let __do_lift ← f b as[j]
        foldlM.loop f as (size as) (_ : size as ≤ size as) i' (j + 1) __do_lift
    else pure b)

tactic: split
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
i j : Nat
b : β
h₁ : j ≤ size as
h₂ : size as ≤ i + j
H : motive j b
hj : j < size as
⊢ SatisfiesM (motive (size as))
    (match i with
    | 0 => pure b
    | Nat.succ i' =>
      let_fun this := (_ : j < size as);
      do
      let __do_lift ← f b as[j]
      foldlM.loop f as (size as) (_ : size as ≤ size as) i' (j + 1) __do_lift)

tactic: cases Nat.not_le_of_gt (by simp [hj]) h₂
state_before: case h_1
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
j : Nat
b : β
h₁ : j ≤ size as
H : motive j b
hj : j < size as
i✝ : Nat
h₂ : size as ≤ 0 + j
⊢ SatisfiesM (motive (size as)) (pure b)

tactic: simp [hj]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
j : Nat
b : β
h₁ : j ≤ size as
H : motive j b
hj : j < size as
i✝ : Nat
h₂ : size as ≤ 0 + j
⊢ size as > 0 + j

tactic: exact (hf ⟨j, hj⟩ b H).bind fun _ => go hj (by rwa [Nat.succ_add] at h₂)
state_before: case h_2
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
j : Nat
b : β
h₁ : j ≤ size as
H : motive j b
hj : j < size as
i✝ i'✝ : Nat
h₂ : size as ≤ Nat.succ i'✝ + j
⊢ SatisfiesM (motive (size as))
    (let_fun this := (_ : j < size as);
    do
    let __do_lift ← f b as[j]
    foldlM.loop f as (size as) (_ : size as ≤ size as) i'✝ (j + 1) __do_lift)

tactic: rwa [Nat.succ_add] at h₂
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
j : Nat
b : β
h₁ : j ≤ size as
H : motive j b
hj : j < size as
i✝ i'✝ : Nat
h₂ : size as ≤ Nat.succ i'✝ + j
x✝ : β
⊢ size as ≤ i'✝ + ({ val := j, isLt := hj }.val + 1)

tactic: next hj => exact Nat.le_antisymm h₁ (Nat.ge_of_not_lt hj) ▸ .pure H
state_before: case inr
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
i j : Nat
b : β
h₁ : j ≤ size as
h₂ : size as ≤ i + j
H : motive j b
h✝ : ¬j < size as
⊢ SatisfiesM (motive (size as)) (pure b)

tactic: exact Nat.le_antisymm h₁ (Nat.ge_of_not_lt hj) ▸ .pure H
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
motive : Nat → β → Prop
init : β
h0 : motive 0 init
f : β → α → m β
hf : ∀ (i : Fin (size as)) (b : β), motive i.val b → SatisfiesM (motive (i.val + 1)) (f b as[i])
i j : Nat
b : β
h₁ : j ≤ size as
h₂ : size as ≤ i + j
H : motive j b
hj : ¬j < size as
⊢ SatisfiesM (motive (size as)) (pure b)