l3lab/ntp-mathlib huggingface dataset:
/-- Induction principle for values produced by a `foldl`: if a property holds
for the seed element `b : β` and for all incremental `op : β → α → β`
performed on the elements `(a : α) ∈ l`. The principle is given for
a `Sort`-valued predicate, i.e., it can also be used to construct data. -/
def foldlRecOn {C : β → Sort*} (l : List α) (op : β → α → β) (b : β) (hb : C b)
    (hl : ∀ b, C b → ∀ a ∈ l, C (op b a)) : C (foldl op b l) := by
  induction l generalizing b with
  | nil => exact hb
  | cons hd tl IH =>
    refine' IH _ _ _
    · exact hl b hb hd (mem_cons_self hd tl)
    · intro y hy x hx
      

Proof state:
case cons.refine'_2
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
C : β → Sort u_2
op : β → α → β
hd : α
tl : List α
IH : (b : β) → C b → ((b : β) → C b → (a : α) → a ∈ tl → C (op b a)) → C (foldl op b tl)
b : β
hb : C b
hl : (b : β) → C b → (a : α) → a ∈ hd :: tl → C (op b a)
y : β
hy : C y
x : α
hx : x ∈ tl
⊢ C (op y x)

Next tactic:
exact hl y hy x (mem_cons_of_mem hd hx)
theorem length_scanl : ∀ a l, length (scanl f a l) = l.length + 1
  | a, [] => rfl
  | a, x :: l => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a✝ : α
l✝ : List α
a : β
x : α
l : List α
⊢ length (scanl f a (x :: l)) = length (x :: l) + 1

Next tactic:
rw [scanl, length_cons, length_cons, ← succ_eq_add_one, congr_arg succ]
theorem length_scanl : ∀ a l, length (scanl f a l) = l.length + 1
  | a, [] => rfl
  | a, x :: l => by
    rw [scanl, length_cons, length_cons, ← succ_eq_add_one, congr_arg succ]
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a✝ : α
l✝ : List α
a : β
x : α
l : List α
⊢ length (scanl f (f a x) l) = length l + 1

Next tactic:
exact length_scanl _ _
@[simp]
theorem scanl_cons : scanl f b (a :: l) = [b] ++ scanl f (f b a) l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a : α
l : List α
⊢ scanl f b (a :: l) = [b] ++ scanl f (f b a) l

Next tactic:
simp only [scanl, eq_self_iff_true, singleton_append, and_self_iff]
@[simp]
theorem get?_zero_scanl : (scanl f b l).get? 0 = some b := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a : α
l : List α
⊢ get? (scanl f b l) 0 = some b

Next tactic:
cases l
@[simp]
theorem get?_zero_scanl : (scanl f b l).get? 0 = some b := by
  cases l
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a : α
⊢ get? (scanl f b []) 0 = some b

Next tactic:
simp only [get?, scanl_nil]
@[simp]
theorem get?_zero_scanl : (scanl f b l).get? 0 = some b := by
  cases l
  · simp only [get?, scanl_nil]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a head✝ : α
tail✝ : List α
⊢ get? (scanl f b (head✝ :: tail✝)) 0 = some b

Next tactic:
simp only [get?, scanl_cons, singleton_append]
@[simp]
theorem get_zero_scanl {h : 0 < (scanl f b l).length} : (scanl f b l).get ⟨0, h⟩ = b := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a : α
l : List α
h : 0 < length (scanl f b l)
⊢ get (scanl f b l) { val := 0, isLt := h } = b

Next tactic:
cases l
@[simp]
theorem get_zero_scanl {h : 0 < (scanl f b l).length} : (scanl f b l).get ⟨0, h⟩ = b := by
  cases l
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a : α
h : 0 < length (scanl f b [])
⊢ get (scanl f b []) { val := 0, isLt := h } = b

Next tactic:
simp only [get, scanl_nil]
@[simp]
theorem get_zero_scanl {h : 0 < (scanl f b l).length} : (scanl f b l).get ⟨0, h⟩ = b := by
  cases l
  · simp only [get, scanl_nil]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a head✝ : α
tail✝ : List α
h : 0 < length (scanl f b (head✝ :: tail✝))
⊢ get (scanl f b (head✝ :: tail✝)) { val := 0, isLt := h } = b

