l3lab/ntp-mathlib huggingface dataset:
@[simp]
lemma N₂Γ₂ToKaroubiIso_hom_app (X : ChainComplex C ℕ) :
    (N₂Γ₂ToKaroubiIso.hom.app X).f = PInfty := by
  ext n
  dsimp [N₂Γ₂ToKaroubiIso]
  simp only [comp_id, assoc, PInfty_f_idem]
  conv_rhs =>
    rw [← PInfty_f_idem]
  congr 1
  apply (Γ₀.splitting X).hom_ext'
  intro A
  rw [Splitting.ι_desc_assoc, assoc]
  

Proof state:
case h.e_a.h
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : ChainComplex C ℕ
n : ℕ
A : Splitting.IndexSet (op [n])
⊢ 𝟙 (HomologicalComplex.X X (SimplexCategory.len A.fst.unop)) ≫
      Splitting.ιSummand (Γ₀.splitting X) A ≫ HomologicalComplex.Hom.f PInfty n =
    Splitting.ιSummand (Γ₀.splitting X) A ≫ HomologicalComplex.Hom.f PInfty n

Next tactic:
apply id_comp
@[simp]
lemma N₂Γ₂ToKaroubiIso_inv_app (X : ChainComplex C ℕ) :
    (N₂Γ₂ToKaroubiIso.inv.app X).f = PInfty := by
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : ChainComplex C ℕ
⊢ (N₂Γ₂ToKaroubiIso.inv.app X).f = PInfty

Next tactic:
ext n
@[simp]
lemma N₂Γ₂ToKaroubiIso_inv_app (X : ChainComplex C ℕ) :
    (N₂Γ₂ToKaroubiIso.inv.app X).f = PInfty := by
  ext n
  

Proof state:
case h
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : ChainComplex C ℕ
n : ℕ
⊢ HomologicalComplex.Hom.f (N₂Γ₂ToKaroubiIso.inv.app X).f n = HomologicalComplex.Hom.f PInfty n

Next tactic:
dsimp [N₂Γ₂ToKaroubiIso]
@[simp]
lemma N₂Γ₂ToKaroubiIso_inv_app (X : ChainComplex C ℕ) :
    (N₂Γ₂ToKaroubiIso.inv.app X).f = PInfty := by
  ext n
  dsimp [N₂Γ₂ToKaroubiIso]
  

Proof state:
case h
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : ChainComplex C ℕ
n : ℕ
⊢ (HomologicalComplex.Hom.f PInfty n ≫
      (HomologicalComplex.Hom.f PInfty n ≫ 𝟙 (Γ₀.Obj.obj₂ X (op [n]))) ≫
        (HomologicalComplex.Hom.f PInfty n ≫ 𝟙 (Γ₀.Obj.obj₂ X (op [n]))) ≫
          HomologicalComplex.Hom.f PInfty n ≫
            Splitting.desc (Γ₀.splitting X) (op [n]) fun A =>
              𝟙 (HomologicalComplex.X X (SimplexCategory.len A.fst.unop)) ≫ Splitting.ιSummand (Γ₀.splitting X) A) =
    HomologicalComplex.Hom.f PInfty n

Next tactic:
simp only [comp_id, PInfty_f_idem_assoc, AlternatingFaceMapComplex.obj_X, Γ₀_obj_obj]
@[simp]
lemma N₂Γ₂ToKaroubiIso_inv_app (X : ChainComplex C ℕ) :
    (N₂Γ₂ToKaroubiIso.inv.app X).f = PInfty := by
  ext n
  dsimp [N₂Γ₂ToKaroubiIso]
  simp only [comp_id, PInfty_f_idem_assoc, AlternatingFaceMapComplex.obj_X, Γ₀_obj_obj]
  

Proof state:
case h
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : ChainComplex C ℕ
n : ℕ
⊢ (HomologicalComplex.Hom.f PInfty n ≫
      Splitting.desc (Γ₀.splitting X) (op [n]) fun A =>
        𝟙 (HomologicalComplex.X X (SimplexCategory.len A.fst.unop)) ≫ Splitting.ιSummand (Γ₀.splitting X) A) =
    HomologicalComplex.Hom.f PInfty n

Next tactic:
convert comp_id _
@[simp]
lemma N₂Γ₂ToKaroubiIso_inv_app (X : ChainComplex C ℕ) :
    (N₂Γ₂ToKaroubiIso.inv.app X).f = PInfty := by
  ext n
  dsimp [N₂Γ₂ToKaroubiIso]
  simp only [comp_id, PInfty_f_idem_assoc, AlternatingFaceMapComplex.obj_X, Γ₀_obj_obj]
  convert comp_id _
  

