l3lab/ntp-mathlib huggingface dataset:
theorem mapIdx_eq_ofFn {α β} (l : List α) (f : ℕ → α → β) :
    l.mapIdx f = ofFn fun i : Fin l.length ↦ f (i : ℕ) (l.get i) := by
  

Proof state:
α✝ : Type u
β✝ : Type v
α : Type u_1
β : Type u_2
l : List α
f : ℕ → α → β
⊢ mapIdx f l = ofFn fun i => f (↑i) (get l i)

Next tactic:
induction' l with hd tl IH generalizing f
theorem mapIdx_eq_ofFn {α β} (l : List α) (f : ℕ → α → β) :
    l.mapIdx f = ofFn fun i : Fin l.length ↦ f (i : ℕ) (l.get i) := by
  induction' l with hd tl IH generalizing f
  · 

Proof state:
case nil
α✝ : Type u
β✝ : Type v
α : Type u_1
β : Type u_2
f : ℕ → α → β
⊢ mapIdx f [] = ofFn fun i => f (↑i) (get [] i)

Next tactic:
rfl
theorem mapIdx_eq_ofFn {α β} (l : List α) (f : ℕ → α → β) :
    l.mapIdx f = ofFn fun i : Fin l.length ↦ f (i : ℕ) (l.get i) := by
  induction' l with hd tl IH generalizing f
  · rfl
  · 

Proof state:
case cons
α✝ : Type u
β✝ : Type v
α : Type u_1
β : Type u_2
hd : α
tl : List α
IH : ∀ (f : ℕ → α → β), mapIdx f tl = ofFn fun i => f (↑i) (get tl i)
f : ℕ → α → β
⊢ mapIdx f (hd :: tl) = ofFn fun i => f (↑i) (get (hd :: tl) i)

Next tactic:
simp [IH]
theorem foldrIdx_eq_foldrIdxSpec (f : ℕ → α → β → β) (b as start) :
    foldrIdx f b as start = foldrIdxSpec f b as start := by
  

Proof state:
α : Type u
β : Type v
f : ℕ → α → β → β
b : β
as : List α
start : ℕ
⊢ foldrIdx f b as start = foldrIdxSpec f b as start

Next tactic:
induction as generalizing start
theorem foldrIdx_eq_foldrIdxSpec (f : ℕ → α → β → β) (b as start) :
    foldrIdx f b as start = foldrIdxSpec f b as start := by
  induction as generalizing start
  · 

Proof state:
case nil
α : Type u
β : Type v
f : ℕ → α → β → β
b : β
start : ℕ
⊢ foldrIdx f b [] start = foldrIdxSpec f b [] start

Next tactic:
rfl
theorem foldrIdx_eq_foldrIdxSpec (f : ℕ → α → β → β) (b as start) :
    foldrIdx f b as start = foldrIdxSpec f b as start := by
  induction as generalizing start
  · rfl
  · 

Proof state:
case cons
α : Type u
β : Type v
f : ℕ → α → β → β
b : β
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ (start : ℕ), foldrIdx f b tail✝ start = foldrIdxSpec f b tail✝ start
start : ℕ
⊢ foldrIdx f b (head✝ :: tail✝) start = foldrIdxSpec f b (head✝ :: tail✝) start

Next tactic:
simp only [foldrIdx, foldrIdxSpec_cons, *]
theorem foldrIdx_eq_foldr_enum (f : ℕ → α → β → β) (b : β) (as : List α) :
    foldrIdx f b as = foldr (uncurry f) b (enum as) := by
  

Proof state:
α : Type u
β : Type v
f : ℕ → α → β → β
b : β
as : List α
⊢ foldrIdx f b as = foldr (uncurry f) b (enum as)

Next tactic:
simp only [foldrIdx, foldrIdxSpec, foldrIdx_eq_foldrIdxSpec, enum]
theorem indexesValues_eq_filter_enum (p : α → Prop) [DecidablePred p] (as : List α) :
    indexesValues p as = filter (p ∘ Prod.snd) (enum as) := by
  

Proof state:
α : Type u
β : Type v
p : α → Prop
inst✝ : DecidablePred p
as : List α
⊢ indexesValues (fun b => decide (p b)) as = filter ((fun b => decide (p b)) ∘ Prod.snd) (enum as)

