Theorem: Array.SatisfiesM_mapIdxM
File: Std/Data/Array/Lemmas.lean

tactic: simp [mapIdxM]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
⊢ SatisfiesM (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
    (mapIdxM as f)

tactic: exact go rfl (fun.) h0
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
⊢ SatisfiesM (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
    (mapIdxM.map as f (size as) 0 (_ : size as + 0 = size as + 0) #[])

tactic: have := (Nat.zero_add _).symm.trans h
state_before: case zero
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
bs : Array β
j : Nat
h : Nat.zero + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
⊢ SatisfiesM (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
    (pure bs)

tactic: exact .pure ⟨this ▸ hm, h₁ ▸ this, fun _ _ => h₂ ..⟩
state_before: case zero
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
bs : Array β
j : Nat
h : Nat.zero + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
this : j = size as
⊢ SatisfiesM (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
    (pure bs)

tactic: refine (hs _ (by exact hm)).bind fun b hb => ih (by simp [h₁]) (fun i hi hi' => ?_) hb.2
state_before: case succ
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i j h bs)
bs : Array β
j : Nat
h : Nat.succ i + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
⊢ SatisfiesM (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i]) do
    let __do_lift ← f { val := j, isLt := (_ : j < size as) } as[j]
    mapIdxM.map as f i (j + 1) (_ : i + (j + 1) = size as) (push bs __do_lift)

tactic: simp at hi'
state_before: case succ
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i✝ : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i✝ + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i✝ j h bs)
bs : Array β
j : Nat
h : Nat.succ i✝ + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
b : β
hb : p { val := j, isLt := (_ : j < size as) } b ∧ motive ({ val := j, isLt := (_ : j < size as) }.val + 1)
i : Nat
hi : i < size as
hi' : i < size (push bs b)
⊢ p { val := i, isLt := hi } (push bs b)[i]

tactic: simp [get_push]
state_before: case succ
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i✝ : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i✝ + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i✝ j h bs)
bs : Array β
j : Nat
h : Nat.succ i✝ + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
b : β
hb : p { val := j, isLt := (_ : j < size as) } b ∧ motive ({ val := j, isLt := (_ : j < size as) }.val + 1)
i : Nat
hi : i < size as
hi'✝ : i < size (push bs b)
hi' : i < size bs + 1
⊢ p { val := i, isLt := hi } (push bs b)[i]

tactic: split
state_before: case succ
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i✝ : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i✝ + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i✝ j h bs)
bs : Array β
j : Nat
h : Nat.succ i✝ + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
b : β
hb : p { val := j, isLt := (_ : j < size as) } b ∧ motive ({ val := j, isLt := (_ : j < size as) }.val + 1)
i : Nat
hi : i < size as
hi'✝ : i < size (push bs b)
hi' : i < size bs + 1
⊢ p { val := i, isLt := hi } (if h : i < size bs then bs[i] else b)

tactic: exact hm
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i j h bs)
bs : Array β
j : Nat
h : Nat.succ i + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
⊢ motive { val := j, isLt := (_ : j < size as) }.val

tactic: simp [h₁]
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i j h bs)
bs : Array β
j : Nat
h : Nat.succ i + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
b : β
hb : p { val := j, isLt := (_ : j < size as) } b ∧ motive ({ val := j, isLt := (_ : j < size as) }.val + 1)
⊢ j + 1 = size (push bs b)

tactic: next h => exact h₂ _ _ h
state_before: case succ.inl
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i✝ : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i✝ + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i✝ j h bs)
bs : Array β
j : Nat
h : Nat.succ i✝ + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
b : β
hb : p { val := j, isLt := (_ : j < size as) } b ∧ motive ({ val := j, isLt := (_ : j < size as) }.val + 1)
i : Nat
hi : i < size as
hi'✝ : i < size (push bs b)
hi' : i < size bs + 1
h✝ : i < size bs
⊢ p { val := i, isLt := hi } bs[i]

tactic: exact h₂ _ _ h
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i✝ : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i✝ + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i✝ j h bs)
bs : Array β
j : Nat
h✝ : Nat.succ i✝ + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
b : β
hb : p { val := j, isLt := (_ : j < size as) } b ∧ motive ({ val := j, isLt := (_ : j < size as) }.val + 1)
i : Nat
hi : i < size as
hi'✝ : i < size (push bs b)
hi' : i < size bs + 1
h : i < size bs
⊢ p { val := i, isLt := hi } bs[i]

tactic: next h => cases h₁.symm ▸ (Nat.le_or_eq_of_le_succ hi').resolve_left h; exact hb.1
state_before: case succ.inr
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i✝ : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i✝ + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i✝ j h bs)
bs : Array β
j : Nat
h : Nat.succ i✝ + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
b : β
hb : p { val := j, isLt := (_ : j < size as) } b ∧ motive ({ val := j, isLt := (_ : j < size as) }.val + 1)
i : Nat
hi : i < size as
hi'✝ : i < size (push bs b)
hi' : i < size bs + 1
h✝ : ¬i < size bs
⊢ p { val := i, isLt := hi } b

tactic: cases h₁.symm ▸ (Nat.le_or_eq_of_le_succ hi').resolve_left h
state_before: m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i✝ : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i✝ + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i✝ j h bs)
bs : Array β
j : Nat
h✝ : Nat.succ i✝ + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
b : β
hb : p { val := j, isLt := (_ : j < size as) } b ∧ motive ({ val := j, isLt := (_ : j < size as) }.val + 1)
i : Nat
hi : i < size as
hi'✝ : i < size (push bs b)
hi' : i < size bs + 1
h : ¬i < size bs
⊢ p { val := i, isLt := hi } b

tactic: exact hb.1
state_before: case refl
m : Type u_1 → Type u_2
α : Type u_3
β : Type u_1
inst✝¹ : Monad m
inst✝ : LawfulMonad m
as : Array α
f : Fin (size as) → α → m β
motive : Nat → Prop
h0 : motive 0
p : Fin (size as) → β → Prop
hs : ∀ (i : Fin (size as)), motive i.val → SatisfiesM (fun x => p i x ∧ motive (i.val + 1)) (f i as[i])
i : Nat
ih :
  ∀ {bs : Array β} {j : Nat} {h : i + j = size as},
    j = size bs →
      (∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]) →
        motive j →
          SatisfiesM
            (fun arr => motive (size as) ∧ ∃ eq, ∀ (i : Nat) (h : i < size as), p { val := i, isLt := h } arr[i])
            (mapIdxM.map as f i j h bs)
bs : Array β
j : Nat
h✝ : Nat.succ i + j = size as
h₁ : j = size bs
h₂ : ∀ (i : Nat) (h : i < size as) (h' : i < size bs), p { val := i, isLt := h } bs[i]
hm : motive j
b : β
hb : p { val := j, isLt := (_ : j < size as) } b ∧ motive ({ val := j, isLt := (_ : j < size as) }.val + 1)
hi : j < size as
hi'✝ : j < size (push bs b)
hi' : j < size bs + 1
h : ¬j < size bs
⊢ p { val := j, isLt := hi } b