Proof state:
case h.e'_2.h.e'_7
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : ChainComplex C ℕ
n : ℕ
⊢ (Splitting.desc (Γ₀.splitting X) (op [n]) fun A =>
      𝟙 (HomologicalComplex.X X (SimplexCategory.len A.fst.unop)) ≫ Splitting.ιSummand (Γ₀.splitting X) A) =
    𝟙 (Γ₀.Obj.obj₂ X (op [n]))

Next tactic:
apply (Γ₀.splitting X).hom_ext'
@[simp]
lemma N₂Γ₂ToKaroubiIso_inv_app (X : ChainComplex C ℕ) :
    (N₂Γ₂ToKaroubiIso.inv.app X).f = PInfty := by
  ext n
  dsimp [N₂Γ₂ToKaroubiIso]
  simp only [comp_id, PInfty_f_idem_assoc, AlternatingFaceMapComplex.obj_X, Γ₀_obj_obj]
  convert comp_id _
  apply (Γ₀.splitting X).hom_ext'
  

Proof state:
case h.e'_2.h.e'_7.h
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : ChainComplex C ℕ
n : ℕ
⊢ ∀ (A : Splitting.IndexSet (op [n])),
    (Splitting.ιSummand (Γ₀.splitting X) A ≫
        Splitting.desc (Γ₀.splitting X) (op [n]) fun A =>
          𝟙 (HomologicalComplex.X X (SimplexCategory.len A.fst.unop)) ≫ Splitting.ιSummand (Γ₀.splitting X) A) =
      Splitting.ιSummand (Γ₀.splitting X) A ≫ 𝟙 (Γ₀.Obj.obj₂ X (op [n]))

Next tactic:
intro A
@[simp]
lemma N₂Γ₂ToKaroubiIso_inv_app (X : ChainComplex C ℕ) :
    (N₂Γ₂ToKaroubiIso.inv.app X).f = PInfty := by
  ext n
  dsimp [N₂Γ₂ToKaroubiIso]
  simp only [comp_id, PInfty_f_idem_assoc, AlternatingFaceMapComplex.obj_X, Γ₀_obj_obj]
  convert comp_id _
  apply (Γ₀.splitting X).hom_ext'
  intro A
  

Proof state:
case h.e'_2.h.e'_7.h
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : ChainComplex C ℕ
n : ℕ
A : Splitting.IndexSet (op [n])
⊢ (Splitting.ιSummand (Γ₀.splitting X) A ≫
      Splitting.desc (Γ₀.splitting X) (op [n]) fun A =>
        𝟙 (HomologicalComplex.X X (SimplexCategory.len A.fst.unop)) ≫ Splitting.ιSummand (Γ₀.splitting X) A) =
    Splitting.ιSummand (Γ₀.splitting X) A ≫ 𝟙 (Γ₀.Obj.obj₂ X (op [n]))

Next tactic:
rw [Splitting.ι_desc]
@[simp]
lemma N₂Γ₂ToKaroubiIso_inv_app (X : ChainComplex C ℕ) :
    (N₂Γ₂ToKaroubiIso.inv.app X).f = PInfty := by
  ext n
  dsimp [N₂Γ₂ToKaroubiIso]
  simp only [comp_id, PInfty_f_idem_assoc, AlternatingFaceMapComplex.obj_X, Γ₀_obj_obj]
  convert comp_id _
  apply (Γ₀.splitting X).hom_ext'
  intro A
  rw [Splitting.ι_desc]
  

Proof state:
case h.e'_2.h.e'_7.h
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : ChainComplex C ℕ
n : ℕ
A : Splitting.IndexSet (op [n])
⊢ 𝟙 (HomologicalComplex.X X (SimplexCategory.len A.fst.unop)) ≫ Splitting.ιSummand (Γ₀.splitting X) A =
    Splitting.ιSummand (Γ₀.splitting X) A ≫ 𝟙 (Γ₀.Obj.obj₂ X (op [n]))