Next tactic:
simp (config := { unfoldPartialApp := true }) [indexesValues, foldrIdx_eq_foldr_enum, uncurry,
    filter_eq_foldr]
theorem findIdxs_eq_map_indexesValues (p : α → Prop) [DecidablePred p] (as : List α) :
    findIdxs p as = map Prod.fst (indexesValues p as) := by
  

Proof state:
α : Type u
β : Type v
p : α → Prop
inst✝ : DecidablePred p
as : List α
⊢ findIdxs (fun b => decide (p b)) as = map Prod.fst (indexesValues (fun b => decide (p b)) as)

Next tactic:
simp (config := { unfoldPartialApp := true }) only [indexesValues_eq_filter_enum,
    map_filter_eq_foldr, findIdxs, uncurry, foldrIdx_eq_foldr_enum, decide_eq_true_eq, comp_apply,
    Bool.cond_decide]
theorem foldlIdx_eq_foldlIdxSpec (f : ℕ → α → β → α) (a bs start) :
    foldlIdx f a bs start = foldlIdxSpec f a bs start := by
  

Proof state:
α : Type u
β : Type v
f : ℕ → α → β → α
a : α
bs : List β
start : ℕ
⊢ foldlIdx f a bs start = foldlIdxSpec f a bs start

Next tactic:
induction bs generalizing start a
theorem foldlIdx_eq_foldlIdxSpec (f : ℕ → α → β → α) (a bs start) :
    foldlIdx f a bs start = foldlIdxSpec f a bs start := by
  induction bs generalizing start a
  · 

Proof state:
case nil
α : Type u
β : Type v
f : ℕ → α → β → α
a : α
start : ℕ
⊢ foldlIdx f a [] start = foldlIdxSpec f a [] start

Next tactic:
rfl
theorem foldlIdx_eq_foldlIdxSpec (f : ℕ → α → β → α) (a bs start) :
    foldlIdx f a bs start = foldlIdxSpec f a bs start := by
  induction bs generalizing start a
  · rfl
  · 

Proof state:
case cons
α : Type u
β : Type v
f : ℕ → α → β → α
head✝ : β
tail✝ : List β
tail_ih✝ : ∀ (a : α) (start : ℕ), foldlIdx f a tail✝ start = foldlIdxSpec f a tail✝ start
a : α
start : ℕ
⊢ foldlIdx f a (head✝ :: tail✝) start = foldlIdxSpec f a (head✝ :: tail✝) start

Next tactic:
simp [foldlIdxSpec, *]
theorem foldlIdx_eq_foldl_enum (f : ℕ → α → β → α) (a : α) (bs : List β) :
    foldlIdx f a bs = foldl (fun a p ↦ f p.fst a p.snd) a (enum bs) := by
  

Proof state:
α : Type u
β : Type v
f : ℕ → α → β → α
a : α
bs : List β
⊢ foldlIdx f a bs = foldl (fun a p => f p.1 a p.2) a (enum bs)

Next tactic:
simp only [foldlIdx, foldlIdxSpec, foldlIdx_eq_foldlIdxSpec, enum]
theorem foldrIdxM_eq_foldrM_enum {α β} (f : ℕ → α → β → m β) (b : β) (as : List α) [LawfulMonad m] :
    foldrIdxM f b as = foldrM (uncurry f) b (enum as) := by
  

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
α : Type u_1
β : Type u
f : ℕ → α → β → m β
b : β
as : List α
inst✝ : LawfulMonad m
⊢ foldrIdxM f b as = foldrM (uncurry f) b (enum as)

Next tactic:
simp (config := { unfoldPartialApp := true }) only [foldrIdxM, foldrM_eq_foldr,
    foldrIdx_eq_foldr_enum, uncurry]
theorem foldlIdxM_eq_foldlM_enum [LawfulMonad m] {α β} (f : ℕ → β → α → m β) (b : β) (as : List α) :
    foldlIdxM f b as = List.foldlM (fun b p ↦ f p.fst b p.snd) b (enum as) := by
  

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → β → α → m β
b : β
as : List α
⊢ foldlIdxM f b as = List.foldlM (fun b p => f p.1 b p.2) b (enum as)