Next tactic:
simp only [get, scanl_cons, singleton_append]
theorem get?_succ_scanl {i : ℕ} : (scanl f b l).get? (i + 1) =
    ((scanl f b l).get? i).bind fun x => (l.get? i).map fun y => f x y := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a : α
l : List α
i : ℕ
⊢ get? (scanl f b l) (i + 1) = Option.bind (get? (scanl f b l) i) fun x => Option.map (fun y => f x y) (get? l i)

Next tactic:
induction' l with hd tl hl generalizing b i
theorem get?_succ_scanl {i : ℕ} : (scanl f b l).get? (i + 1) =
    ((scanl f b l).get? i).bind fun x => (l.get? i).map fun y => f x y := by
  induction' l with hd tl hl generalizing b i
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
b : β
i : ℕ
⊢ get? (scanl f b []) (i + 1) = Option.bind (get? (scanl f b []) i) fun x => Option.map (fun y => f x y) (get? [] i)

Next tactic:
symm
theorem get?_succ_scanl {i : ℕ} : (scanl f b l).get? (i + 1) =
    ((scanl f b l).get? i).bind fun x => (l.get? i).map fun y => f x y := by
  induction' l with hd tl hl generalizing b i
  · symm
    

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
b : β
i : ℕ
⊢ (Option.bind (get? (scanl f b []) i) fun x => Option.map (fun y => f x y) (get? [] i)) = get? (scanl f b []) (i + 1)

Next tactic:
simp only [Option.bind_eq_none', get?, forall₂_true_iff, not_false_iff, Option.map_none',
      scanl_nil, Option.not_mem_none, forall_true_iff]
theorem get?_succ_scanl {i : ℕ} : (scanl f b l).get? (i + 1) =
    ((scanl f b l).get? i).bind fun x => (l.get? i).map fun y => f x y := by
  induction' l with hd tl hl generalizing b i
  · symm
    simp only [Option.bind_eq_none', get?, forall₂_true_iff, not_false_iff, Option.map_none',
      scanl_nil, Option.not_mem_none, forall_true_iff]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a hd : α
tl : List α
hl :
  ∀ {b : β} {i : ℕ},
    get? (scanl f b tl) (i + 1) = Option.bind (get? (scanl f b tl) i) fun x => Option.map (fun y => f x y) (get? tl i)
b : β
i : ℕ
⊢ get? (scanl f b (hd :: tl)) (i + 1) =
    Option.bind (get? (scanl f b (hd :: tl)) i) fun x => Option.map (fun y => f x y) (get? (hd :: tl) i)

Next tactic:
simp only [scanl_cons, singleton_append]
theorem get?_succ_scanl {i : ℕ} : (scanl f b l).get? (i + 1) =
    ((scanl f b l).get? i).bind fun x => (l.get? i).map fun y => f x y := by
  induction' l with hd tl hl generalizing b i
  · symm
    simp only [Option.bind_eq_none', get?, forall₂_true_iff, not_false_iff, Option.map_none',
      scanl_nil, Option.not_mem_none, forall_true_iff]
  · simp only [scanl_cons, singleton_append]
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a hd : α
tl : List α
hl :
  ∀ {b : β} {i : ℕ},
    get? (scanl f b tl) (i + 1) = Option.bind (get? (scanl f b tl) i) fun x => Option.map (fun y => f x y) (get? tl i)
b : β
i : ℕ
⊢ get? (b :: scanl f (f b hd) tl) (i + 1) =
    Option.bind (get? (b :: scanl f (f b hd) tl) i) fun x => Option.map (fun y => f x y) (get? (hd :: tl) i)

Next tactic:
cases i
theorem get?_succ_scanl {i : ℕ} : (scanl f b l).get? (i + 1) =
    ((scanl f b l).get? i).bind fun x => (l.get? i).map fun y => f x y := by
  induction' l with hd tl hl generalizing b i
  · symm
    simp only [Option.bind_eq_none', get?, forall₂_true_iff, not_false_iff, Option.map_none',
      scanl_nil, Option.not_mem_none, forall_true_iff]
  · simp only [scanl_cons, singleton_append]
    cases i
    · 