Next tactic:
erw [comp_id, id_comp]
@[simp]
theorem N₂Γ₂_inv_app_f_f (X : Karoubi (ChainComplex C ℕ)) (n : ℕ) :
    (N₂Γ₂.inv.app X).f.f n =
      X.p.f n ≫ (Γ₀.splitting X.X).ιSummand (Splitting.IndexSet.id (op [n])) := by
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : Karoubi (ChainComplex C ℕ)
n : ℕ
⊢ HomologicalComplex.Hom.f (N₂Γ₂.inv.app X).f n =
    HomologicalComplex.Hom.f X.p n ≫ Splitting.ιSummand (Γ₀.splitting X.X) (Splitting.IndexSet.id (op [n]))

Next tactic:
dsimp [N₂Γ₂]
@[simp]
theorem N₂Γ₂_inv_app_f_f (X : Karoubi (ChainComplex C ℕ)) (n : ℕ) :
    (N₂Γ₂.inv.app X).f.f n =
      X.p.f n ≫ (Γ₀.splitting X.X).ιSummand (Splitting.IndexSet.id (op [n])) := by
  dsimp [N₂Γ₂]
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : Karoubi (ChainComplex C ℕ)
n : ℕ
⊢ HomologicalComplex.Hom.f
      ((((whiskeringLeft (ChainComplex C ℕ) (Karoubi (ChainComplex C ℕ)) (Karoubi (ChainComplex C ℕ))).obj
                  (toKaroubi (ChainComplex C ℕ))).preimage
              (N₁Γ₀.inv ≫ N₂Γ₂ToKaroubiIso.inv)).app
          X).f
      n =
    HomologicalComplex.Hom.f X.p n ≫ Splitting.ιSummand (Γ₀.splitting X.X) (Splitting.IndexSet.id (op [n]))

Next tactic:
simp only [whiskeringLeft_obj_preimage_app, NatTrans.comp_app, Functor.comp_map,
    Karoubi.comp_f, N₂Γ₂ToKaroubiIso_inv_app, HomologicalComplex.comp_f,
    N₁Γ₀_inv_app_f_f, toKaroubi_obj_X, Splitting.toKaroubiNondegComplexIsoN₁_hom_f_f,
    Γ₀.obj_obj, PInfty_on_Γ₀_splitting_summand_eq_self, N₂_map_f_f,
    Γ₂_map_f_app, unop_op, Karoubi.decompId_p_f, PInfty_f_idem_assoc,
    PInfty_on_Γ₀_splitting_summand_eq_self_assoc, Splitting.IndexSet.id_fst, SimplexCategory.len_mk,
    Splitting.ι_desc]
@[simp]
theorem N₂Γ₂_inv_app_f_f (X : Karoubi (ChainComplex C ℕ)) (n : ℕ) :
    (N₂Γ₂.inv.app X).f.f n =
      X.p.f n ≫ (Γ₀.splitting X.X).ιSummand (Splitting.IndexSet.id (op [n])) := by
  dsimp [N₂Γ₂]
  simp only [whiskeringLeft_obj_preimage_app, NatTrans.comp_app, Functor.comp_map,
    Karoubi.comp_f, N₂Γ₂ToKaroubiIso_inv_app, HomologicalComplex.comp_f,
    N₁Γ₀_inv_app_f_f, toKaroubi_obj_X, Splitting.toKaroubiNondegComplexIsoN₁_hom_f_f,
    Γ₀.obj_obj, PInfty_on_Γ₀_splitting_summand_eq_self, N₂_map_f_f,
    Γ₂_map_f_app, unop_op, Karoubi.decompId_p_f, PInfty_f_idem_assoc,
    PInfty_on_Γ₀_splitting_summand_eq_self_assoc, Splitting.IndexSet.id_fst, SimplexCategory.len_mk,
    Splitting.ι_desc]
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
X : Karoubi (ChainComplex C ℕ)
n : ℕ
⊢ HomologicalComplex.Hom.f ((𝟭 (Karoubi (ChainComplex C ℕ))).map (Karoubi.decompId_i X)).f n ≫
      HomologicalComplex.Hom.f X.p n ≫ Splitting.ιSummand (Γ₀.splitting X.X) (Splitting.IndexSet.id (op [n])) =
    HomologicalComplex.Hom.f X.p n ≫ Splitting.ιSummand (Γ₀.splitting X.X) (Splitting.IndexSet.id (op [n]))

Next tactic:
apply Karoubi.HomologicalComplex.p_idem_assoc
lemma whiskerLeft_toKaroubi_N₂Γ₂_hom :
    whiskerLeft (toKaroubi (ChainComplex C ℕ)) N₂Γ₂.hom = N₂Γ₂ToKaroubiIso.hom ≫ N₁Γ₀.hom := by
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
⊢ whiskerLeft (toKaroubi (ChainComplex C ℕ)) N₂Γ₂.hom = N₂Γ₂ToKaroubiIso.hom ≫ N₁Γ₀.hom