Next tactic:
rw [foldlIdxM, foldlM_eq_foldl, foldlIdx_eq_foldl_enum]
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
arr : Array β
as : List α
⊢ mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as

Next tactic:
generalize e : as.length = len
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
arr : Array β
as : List α
len : ℕ
e : length as = len
⊢ mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as

Next tactic:
revert as arr
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
⊢ ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as

Next tactic:
induction' len with len ih
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> 

Proof state:
case zero
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
⊢ ∀ (arr : Array β) (as : List α),
    length as = Nat.zero →
      mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as

Next tactic:
intro arr as h
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> 

Proof state:
case succ
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
⊢ ∀ (arr : Array β) (as : List α),
    length as = Nat.succ len →
      mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as

Next tactic:
intro arr as h
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · 

Proof state:
case zero
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
arr : Array β
as : List α
h : length as = Nat.zero
⊢ mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as

Next tactic:
have : as = [] := by cases as; rfl; contradiction
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by 

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
arr : Array β
as : List α
h : length as = Nat.zero
⊢ as = []

Next tactic:
cases as
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; 

Proof state:
case nil
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
arr : Array β
h : length [] = Nat.zero
⊢ [] = []
case cons
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
arr : Array β
head✝ : α
tail✝ : List α
h : length (head✝ :: tail✝) = Nat.zero
⊢ head✝ :: tail✝ = []

Next tactic:
rfl
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; 

Proof state:
case cons
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
arr : Array β
head✝ : α
tail✝ : List α
h : length (head✝ :: tail✝) = Nat.zero
⊢ head✝ :: tail✝ = []

Next tactic:
contradiction
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    

Proof state:
case zero
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
arr : Array β
as : List α
h : length as = Nat.zero
this : as = []
⊢ mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as

Next tactic:
simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
  · 

Proof state:
case succ
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
arr : Array β
as : List α
h : length as = Nat.succ len
⊢ mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as

Next tactic:
match as with
    | nil => contradiction
    | cons head tail =>
      simp only [length_cons, Nat.succ.injEq] at h
      simp only [mapIdxM.go, mapIdxMAuxSpec_cons, map_eq_pure_bind, seq_eq_bind_map,
        LawfulMonad.bind_assoc, pure_bind]
      congr
      conv => { lhs; intro x; rw [ih _ _ h]; }
      funext x
      simp only [Array.toList_eq, Array.push_data, append_assoc, singleton_append, Array.size_push,
        map_eq_pure_bind]
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
  · match as with
    | nil => 

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
arr : Array β
as : List α
h : length [] = Nat.succ len
⊢ mapIdxM.go f [] arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) []

Next tactic:
contradiction
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
  · match as with
    | nil => contradiction
    | cons head tail =>
      

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
arr : Array β
as : List α
head : α
tail : List α
h : length (head :: tail) = Nat.succ len
⊢ mapIdxM.go f (head :: tail) arr =
    (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) (head :: tail)

Next tactic:
simp only [length_cons, Nat.succ.injEq] at h
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
  · match as with
    | nil => contradiction
    | cons head tail =>
      simp only [length_cons, Nat.succ.injEq] at h
      

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
arr : Array β
as : List α
head : α
tail : List α
h : length tail = len
⊢ mapIdxM.go f (head :: tail) arr =
    (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) (head :: tail)

Next tactic:
simp only [mapIdxM.go, mapIdxMAuxSpec_cons, map_eq_pure_bind, seq_eq_bind_map,
        LawfulMonad.bind_assoc, pure_bind]
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
  · match as with
    | nil => contradiction
    | cons head tail =>
      simp only [length_cons, Nat.succ.injEq] at h
      simp only [mapIdxM.go, mapIdxMAuxSpec_cons, map_eq_pure_bind, seq_eq_bind_map,
        LawfulMonad.bind_assoc, pure_bind]
      

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
arr : Array β
as : List α
head : α
tail : List α
h : length tail = len
⊢ (do
      let __do_lift ← f (Array.size arr) head
      mapIdxM.go f tail (Array.push arr __do_lift)) =
    do
    let x ← f (Array.size arr) head
    let x_1 ← mapIdxMAuxSpec f (Array.size arr + 1) tail
    pure (Array.toList arr ++ x :: x_1)