Proof state:
case cons.zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a hd : α
tl : List α
hl :
  ∀ {b : β} {i : ℕ},
    get? (scanl f b tl) (i + 1) = Option.bind (get? (scanl f b tl) i) fun x => Option.map (fun y => f x y) (get? tl i)
b : β
⊢ get? (b :: scanl f (f b hd) tl) (zero + 1) =
    Option.bind (get? (b :: scanl f (f b hd) tl) zero) fun x => Option.map (fun y => f x y) (get? (hd :: tl) zero)

Next tactic:
simp only [Option.map_some', get?_zero_scanl, get?, Option.some_bind']
theorem get?_succ_scanl {i : ℕ} : (scanl f b l).get? (i + 1) =
    ((scanl f b l).get? i).bind fun x => (l.get? i).map fun y => f x y := by
  induction' l with hd tl hl generalizing b i
  · symm
    simp only [Option.bind_eq_none', get?, forall₂_true_iff, not_false_iff, Option.map_none',
      scanl_nil, Option.not_mem_none, forall_true_iff]
  · simp only [scanl_cons, singleton_append]
    cases i
    · simp only [Option.map_some', get?_zero_scanl, get?, Option.some_bind']
    · 

Proof state:
case cons.succ
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a hd : α
tl : List α
hl :
  ∀ {b : β} {i : ℕ},
    get? (scanl f b tl) (i + 1) = Option.bind (get? (scanl f b tl) i) fun x => Option.map (fun y => f x y) (get? tl i)
b : β
n✝ : ℕ
⊢ get? (b :: scanl f (f b hd) tl) (succ n✝ + 1) =
    Option.bind (get? (b :: scanl f (f b hd) tl) (succ n✝)) fun x =>
      Option.map (fun y => f x y) (get? (hd :: tl) (succ n✝))

Next tactic:
simp only [hl, get?]
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
b : β
a : α
l : List α
i : ℕ
h : i + 1 < length (scanl f b l)
⊢ nthLe (scanl f b l) (i + 1) h =
    f (nthLe (scanl f b l) i (_ : i < length (scanl f b l))) (nthLe l i (_ : i < length l))