Next tactic:
let e : _ ≅ toKaroubi (ChainComplex C ℕ) ⋙ 𝟭 _ := N₂Γ₂ToKaroubiIso ≪≫ N₁Γ₀
lemma whiskerLeft_toKaroubi_N₂Γ₂_hom :
    whiskerLeft (toKaroubi (ChainComplex C ℕ)) N₂Γ₂.hom = N₂Γ₂ToKaroubiIso.hom ≫ N₁Γ₀.hom := by
  let e : _ ≅ toKaroubi (ChainComplex C ℕ) ⋙ 𝟭 _ := N₂Γ₂ToKaroubiIso ≪≫ N₁Γ₀
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
e : toKaroubi (ChainComplex C ℕ) ⋙ Γ₂ ⋙ N₂ ≅ toKaroubi (ChainComplex C ℕ) ⋙ 𝟭 (Karoubi (ChainComplex C ℕ)) :=
  N₂Γ₂ToKaroubiIso ≪≫ N₁Γ₀
⊢ whiskerLeft (toKaroubi (ChainComplex C ℕ)) N₂Γ₂.hom = N₂Γ₂ToKaroubiIso.hom ≫ N₁Γ₀.hom

Next tactic:
have h := ((whiskeringLeft _ _ (Karoubi (ChainComplex C ℕ))).obj
    (toKaroubi (ChainComplex C ℕ))).image_preimage e.hom
lemma whiskerLeft_toKaroubi_N₂Γ₂_hom :
    whiskerLeft (toKaroubi (ChainComplex C ℕ)) N₂Γ₂.hom = N₂Γ₂ToKaroubiIso.hom ≫ N₁Γ₀.hom := by
  let e : _ ≅ toKaroubi (ChainComplex C ℕ) ⋙ 𝟭 _ := N₂Γ₂ToKaroubiIso ≪≫ N₁Γ₀
  have h := ((whiskeringLeft _ _ (Karoubi (ChainComplex C ℕ))).obj
    (toKaroubi (ChainComplex C ℕ))).image_preimage e.hom
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
e : toKaroubi (ChainComplex C ℕ) ⋙ Γ₂ ⋙ N₂ ≅ toKaroubi (ChainComplex C ℕ) ⋙ 𝟭 (Karoubi (ChainComplex C ℕ)) :=
  N₂Γ₂ToKaroubiIso ≪≫ N₁Γ₀
h :
  ((whiskeringLeft (ChainComplex C ℕ) (Karoubi (ChainComplex C ℕ)) (Karoubi (ChainComplex C ℕ))).obj
          (toKaroubi (ChainComplex C ℕ))).map
      (((whiskeringLeft (ChainComplex C ℕ) (Karoubi (ChainComplex C ℕ)) (Karoubi (ChainComplex C ℕ))).obj
            (toKaroubi (ChainComplex C ℕ))).preimage
        e.hom) =
    e.hom
⊢ whiskerLeft (toKaroubi (ChainComplex C ℕ)) N₂Γ₂.hom = N₂Γ₂ToKaroubiIso.hom ≫ N₁Γ₀.hom

Next tactic:
dsimp only [whiskeringLeft, N₂Γ₂, Functor.preimageIso] at h ⊢
lemma whiskerLeft_toKaroubi_N₂Γ₂_hom :
    whiskerLeft (toKaroubi (ChainComplex C ℕ)) N₂Γ₂.hom = N₂Γ₂ToKaroubiIso.hom ≫ N₁Γ₀.hom := by
  let e : _ ≅ toKaroubi (ChainComplex C ℕ) ⋙ 𝟭 _ := N₂Γ₂ToKaroubiIso ≪≫ N₁Γ₀
  have h := ((whiskeringLeft _ _ (Karoubi (ChainComplex C ℕ))).obj
    (toKaroubi (ChainComplex C ℕ))).image_preimage e.hom
  dsimp only [whiskeringLeft, N₂Γ₂, Functor.preimageIso] at h ⊢
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : Preadditive C
inst✝ : HasFiniteCoproducts C
e : toKaroubi (ChainComplex C ℕ) ⋙ Γ₂ ⋙ N₂ ≅ toKaroubi (ChainComplex C ℕ) ⋙ 𝟭 (Karoubi (ChainComplex C ℕ)) :=
  N₂Γ₂ToKaroubiIso ≪≫ N₁Γ₀
