Theorem: list_foldl'
File: Mathlib/Computability/Primrec.lean

tactic: letI := prim H
state_before: α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
⊢ Primrec fun a => List.foldl (fun s b => h a (s, b)) (g a) (f a)

tactic: let G (a : α) (IH : σ × List β) : σ × List β := List.casesOn IH.2 IH fun b l => (h a (IH.1, b), l)
state_before: α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
⊢ Primrec fun a => List.foldl (fun s b => h a (s, b)) (g a) (f a)

tactic: have hG : Primrec₂ G := list_casesOn' H (snd.comp snd) snd <|
  to₂ <|
  pair (hh.comp (fst.comp fst) <| pair ((fst.comp snd).comp fst) (fst.comp snd))
    (snd.comp snd)
state_before: α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
⊢ Primrec fun a => List.foldl (fun s b => h a (s, b)) (g a) (f a)

tactic: let F := fun (a : α) (n : ℕ) => (G a^[n]) (g a, f a)
state_before: α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
⊢ Primrec fun a => List.foldl (fun s b => h a (s, b)) (g a) (f a)

tactic: have hF : Primrec fun a => (F a (encode (f a))).1 :=
  (fst.comp <|
    nat_iterate (encode_iff.2 hf) (pair hg hf) <|
    hG)
state_before: α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
⊢ Primrec fun a => List.foldl (fun s b => h a (s, b)) (g a) (f a)

tactic: suffices : ∀ a n, F a n = (((f a).take n).foldl (fun s b => h a (s, b)) (g a), (f a).drop n)
state_before: α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
⊢ Primrec fun a => List.foldl (fun s b => h a (s, b)) (g a) (f a)

tactic: introv
state_before: case this
α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
⊢ ∀ (a : α) (n : ℕ), F a n = (List.foldl (fun s b => h a (s, b)) (g a) (List.take n (f a)), List.drop n (f a))

tactic: dsimp only
state_before: case this
α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
a : α
n : ℕ
⊢ F a n = (List.foldl (fun s b => h a (s, b)) (g a) (List.take n (f a)), List.drop n (f a))

tactic: generalize f a = l
state_before: case this
α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
a : α
n : ℕ
⊢ ((fun IH => List.rec IH (fun head tail tail_ih => (h a (IH.fst, head), tail)) IH.snd)^[n]) (g a, f a) =
    (List.foldl (fun s b => h a (s, b)) (g a) (List.take n (f a)), List.drop n (f a))

tactic: generalize g a = x
state_before: case this
α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
a : α
n : ℕ
l : List β
⊢ ((fun IH => List.rec IH (fun head tail tail_ih => (h a (IH.fst, head), tail)) IH.snd)^[n]) (g a, l) =
    (List.foldl (fun s b => h a (s, b)) (g a) (List.take n l), List.drop n l)

tactic: induction' n with n IH generalizing l x
state_before: case this
α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
a : α
n : ℕ
l : List β
x : σ
⊢ ((fun IH => List.rec IH (fun head tail tail_ih => (h a (IH.fst, head), tail)) IH.snd)^[n]) (x, l) =
    (List.foldl (fun s b => h a (s, b)) x (List.take n l), List.drop n l)

tactic: simp
state_before: case this.succ
α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
a : α
l✝ : List β
x✝ : σ
n : ℕ
IH :
  ∀ (l : List β) (x : σ),
    ((fun IH => List.rec IH (fun head tail tail_ih => (h a (IH.fst, head), tail)) IH.snd)^[n]) (x, l) =
      (List.foldl (fun s b => h a (s, b)) x (List.take n l), List.drop n l)
l : List β
x : σ
⊢ ((fun IH => List.rec IH (fun head tail tail_ih => (h a (IH.fst, head), tail)) IH.snd)^[Nat.succ n]) (x, l) =
    (List.foldl (fun s b => h a (s, b)) x (List.take (Nat.succ n) l), List.drop (Nat.succ n) l)

tactic: cases' l with b l <;> simp [IH]
state_before: case this.succ
α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
a : α
l✝ : List β
x✝ : σ
n : ℕ
IH :
  ∀ (l : List β) (x : σ),
    ((fun IH => List.rec IH (fun head tail tail_ih => (h a (IH.fst, head), tail)) IH.snd)^[n]) (x, l) =
      (List.foldl (fun s b => h a (s, b)) x (List.take n l), List.drop n l)
l : List β
x : σ
⊢ ((fun IH => List.rec IH (fun head tail tail_ih => (h a (IH.fst, head), tail)) IH.snd)^[n])
      (List.rec (x, l) (fun head tail tail_ih => (h a (x, head), tail)) l) =
    (List.foldl (fun s b => h a (s, b)) x (List.take (Nat.succ n) l), List.drop (Nat.succ n) l)

tactic: refine hF.of_eq fun a => ?_
state_before: α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this✝ : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
this : ∀ (a : α) (n : ℕ), F a n = (List.foldl (fun s b => h a (s, b)) (g a) (List.take n (f a)), List.drop n (f a))
⊢ Primrec fun a => List.foldl (fun s b => h a (s, b)) (g a) (f a)

tactic: rw [this, List.take_all_of_le (length_le_encode _)]
state_before: α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this✝ : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
this : ∀ (a : α) (n : ℕ), F a n = (List.foldl (fun s b => h a (s, b)) (g a) (List.take n (f a)), List.drop n (f a))
a : α
⊢ (F a (encode (f a))).fst = List.foldl (fun s b => h a (s, b)) (g a) (f a)

tactic: rfl
state_before: case this.zero
α : Type u_3
β : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable β
inst✝ : Primcodable σ
H : Nat.Primrec fun n => encode (decode n)
f : α → List β
g : α → σ
h : α → σ × β → σ
hf : Primrec f
hg : Primrec g
hh : Primrec₂ h
this : Primcodable (List β) := prim H
G : α → σ × List β → σ × List β := fun a IH => List.casesOn IH.snd IH fun b l => (h a (IH.fst, b), l)
hG : Primrec₂ G
F : α → ℕ → σ × List β := fun a n => (G a^[n]) (g a, f a)
hF : Primrec fun a => (F a (encode (f a))).fst
a : α
l✝ : List β
x✝ : σ
l : List β
x : σ
⊢ ((fun IH => List.rec IH (fun head tail tail_ih => (h a (IH.fst, head), tail)) IH.snd)^[Nat.zero]) (x, l) =
    (List.foldl (fun s b => h a (s, b)) x (List.take Nat.zero l), List.drop Nat.zero l)