Theorem: Array.SatisfiesM_foldrM
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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
i : Nat
b : β
hi : i ≤ as.size
H : motive i b
⊢ SatisfiesM (motive 0) (foldrM.fold f as 0 i hi 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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
i : Nat
b : β
hi : i ≤ as.size
H : motive i b
⊢ SatisfiesM (motive 0)
    (if (i == 0) = true then pure b
    else
      match i, hi with
      | 0, x => pure b
      | i.succ, h =>
        let_fun this := ⋯;
        do
        let __do_lift ← f as[i] b
        foldrM.fold f as 0 i ⋯ __do_lift)
tactic: unfold foldrM.fold
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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
i : Nat
b : β
hi : i ≤ as.size
H : motive i b
⊢ SatisfiesM (motive 0)
    (if (i == 0) = true then pure b
    else
      match i, hi with
      | 0, x => pure b
      | i.succ, h =>
        let_fun this := ⋯;
        do
        let __do_lift ← f as[i] b
        foldrM.fold f as 0 i ⋯ __do_lift)
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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
i : Nat
b : β
hi : i ≤ as.size
H : motive i b
⊢ SatisfiesM (motive 0)
    (if i = 0 then pure b
    else
      match i, hi with
      | 0, x => pure b
      | i.succ, h => do
        let __do_lift ← f as[i] b
        foldrM.fold f as 0 i ⋯ __do_lift)
tactic: simp
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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
i : Nat
b : β
hi : i ≤ as.size
H : motive i b
⊢ SatisfiesM (motive 0)
    (if i = 0 then pure b
    else
      match i, hi with
      | 0, x => pure b
      | i.succ, h => do
        let __do_lift ← f as[i] b
        foldrM.fold f as 0 i ⋯ __do_lift)
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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
i : Nat
b : β
hi : i ≤ as.size
H : motive i b
h✝ : i = 0
⊢ SatisfiesM (motive 0) (pure b)

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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
i : Nat
b : β
hi : i ≤ as.size
H : motive i b
h✝ : ¬i = 0
⊢ SatisfiesM (motive 0)
    (match i, hi with
    | 0, x => pure b
    | i.succ, h => do
      let __do_lift ← f as[i] b
      foldrM.fold f as 0 i ⋯ __do_lift)
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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
⊢ SatisfiesM (motive 0) (foldrM f init as as.size)
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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
⊢ SatisfiesM (motive 0) (if 0 < as.size then foldrM.fold f as 0 as.size ⋯ init else pure init)
tactic: simp [foldrM]
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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
⊢ SatisfiesM (motive 0) (if 0 < as.size then foldrM.fold f as 0 as.size ⋯ init else pure init)
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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
h✝ : 0 < as.size
⊢ SatisfiesM (motive 0) (foldrM.fold f as 0 as.size ⋯ init)

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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
h✝ : ¬0 < as.size
⊢ SatisfiesM (motive 0) (pure init)
tactic: split
state_before: 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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
h✝ : 0 < as.size
⊢ SatisfiesM (motive 0) (foldrM.fold f as 0 as.size ⋯ init)

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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
h✝ : ¬0 < as.size
⊢ SatisfiesM (motive 0) (pure init)
state_after: 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 as.size init
f : α → β → m β
hf : ∀ (i : Fin as.size) (b : β), motive (↑i + 1) b → SatisfiesM (motive ↑i) (f as[i] b)
h✝ : ¬0 < as.size
⊢ SatisfiesM (motive 0) (pure init)
tactic: {exact go _ h0}