h :
  whiskerLeft (toKaroubi (ChainComplex C ℕ))
      ((CategoryTheory.Functor.mk
            { obj := fun G => toKaroubi (ChainComplex C ℕ) ⋙ G,
              map := fun {X Y} α => whiskerLeft (toKaroubi (ChainComplex C ℕ)) α }).preimage
        (N₂Γ₂ToKaroubiIso ≪≫ N₁Γ₀).hom) =
    (N₂Γ₂ToKaroubiIso ≪≫ N₁Γ₀).hom
⊢ whiskerLeft (toKaroubi (ChainComplex C ℕ))
      ((CategoryTheory.Functor.mk
            { obj := fun G => toKaroubi (ChainComplex C ℕ) ⋙ G,
              map := fun {X Y} α => whiskerLeft (toKaroubi (ChainComplex C ℕ)) α }).preimage
        (N₂Γ₂ToKaroubiIso ≪≫ N₁Γ₀).hom) =
    N₂Γ₂ToKaroubiIso.hom ≫ N₁Γ₀.hom

Next tactic:
exact h
protected theorem eta (s : Stream' α) : (head s::tail s) = s :=
  funext fun i => by 

Proof state:
α : Type u
β : Type v
δ : Type w
s : Stream' α
i : ℕ
⊢ (head s :: tail s) i = s i

Next tactic:
cases i
protected theorem eta (s : Stream' α) : (head s::tail s) = s :=
  funext fun i => by cases i <;> 

Proof state:
case zero
α : Type u
β : Type v
δ : Type w
s : Stream' α
⊢ (head s :: tail s) zero = s zero

Next tactic:
rfl
protected theorem eta (s : Stream' α) : (head s::tail s) = s :=
  funext fun i => by cases i <;> 

Proof state:
case succ
α : Type u
β : Type v
δ : Type w
s : Stream' α
n✝ : ℕ
⊢ (head s :: tail s) (succ n✝) = s (succ n✝)

Next tactic:
rfl
@[simp]
theorem drop_drop (n m : Nat) (s : Stream' α) : drop n (drop m s) = drop (n + m) s := by
  

Proof state:
α : Type u
β : Type v
δ : Type w
n m : ℕ
s : Stream' α
⊢ drop n (drop m s) = drop (n + m) s

Next tactic:
ext
@[simp]
theorem drop_drop (n m : Nat) (s : Stream' α) : drop n (drop m s) = drop (n + m) s := by
  ext; 

Proof state:
case a
α : Type u
β : Type v
δ : Type w
n m : ℕ
s : Stream' α
n✝ : ℕ
⊢ get (drop n (drop m s)) n✝ = get (drop (n + m) s) n✝

Next tactic:
simp [Nat.add_assoc]
@[simp] theorem tail_drop' {s : Stream' α} : tail (drop i s) = s.drop (i+1) := by
  

Proof state:
α : Type u
β : Type v
δ : Type w
i : ℕ
s : Stream' α
⊢ tail (drop i s) = drop (i + 1) s

Next tactic:
ext
@[simp] theorem tail_drop' {s : Stream' α} : tail (drop i s) = s.drop (i+1) := by
  ext; 

Proof state:
case a
α : Type u
β : Type v
δ : Type w
i : ℕ
s : Stream' α
n✝ : ℕ
⊢ get (tail (drop i s)) n✝ = get (drop (i + 1) s) n✝

Next tactic:
simp [add_comm, add_assoc, add_left_comm]
theorem tail_drop (n : Nat) (s : Stream' α) : tail (drop n s) = drop n (tail s) := by 

Proof state:
α : Type u
β : Type v
δ : Type w
n : ℕ
s : Stream' α
⊢ tail (drop n s) = drop n (tail s)

Next tactic:
simp
theorem head_drop (a : Stream' α) (n : ℕ) : (a.drop n).head = a.get n := by 

Proof state:
α : Type u
β : Type v
δ : Type w
a : Stream' α
n : ℕ
⊢ head (drop n a) = get a n

Next tactic:
simp
theorem cons_injective2 : Function.Injective2 (cons : α → Stream' α → Stream' α) := fun x y s t h =>
  ⟨by 

Proof state:
α : Type u
β : Type v
δ : Type w
x y : α
s t : Stream' α
h : x :: s = y :: t
⊢ x = y

Next tactic:
rw [← get_zero_cons x s, h, get_zero_cons]
theorem cons_injective2 : Function.Injective2 (cons : α → Stream' α → Stream' α) := fun x y s t h =>
  ⟨by rw [← get_zero_cons x s, h, get_zero_cons],
    Stream'.ext fun n => by 

Proof state:
α : Type u
β : Type v
δ : Type w
x y : α
s t : Stream' α
h : x :: s = y :: t
n : ℕ
⊢ get s n = get t n

Next tactic:
rw [← get_succ_cons n _ x, h, get_succ_cons]
theorem mem_cons_of_mem {a : α} {s : Stream' α} (b : α) : a ∈ s → a ∈ b::s := fun ⟨n, h⟩ =>
  Exists.intro (succ n) (by 

Proof state:
α : Type u
β : Type v
δ : Type w
a : α
s : Stream' α
b : α
x✝ : a ∈ s
n : ℕ
h : (fun b => a = b) (get s n)
⊢ (fun b => a = b) (get (b :: s) (succ n))

Next tactic:
rw [get_succ, tail_cons, h]
theorem eq_or_mem_of_mem_cons {a b : α} {s : Stream' α} : (a ∈ b::s) → a = b ∨ a ∈ s :=
    fun ⟨n, h⟩ => by
  

Proof state:
α : Type u
β : Type v
δ : Type w
a b : α
s : Stream' α
x✝ : a ∈ b :: s
n : ℕ
h : (fun b => a = b) (get (b :: s) n)
⊢ a = b ∨ a ∈ s

Next tactic:
cases' n with n'
theorem eq_or_mem_of_mem_cons {a b : α} {s : Stream' α} : (a ∈ b::s) → a = b ∨ a ∈ s :=
    fun ⟨n, h⟩ => by
  cases' n with n'
  · 

Proof state:
case zero
α : Type u
β : Type v
δ : Type w
a b : α
s : Stream' α
x✝ : a ∈ b :: s
h : a = get (b :: s) zero
⊢ a = b ∨ a ∈ s

Next tactic:
left
theorem eq_or_mem_of_mem_cons {a b : α} {s : Stream' α} : (a ∈ b::s) → a = b ∨ a ∈ s :=
    fun ⟨n, h⟩ => by
  cases' n with n'
  · left
    

Proof state:
case zero.h
α : Type u
β : Type v
δ : Type w
a b : α
s : Stream' α
x✝ : a ∈ b :: s
h : a = get (b :: s) zero
⊢ a = b

Next tactic:
exact h
theorem eq_or_mem_of_mem_cons {a b : α} {s : Stream' α} : (a ∈ b::s) → a = b ∨ a ∈ s :=
    fun ⟨n, h⟩ => by
  cases' n with n'
  · left
    exact h
  · 

Proof state:
case succ
α : Type u
β : Type v
δ : Type w
a b : α
s : Stream' α
x✝ : a ∈ b :: s
n' : ℕ
h : a = get (b :: s) (succ n')
⊢ a = b ∨ a ∈ s

Next tactic:
right
theorem eq_or_mem_of_mem_cons {a b : α} {s : Stream' α} : (a ∈ b::s) → a = b ∨ a ∈ s :=
    fun ⟨n, h⟩ => by
  cases' n with n'
  · left
    exact h
  · right
    

Proof state:
case succ.h
α : Type u
β : Type v
δ : Type w
a b : α
s : Stream' α
x✝ : a ∈ b :: s
n' : ℕ
h : a = get (b :: s) (succ n')
⊢ a ∈ s

Next tactic:
rw [get_succ, tail_cons] at h
theorem eq_or_mem_of_mem_cons {a b : α} {s : Stream' α} : (a ∈ b::s) → a = b ∨ a ∈ s :=
    fun ⟨n, h⟩ => by
  cases' n with n'
  · left
    exact h
  · right
    rw [get_succ, tail_cons] at h
    

Proof state:
case succ.h
α : Type u
β : Type v
δ : Type w
a b : α
s : Stream' α
x✝ : a ∈ b :: s
n' : ℕ
h : a = get s n'
⊢ a ∈ s

Next tactic:
exact ⟨n', h⟩
theorem map_eq (s : Stream' α) : map f s = f (head s)::map f (tail s) := by
  

Proof state:
α : Type u
β : Type v
δ : Type w
f : α → β
s : Stream' α
⊢ map f s = f (head s) :: map f (tail s)

Next tactic:
rw [← Stream'.eta (map f s), tail_map, head_map]
theorem map_cons (a : α) (s : Stream' α) : map f (a::s) = f a::map f s := by
  

Proof state:
α : Type u
β : Type v
δ : Type w
f : α → β
a : α
s : Stream' α
⊢ map f (a :: s) = f a :: map f s

Next tactic:
rw [← Stream'.eta (map f (a::s)), map_eq]
theorem map_cons (a : α) (s : Stream' α) : map f (a::s) = f a::map f s := by
  rw [← Stream'.eta (map f (a::s)), map_eq]; 

Proof state:
α : Type u
β : Type v
δ : Type w
f : α → β
a : α
s : Stream' α
⊢ head (f (head (a :: s)) :: map f (tail (a :: s))) :: tail (f (head (a :: s)) :: map f (tail (a :: s))) =
    f a :: map f s

Next tactic:
rfl
theorem mem_map {a : α} {s : Stream' α} : a ∈ s → f a ∈ map f s := fun ⟨n, h⟩ =>
  Exists.intro n (by 

Proof state:
α : Type u
β : Type v
δ : Type w
f : α → β
a : α
s : Stream' α
x✝ : a ∈ s
n : ℕ
h : (fun b => a = b) (get s n)
⊢ (fun b => f a = b) (get (map f s) n)

Next tactic:
rw [get_map, h]
theorem zip_eq (s₁ : Stream' α) (s₂ : Stream' β) :
    zip f s₁ s₂ = f (head s₁) (head s₂)::zip f (tail s₁) (tail s₂) := by
  

Proof state:
α : Type u
β : Type v
δ : Type w
f : α → β → δ
s₁ : Stream' α
s₂ : Stream' β
⊢ zip f s₁ s₂ = f (head s₁) (head s₂) :: zip f (tail s₁) (tail s₂)

Next tactic:
rw [← Stream'.eta (zip f s₁ s₂)]
theorem zip_eq (s₁ : Stream' α) (s₂ : Stream' β) :
    zip f s₁ s₂ = f (head s₁) (head s₂)::zip f (tail s₁) (tail s₂) := by
  rw [← Stream'.eta (zip f s₁ s₂)]; 

Proof state:
α : Type u
β : Type v
δ : Type w
f : α → β → δ
s₁ : Stream' α
s₂ : Stream' β
⊢ head (zip f s₁ s₂) :: tail (zip f s₁ s₂) = f (head s₁) (head s₂) :: zip f (tail s₁) (tail s₂)

Next tactic:
rfl
theorem const_eq (a : α) : const a = a::const a := by
  

Proof state:
α : Type u
β : Type v
δ : Type w
a : α
⊢ const a = a :: const a

Next tactic:
apply Stream'.ext
theorem const_eq (a : α) : const a = a::const a := by
  apply Stream'.ext; 

Proof state:
case a
α : Type u
β : Type v
δ : Type w
a : α
⊢ ∀ (n : ℕ), get (const a) n = get (a :: const a) n

Next tactic:
intro n
theorem const_eq (a : α) : const a = a::const a := by
  apply Stream'.ext; intro n
  

Proof state:
case a
α : Type u
β : Type v
δ : Type w
a : α
n : ℕ
⊢ get (const a) n = get (a :: const a) n

Next tactic:
cases n
theorem const_eq (a : α) : const a = a::const a := by
  apply Stream'.ext; intro n
  cases n <;> 

Proof state:
case a.zero
α : Type u
β : Type v
δ : Type w
a : α
⊢ get (const a) zero = get (a :: const a) zero

Next tactic:
rfl
theorem const_eq (a : α) : const a = a::const a := by
  apply Stream'.ext; intro n
  cases n <;> 

Proof state:
case a.succ
α : Type u
β : Type v
δ : Type w
a : α
n✝ : ℕ
⊢ get (const a) (succ n✝) = get (a :: const a) (succ n✝)

Next tactic:
rfl
@[simp]
theorem tail_const (a : α) : tail (const a) = const a :=
  suffices tail (a::const a) = const a by 

Proof state:
α : Type u
β : Type v
δ : Type w
a : α
this : tail (a :: const a) = const a
⊢ tail (const a) = const a

Next tactic:
rwa [← const_eq] at this
theorem tail_iterate (f : α → α) (a : α) : tail (iterate f a) = iterate f (f a) := by
  

Proof state:
α : Type u
β : Type v
δ : Type w
f : α → α
a : α
⊢ tail (iterate f a) = iterate f (f a)

Next tactic:
ext n
theorem tail_iterate (f : α → α) (a : α) : tail (iterate f a) = iterate f (f a) := by
  ext n
  

Proof state:
case a
α : Type u
β : Type v
δ : Type w
f : α → α
a : α
n : ℕ
⊢ get (tail (iterate f a)) n = get (iterate f (f a)) n

Next tactic:
rw [get_tail]
theorem tail_iterate (f : α → α) (a : α) : tail (iterate f a) = iterate f (f a) := by
  ext n
  rw [get_tail]
  

Proof state:
case a
α : Type u
β : Type v
δ : Type w
f : α → α
a : α
n : ℕ
⊢ get (iterate f a) (n + 1) = get (iterate f (f a)) n

Next tactic:
induction' n with n' ih
theorem tail_iterate (f : α → α) (a : α) : tail (iterate f a) = iterate f (f a) := by
  ext n
  rw [get_tail]
  induction' n with n' ih
  · 

Proof state:
case a.zero
α : Type u
β : Type v
δ : Type w
f : α → α
a : α
⊢ get (iterate f a) (zero + 1) = get (iterate f (f a)) zero

Next tactic:
rfl
theorem tail_iterate (f : α → α) (a : α) : tail (iterate f a) = iterate f (f a) := by
  ext n
  rw [get_tail]
  induction' n with n' ih
  · rfl
  · 

Proof state:
case a.succ
α : Type u
β : Type v
δ : Type w
f : α → α
a : α
n' : ℕ
ih : get (iterate f a) (n' + 1) = get (iterate f (f a)) n'
⊢ get (iterate f a) (succ n' + 1) = get (iterate f (f a)) (succ n')

Next tactic:
rw [get_succ_iterate', ih, get_succ_iterate']
theorem iterate_eq (f : α → α) (a : α) : iterate f a = a::iterate f (f a) := by
  

Proof state:
α : Type u
β : Type v
δ : Type w
f : α → α
a : α
⊢ iterate f a = a :: iterate f (f a)

Next tactic:
rw [← Stream'.eta (iterate f a)]
theorem iterate_eq (f : α → α) (a : α) : iterate f a = a::iterate f (f a) := by
  rw [← Stream'.eta (iterate f a)]
  

Proof state:
α : Type u
β : Type v
δ : Type w
f : α → α
a : α
⊢ head (iterate f a) :: tail (iterate f a) = a :: iterate f (f a)

Next tactic:
rw [tail_iterate]
theorem iterate_eq (f : α → α) (a : α) : iterate f a = a::iterate f (f a) := by
  rw [← Stream'.eta (iterate f a)]
  rw [tail_iterate]; 

Proof state:
α : Type u
β : Type v
δ : Type w
f : α → α
a : α
⊢ head (iterate f a) :: iterate f (f a) = a :: iterate f (f a)

Next tactic:
rfl
theorem get_succ_iterate (n : Nat) (f : α → α) (a : α) :
    get (iterate f a) (succ n) = get (iterate f (f a)) n := by 

Proof state:
α : Type u
β : Type v
δ : Type w
n : ℕ
f : α → α
a : α
⊢ get (iterate f a) (succ n) = get (iterate f (f a)) n

Next tactic:
rw [get_succ, tail_iterate]
theorem bisim_simple (s₁ s₂ : Stream' α) :
    head s₁ = head s₂ → s₁ = tail s₁ → s₂ = tail s₂ → s₁ = s₂ := fun hh ht₁ ht₂ =>
  eq_of_bisim (fun s₁ s₂ => head s₁ = head s₂ ∧ s₁ = tail s₁ ∧ s₂ = tail s₂)
    (fun s₁ s₂ ⟨h₁, h₂, h₃⟩ => by
      

Proof state:
α : Type u
β : Type v
δ : Type w
s₁✝ s₂✝ : Stream' α
hh : head s₁✝ = head s₂✝
ht₁ : s₁✝ = tail s₁✝
ht₂ : s₂✝ = tail s₂✝
s₁ s₂ : Stream' α
x✝ : (fun s₁ s₂ => head s₁ = head s₂ ∧ s₁ = tail s₁ ∧ s₂ = tail s₂) s₁ s₂
h₁ : head s₁ = head s₂
h₂ : s₁ = tail s₁
h₃ : s₂ = tail s₂
⊢ head s₁ = head s₂ ∧ (fun s₁ s₂ => head s₁ = head s₂ ∧ s₁ = tail s₁ ∧ s₂ = tail s₂) (tail s₁) (tail s₂)

Next tactic:
constructor