Theorem: Array.SatisfiesM_foldlM
File: .lake/packages/batteries/Batteries/Data/Array/Monadic.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 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: 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 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: 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) (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: 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])
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])
i j : Nat
b : β
h₁ : j ≤ as.size
h₂ : as.size ≤ i + j
H : motive j b
hj : 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)
state_after: 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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
j : Nat
b : β
h₁ : j ≤ as.size
H : motive j b
hj : j < as.size
i✝ : Nat
h₂ : as.size ≤ 0 + j
⊢ SatisfiesM (motive as.size) (pure b)

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

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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
j : Nat
b : β
h₁ : j ≤ as.size
H : motive j b
hj : j < as.size
i✝ : Nat
h₂ : as.size ≤ 0 + j
⊢ as.size > 0 + j
state_after: no goals

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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
j : Nat
b : β
h₁ : j ≤ as.size
H : motive j b
hj : j < as.size
i✝ i'✝ : Nat
h₂ : as.size ≤ i'✝.succ + j
⊢ SatisfiesM (motive as.size)
    (let_fun this := ⋯;
    do
    let __do_lift ← f b as[j]
    foldlM.loop f as as.size ⋯ i'✝ (j + 1) __do_lift)
state_after: no goals

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 as.size) (b : β), motive (↑i) b → SatisfiesM (motive (↑i + 1)) (f b as[i])
j : Nat
b : β
h₁ : j ≤ as.size
H : motive j b
hj : j < as.size
i✝ i'✝ : Nat
h₂ : as.size ≤ i'✝.succ + j
x✝ : β
⊢ as.size ≤ i'✝ + (↑⟨j, hj⟩ + 1)
state_after: no goals

tactic: next hj => exact Nat.le_antisymm h₁ (Nat.ge_of_not_lt hj) ▸ .pure H
state_before: 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)
state_after: no goals

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 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
hj : ¬j < as.size
⊢ SatisfiesM (motive as.size) (pure b)
state_after: no goals