Theorem: Array.SatisfiesM_foldlM
File: .lake/packages/batteries/Batteries/Data/Array/Monadic.lean

Proof steps:
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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
i j : Nat
b : β
h₁ : j ≤ as.size
h₂ : as.size ≤ i + j
H : motive j b
⊢ SatisfiesM (motive as.size) (foldlM.loop f as as.size ⋯ i j b)
state_after: 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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
i j : Nat
b : β
h₁ : j ≤ as.size
h₂ : as.size ≤ i + j
H : motive j b
⊢ SatisfiesM (motive as.size)
    (if hlt : j < as.size then
      match i with
      | 0 => pure b
      | i'.succ =>
        let_fun this := ⋯;
        do
        let __do_lift ← f b as[j]
        foldlM.loop f as as.size ⋯ i' (j + 1) __do_lift
    else pure b)
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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
i j : Nat
b : β
h₁ : j ≤ as.size
h₂ : as.size ≤ i + j
H : motive j b
⊢ SatisfiesM (motive as.size)
    (if hlt : j < as.size then
      match i with
      | 0 => pure b
      | i'.succ =>
        let_fun this := ⋯;
        do
        let __do_lift ← f b as[j]
        foldlM.loop f as as.size ⋯ i' (j + 1) __do_lift
    else pure b)
state_after: case isTrue
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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
i j : Nat
b : β
h₁ : j ≤ as.size
h₂ : as.size ≤ i + j
H : motive j b
h✝ : j < as.size
⊢ SatisfiesM (motive as.size)
    (match i with
    | 0 => pure b
    | i'.succ =>
      let_fun this := ⋯;
      do
      let __do_lift ← f b as[j]
      foldlM.loop f as as.size ⋯ i' (j + 1) __do_lift)

case isFalse
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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
i j : Nat
b : β
h₁ : j ≤ as.size
h₂ : as.size ≤ i + j
H : motive j b
h✝ : ¬j < as.size
⊢ SatisfiesM (motive as.size) (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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
⊢ SatisfiesM (motive as.size) (foldlM f init as 0)
state_after: 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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
⊢ SatisfiesM (motive as.size) (foldlM.loop f as as.size ⋯ as.size 0 init)
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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
⊢ SatisfiesM (motive as.size) (foldlM.loop f as as.size ⋯ as.size 0 init)
state_after: no goals
tactic: exact go (Nat.zero_le _) (Nat.le_refl _) h0