Next tactic:
congr
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
  · match as with
    | nil => contradiction
    | cons head tail =>
      simp only [length_cons, Nat.succ.injEq] at h
      simp only [mapIdxM.go, mapIdxMAuxSpec_cons, map_eq_pure_bind, seq_eq_bind_map,
        LawfulMonad.bind_assoc, pure_bind]
      congr
      

Proof state:
case e_a
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
arr : Array β
as : List α
head : α
tail : List α
h : length tail = len
⊢ (fun __do_lift => mapIdxM.go f tail (Array.push arr __do_lift)) = fun x => do
    let x_1 ← mapIdxMAuxSpec f (Array.size arr + 1) tail
    pure (Array.toList arr ++ x :: x_1)

Next tactic:
conv => { lhs; intro x; rw [ih _ _ h]; }
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
  · match as with
    | nil => contradiction
    | cons head tail =>
      simp only [length_cons, Nat.succ.injEq] at h
      simp only [mapIdxM.go, mapIdxMAuxSpec_cons, map_eq_pure_bind, seq_eq_bind_map,
        LawfulMonad.bind_assoc, pure_bind]
      congr
      conv => 

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
arr : Array β
as : List α
head : α
tail : List α
h : length tail = len
| (fun __do_lift => mapIdxM.go f tail (Array.push arr __do_lift)) = fun x => do
    let x_1 ← mapIdxMAuxSpec f (Array.size arr + 1) tail
    pure (Array.toList arr ++ x :: x_1)

Next tactic:
{ lhs; intro x; rw [ih _ _ h]; }
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
  · match as with
    | nil => contradiction
    | cons head tail =>
      simp only [length_cons, Nat.succ.injEq] at h
      simp only [mapIdxM.go, mapIdxMAuxSpec_cons, map_eq_pure_bind, seq_eq_bind_map,
        LawfulMonad.bind_assoc, pure_bind]
      congr
      conv => { 

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
arr : Array β
as : List α
head : α
tail : List α
h : length tail = len
| (fun __do_lift => mapIdxM.go f tail (Array.push arr __do_lift)) = fun x => do
    let x_1 ← mapIdxMAuxSpec f (Array.size arr + 1) tail
    pure (Array.toList arr ++ x :: x_1)

Next tactic:
lhs
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
  · match as with
    | nil => contradiction
    | cons head tail =>
      simp only [length_cons, Nat.succ.injEq] at h
      simp only [mapIdxM.go, mapIdxMAuxSpec_cons, map_eq_pure_bind, seq_eq_bind_map,
        LawfulMonad.bind_assoc, pure_bind]
      congr
      conv => { lhs; 

Proof state:
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
arr : Array β
as : List α
head : α
tail : List α
h : length tail = len
| fun __do_lift => mapIdxM.go f tail (Array.push arr __do_lift)

Next tactic:
intro x
theorem mapIdxMGo_eq_mapIdxMAuxSpec {α β} (f : ℕ → α → m β) (arr : Array β) (as : List α) :
    mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by
  generalize e : as.length = len
  revert as arr
  induction' len with len ih <;> intro arr as h
  · have : as = [] := by cases as; rfl; contradiction
    simp only [this, mapIdxM.go, mapIdxMAuxSpec, List.traverse, map_pure, append_nil]
  · match as with
    | nil => contradiction
    | cons head tail =>
      simp only [length_cons, Nat.succ.injEq] at h
      simp only [mapIdxM.go, mapIdxMAuxSpec_cons, map_eq_pure_bind, seq_eq_bind_map,
        LawfulMonad.bind_assoc, pure_bind]
      congr
      conv => { lhs; intro x; 

Proof state:
case h
α✝ : Type u
β✝ : Type v
m : Type u → Type v
inst✝¹ : Monad m
inst✝ : LawfulMonad m
α : Type u_1
β : Type u
f : ℕ → α → m β
len : ℕ
ih :
  ∀ (arr : Array β) (as : List α),
    length as = len → mapIdxM.go f as arr = (fun x => Array.toList arr ++ x) <$> mapIdxMAuxSpec f (Array.size arr) as
arr : Array β
as : List α
head : α
tail : List α
h : length tail = len
x : β
| mapIdxM.go f tail (Array.push arr x)

Next tactic:
rw [ih _ _ h]