Next tactic:
induction i generalizing b l with
  | zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
  | succ i hi =>
    cases l
    · simp only [length, add_lt_iff_neg_right, scanl_nil] at h
      exact absurd h (not_lt_of_lt Nat.succ_pos')
    · simp_rw [scanl_cons]
      rw [nthLe_append_right]
      · simp only [length, zero_add 1, succ_add_sub_one, hi]; rfl
      · simp only [length, Nat.zero_le, le_add_iff_nonneg_left]
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  

Proof state:
case zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
b : β
l : List α
h : zero + 1 < length (scanl f b l)
⊢ nthLe (scanl f b l) (zero + 1) h =
    f (nthLe (scanl f b l) zero (_ : zero < length (scanl f b l))) (nthLe l zero (_ : zero < length l))

Next tactic:
| zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    

Proof state:
case zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
b : β
l : List α
h : zero + 1 < length (scanl f b l)
⊢ nthLe (scanl f b l) (zero + 1) h =
    f (nthLe (scanl f b l) zero (_ : zero < length (scanl f b l))) (nthLe l zero (_ : zero < length l))

Next tactic:
cases l
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    cases l
    · 

Proof state:
case zero.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
b : β
h : zero + 1 < length (scanl f b [])
⊢ nthLe (scanl f b []) (zero + 1) h =
    f (nthLe (scanl f b []) zero (_ : zero < length (scanl f b []))) (nthLe [] zero (_ : zero < length []))

Next tactic:
simp only [length, zero_eq, lt_self_iff_false] at h
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · 

Proof state:
case zero.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
b : β
head✝ : α
tail✝ : List α
h : zero + 1 < length (scanl f b (head✝ :: tail✝))
⊢ nthLe (scanl f b (head✝ :: tail✝)) (zero + 1) h =
    f (nthLe (scanl f b (head✝ :: tail✝)) zero (_ : zero < length (scanl f b (head✝ :: tail✝))))
      (nthLe (head✝ :: tail✝) zero (_ : zero < length (head✝ :: tail✝)))

Next tactic:
simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
  

Proof state:
case succ
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
i : ℕ
hi :
  ∀ {b : β} {l : List α} {h : i + 1 < length (scanl f b l)},
    nthLe (scanl f b l) (i + 1) h =
      f (nthLe (scanl f b l) i (_ : i < length (scanl f b l))) (nthLe l i (_ : i < length l))
b : β
l : List α
h : succ i + 1 < length (scanl f b l)
⊢ nthLe (scanl f b l) (succ i + 1) h =
    f (nthLe (scanl f b l) (succ i) (_ : succ i < length (scanl f b l))) (nthLe l (succ i) (_ : succ i < length l))

Next tactic:
| succ i hi =>
    cases l
    · simp only [length, add_lt_iff_neg_right, scanl_nil] at h
      exact absurd h (not_lt_of_lt Nat.succ_pos')
    · simp_rw [scanl_cons]
      rw [nthLe_append_right]
      · simp only [length, zero_add 1, succ_add_sub_one, hi]; rfl
      · simp only [length, Nat.zero_le, le_add_iff_nonneg_left]
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
  | succ i hi =>
    

Proof state:
case succ
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
i : ℕ
hi :
  ∀ {b : β} {l : List α} {h : i + 1 < length (scanl f b l)},
    nthLe (scanl f b l) (i + 1) h =
      f (nthLe (scanl f b l) i (_ : i < length (scanl f b l))) (nthLe l i (_ : i < length l))
b : β
l : List α
h : succ i + 1 < length (scanl f b l)
⊢ nthLe (scanl f b l) (succ i + 1) h =
    f (nthLe (scanl f b l) (succ i) (_ : succ i < length (scanl f b l))) (nthLe l (succ i) (_ : succ i < length l))

Next tactic:
cases l
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
  | succ i hi =>
    cases l
    · 

Proof state:
case succ.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
i : ℕ
hi :
  ∀ {b : β} {l : List α} {h : i + 1 < length (scanl f b l)},
    nthLe (scanl f b l) (i + 1) h =
      f (nthLe (scanl f b l) i (_ : i < length (scanl f b l))) (nthLe l i (_ : i < length l))
b : β
h : succ i + 1 < length (scanl f b [])
⊢ nthLe (scanl f b []) (succ i + 1) h =
    f (nthLe (scanl f b []) (succ i) (_ : succ i < length (scanl f b []))) (nthLe [] (succ i) (_ : succ i < length []))

Next tactic:
simp only [length, add_lt_iff_neg_right, scanl_nil] at h
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
  | succ i hi =>
    cases l
    · simp only [length, add_lt_iff_neg_right, scanl_nil] at h
      

Proof state:
case succ.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
i : ℕ
hi :
  ∀ {b : β} {l : List α} {h : i + 1 < length (scanl f b l)},
    nthLe (scanl f b l) (i + 1) h =
      f (nthLe (scanl f b l) i (_ : i < length (scanl f b l))) (nthLe l i (_ : i < length l))
b : β
h✝ : succ i + 1 < length (scanl f b [])
h : succ i < 0
⊢ nthLe (scanl f b []) (succ i + 1) h✝ =
    f (nthLe (scanl f b []) (succ i) (_ : succ i < length (scanl f b []))) (nthLe [] (succ i) (_ : succ i < length []))

Next tactic:
exact absurd h (not_lt_of_lt Nat.succ_pos')
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
  | succ i hi =>
    cases l
    · simp only [length, add_lt_iff_neg_right, scanl_nil] at h
      exact absurd h (not_lt_of_lt Nat.succ_pos')
    · 

Proof state:
case succ.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
i : ℕ
hi :
  ∀ {b : β} {l : List α} {h : i + 1 < length (scanl f b l)},
    nthLe (scanl f b l) (i + 1) h =
      f (nthLe (scanl f b l) i (_ : i < length (scanl f b l))) (nthLe l i (_ : i < length l))
b : β
head✝ : α
tail✝ : List α
h : succ i + 1 < length (scanl f b (head✝ :: tail✝))
⊢ nthLe (scanl f b (head✝ :: tail✝)) (succ i + 1) h =
    f (nthLe (scanl f b (head✝ :: tail✝)) (succ i) (_ : succ i < length (scanl f b (head✝ :: tail✝))))
      (nthLe (head✝ :: tail✝) (succ i) (_ : succ i < length (head✝ :: tail✝)))

Next tactic:
simp_rw [scanl_cons]
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
  | succ i hi =>
    cases l
    · simp only [length, add_lt_iff_neg_right, scanl_nil] at h
      exact absurd h (not_lt_of_lt Nat.succ_pos')
    · simp_rw [scanl_cons]
      

Proof state:
case succ.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
i : ℕ
hi :
  ∀ {b : β} {l : List α} {h : i + 1 < length (scanl f b l)},
    nthLe (scanl f b l) (i + 1) h =
      f (nthLe (scanl f b l) i (_ : i < length (scanl f b l))) (nthLe l i (_ : i < length l))
b : β
head✝ : α
tail✝ : List α
h : succ i + 1 < length (scanl f b (head✝ :: tail✝))
⊢ nthLe ([b] ++ scanl f (f b head✝) tail✝) (succ i + 1) (_ : succ i + 1 < length ([b] ++ scanl f (f b head✝) tail✝)) =
    f (nthLe ([b] ++ scanl f (f b head✝) tail✝) (succ i) (_ : succ i < length ([b] ++ scanl f (f b head✝) tail✝)))
      (nthLe (head✝ :: tail✝) (succ i) (_ : succ i < length (head✝ :: tail✝)))

Next tactic:
rw [nthLe_append_right]
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
  | succ i hi =>
    cases l
    · simp only [length, add_lt_iff_neg_right, scanl_nil] at h
      exact absurd h (not_lt_of_lt Nat.succ_pos')
    · simp_rw [scanl_cons]
      rw [nthLe_append_right]
      · 

Proof state:
case succ.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
i : ℕ
hi :
  ∀ {b : β} {l : List α} {h : i + 1 < length (scanl f b l)},
    nthLe (scanl f b l) (i + 1) h =
      f (nthLe (scanl f b l) i (_ : i < length (scanl f b l))) (nthLe l i (_ : i < length l))
b : β
head✝ : α
tail✝ : List α
h : succ i + 1 < length (scanl f b (head✝ :: tail✝))
⊢ nthLe (scanl f (f b head✝) tail✝) (succ i + 1 - length [b])
      (_ : succ i + 1 - length [b] < length (scanl f (f b head✝) tail✝)) =
    f (nthLe ([b] ++ scanl f (f b head✝) tail✝) (succ i) (_ : succ i < length ([b] ++ scanl f (f b head✝) tail✝)))
      (nthLe (head✝ :: tail✝) (succ i) (_ : succ i < length (head✝ :: tail✝)))

Next tactic:
simp only [length, zero_add 1, succ_add_sub_one, hi]
set_option linter.deprecated false in
theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} :
    (scanl f b l).nthLe (i + 1) h =
      f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h))
        (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by
  induction i generalizing b l with
  | zero =>
    cases l
    · simp only [length, zero_eq, lt_self_iff_false] at h
    · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons]
  | succ i hi =>
    cases l
    · simp only [length, add_lt_iff_neg_right, scanl_nil] at h
      exact absurd h (not_lt_of_lt Nat.succ_pos')
    · simp_rw [scanl_cons]
      rw [nthLe_append_right]
      · simp only [length, zero_add 1, succ_add_sub_one, hi]; 

Proof state:
case succ.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : β → α → β
a : α
i : ℕ
hi :
  ∀ {b : β} {l : List α} {h : i + 1 < length (scanl f b l)},
    nthLe (scanl f b l) (i + 1) h =
      f (nthLe (scanl f b l) i (_ : i < length (scanl f b l))) (nthLe l i (_ : i < length l))
b : β
head✝ : α
tail✝ : List α
h : succ i + 1 < length (scanl f b (head✝ :: tail✝))
⊢ f (nthLe (scanl f (f b head✝) tail✝) i (_ : i < length (scanl f (f b head✝) tail✝)))
      (nthLe tail✝ i (_ : i < length tail✝)) =
    f (nthLe ([b] ++ scanl f (f b head✝) tail✝) (succ i) (_ : succ i < length ([b] ++ scanl f (f b head✝) tail✝)))
      (nthLe (head✝ :: tail✝) (succ i) (_ : succ i < length (head✝ :: tail✝)))

Next tactic:
rfl