l3lab/ntp-mathlib huggingface dataset:
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cone (Discrete.functor f)
m : s.pt ⟶ (Bicone.toCone b).pt
h : ∀ (j : Discrete J), m ≫ (Bicone.toCone b).π.app j = s.π.app j
⊢ ∑ j : J, m ≫ Bicone.π b j ≫ Bicone.ι b j = (fun s => ∑ j : J, s.π.app { as := j } ≫ Bicone.ι b j) s

Next tactic:
apply Finset.sum_congr rfl
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cone (Discrete.functor f)
m : s.pt ⟶ (Bicone.toCone b).pt
h : ∀ (j : Discrete J), m ≫ (Bicone.toCone b).π.app j = s.π.app j
⊢ ∀ x ∈ Finset.univ, m ≫ Bicone.π b x ≫ Bicone.ι b x = s.π.app { as := x } ≫ Bicone.ι b x

Next tactic:
intro j _
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cone (Discrete.functor f)
m : s.pt ⟶ (Bicone.toCone b).pt
h : ∀ (j : Discrete J), m ≫ (Bicone.toCone b).π.app j = s.π.app j
j : J
a✝ : j ∈ Finset.univ
⊢ m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app { as := j } ≫ Bicone.ι b j

Next tactic:
have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cone (Discrete.functor f)
m : s.pt ⟶ (Bicone.toCone b).pt
h : ∀ (j : Discrete J), m ≫ (Bicone.toCone b).π.app j = s.π.app j
j : J
a✝ : j ∈ Finset.univ
⊢ m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app { as := j } ≫ Bicone.ι b j

Next tactic:
erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cone (Discrete.functor f)
m : s.pt ⟶ (Bicone.toCone b).pt
h : ∀ (j : Discrete J), m ≫ (Bicone.toCone b).π.app j = s.π.app j
j : J
a✝ : j ∈ Finset.univ
reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app { as := j } ≫ Bicone.ι b j
⊢ m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app { as := j } ≫ Bicone.ι b j

Next tactic:
rw [reassoced]
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        rw [reassoced]
      fac := fun s j => by
        cases j
        simp only [sum_comp, Category.assoc, Bicone.toCone_π_app, b.ι_π, comp_dite]
        -- See note [dsimp, simp].
        dsimp;
        simp }
  isColimit :=
    { desc := fun s => ∑ j : J, b.π j ≫ s.ι.app ⟨j⟩
      uniq := fun s m h => by
        erw [← Category.id_comp m, ← total, sum_comp]
        apply Finset.sum_congr rfl
        intro j _
        erw [Category.assoc, h ⟨j⟩]
      fac := fun s j => by
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cocone (Discrete.functor f)
j : Discrete J
⊢ (Bicone.toCocone b).ι.app j ≫ (fun s => ∑ j : J, Bicone.π b j ≫ s.ι.app { as := j }) s = s.ι.app j

Next tactic:
cases j
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        rw [reassoced]
      fac := fun s j => by
        cases j
        simp only [sum_comp, Category.assoc, Bicone.toCone_π_app, b.ι_π, comp_dite]
        -- See note [dsimp, simp].
        dsimp;
        simp }
  isColimit :=
    { desc := fun s => ∑ j : J, b.π j ≫ s.ι.app ⟨j⟩
      uniq := fun s m h => by
        erw [← Category.id_comp m, ← total, sum_comp]
        apply Finset.sum_congr rfl
        intro j _
        erw [Category.assoc, h ⟨j⟩]
      fac := fun s j => by
        cases j
        

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cocone (Discrete.functor f)
as✝ : J
⊢ (Bicone.toCocone b).ι.app { as := as✝ } ≫ (fun s => ∑ j : J, Bicone.π b j ≫ s.ι.app { as := j }) s =
    s.ι.app { as := as✝ }

Next tactic:
simp only [comp_sum, ← Category.assoc, Bicone.toCocone_ι_app, b.ι_π, dite_comp]
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        rw [reassoced]
      fac := fun s j => by
        cases j
        simp only [sum_comp, Category.assoc, Bicone.toCone_π_app, b.ι_π, comp_dite]
        -- See note [dsimp, simp].
        dsimp;
        simp }
  isColimit :=
    { desc := fun s => ∑ j : J, b.π j ≫ s.ι.app ⟨j⟩
      uniq := fun s m h => by
        erw [← Category.id_comp m, ← total, sum_comp]
        apply Finset.sum_congr rfl
        intro j _
        erw [Category.assoc, h ⟨j⟩]
      fac := fun s j => by
        cases j
        simp only [comp_sum, ← Category.assoc, Bicone.toCocone_ι_app, b.ι_π, dite_comp]
        

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cocone (Discrete.functor f)
as✝ : J
⊢ (∑ x : J, if h : as✝ = x then eqToHom (_ : f as✝ = f x) ≫ s.ι.app { as := x } else 0 ≫ s.ι.app { as := x }) =
    s.ι.app { as := as✝ }

Next tactic:
dsimp
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        rw [reassoced]
      fac := fun s j => by
        cases j
        simp only [sum_comp, Category.assoc, Bicone.toCone_π_app, b.ι_π, comp_dite]
        -- See note [dsimp, simp].
        dsimp;
        simp }
  isColimit :=
    { desc := fun s => ∑ j : J, b.π j ≫ s.ι.app ⟨j⟩
      uniq := fun s m h => by
        erw [← Category.id_comp m, ← total, sum_comp]
        apply Finset.sum_congr rfl
        intro j _
        erw [Category.assoc, h ⟨j⟩]
      fac := fun s j => by
        cases j
        simp only [comp_sum, ← Category.assoc, Bicone.toCocone_ι_app, b.ι_π, dite_comp]
        dsimp; 

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cocone (Discrete.functor f)
as✝ : J
⊢ (∑ x : J, if h : as✝ = x then eqToHom (_ : f as✝ = f x) ≫ s.ι.app { as := x } else 0 ≫ s.ι.app { as := x }) =
    s.ι.app { as := as✝ }

Next tactic:
simp
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        rw [reassoced]
      fac := fun s j => by
        cases j
        simp only [sum_comp, Category.assoc, Bicone.toCone_π_app, b.ι_π, comp_dite]
        -- See note [dsimp, simp].
        dsimp;
        simp }
  isColimit :=
    { desc := fun s => ∑ j : J, b.π j ≫ s.ι.app ⟨j⟩
      uniq := fun s m h => by
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cocone (Discrete.functor f)
m : (Bicone.toCocone b).pt ⟶ s.pt
h : ∀ (j : Discrete J), (Bicone.toCocone b).ι.app j ≫ m = s.ι.app j
⊢ m = (fun s => ∑ j : J, Bicone.π b j ≫ s.ι.app { as := j }) s

Next tactic:
erw [← Category.id_comp m, ← total, sum_comp]
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        rw [reassoced]
      fac := fun s j => by
        cases j
        simp only [sum_comp, Category.assoc, Bicone.toCone_π_app, b.ι_π, comp_dite]
        -- See note [dsimp, simp].
        dsimp;
        simp }
  isColimit :=
    { desc := fun s => ∑ j : J, b.π j ≫ s.ι.app ⟨j⟩
      uniq := fun s m h => by
        erw [← Category.id_comp m, ← total, sum_comp]
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cocone (Discrete.functor f)
m : (Bicone.toCocone b).pt ⟶ s.pt
h : ∀ (j : Discrete J), (Bicone.toCocone b).ι.app j ≫ m = s.ι.app j
⊢ ∑ j : J, (Bicone.π b j ≫ Bicone.ι b j) ≫ m = (fun s => ∑ j : J, Bicone.π b j ≫ s.ι.app { as := j }) s

Next tactic:
apply Finset.sum_congr rfl
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        rw [reassoced]
      fac := fun s j => by
        cases j
        simp only [sum_comp, Category.assoc, Bicone.toCone_π_app, b.ι_π, comp_dite]
        -- See note [dsimp, simp].
        dsimp;
        simp }
  isColimit :=
    { desc := fun s => ∑ j : J, b.π j ≫ s.ι.app ⟨j⟩
      uniq := fun s m h => by
        erw [← Category.id_comp m, ← total, sum_comp]
        apply Finset.sum_congr rfl
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cocone (Discrete.functor f)
m : (Bicone.toCocone b).pt ⟶ s.pt
h : ∀ (j : Discrete J), (Bicone.toCocone b).ι.app j ≫ m = s.ι.app j
⊢ ∀ x ∈ Finset.univ, (Bicone.π b x ≫ Bicone.ι b x) ≫ m = Bicone.π b x ≫ s.ι.app { as := x }

Next tactic:
intro j _
/-- In a preadditive category, we can construct a biproduct for `f : J → C` from
any bicone `b` for `f` satisfying `total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.X`.

(That is, such a bicone is a limit cone and a colimit cocone.)
-/
def isBilimitOfTotal {f : J → C} (b : Bicone f) (total : ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt) :
    b.IsBilimit where
  isLimit :=
    { lift := fun s => ∑ j : J, s.π.app ⟨j⟩ ≫ b.ι j
      uniq := fun s m h => by
        erw [← Category.comp_id m, ← total, comp_sum]
        apply Finset.sum_congr rfl
        intro j _
        have reassoced : m ≫ Bicone.π b j ≫ Bicone.ι b j = s.π.app ⟨j⟩ ≫ Bicone.ι b j := by
          erw [← Category.assoc, eq_whisker (h ⟨j⟩)]
        rw [reassoced]
      fac := fun s j => by
        cases j
        simp only [sum_comp, Category.assoc, Bicone.toCone_π_app, b.ι_π, comp_dite]
        -- See note [dsimp, simp].
        dsimp;
        simp }
  isColimit :=
    { desc := fun s => ∑ j : J, b.π j ≫ s.ι.app ⟨j⟩
      uniq := fun s m h => by
        erw [← Category.id_comp m, ← total, sum_comp]
        apply Finset.sum_congr rfl
        intro j _
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
total : ∑ j : J, Bicone.π b j ≫ Bicone.ι b j = 𝟙 b.pt
s : Cocone (Discrete.functor f)
m : (Bicone.toCocone b).pt ⟶ s.pt
h : ∀ (j : Discrete J), (Bicone.toCocone b).ι.app j ≫ m = s.ι.app j
j : J
a✝ : j ∈ Finset.univ
⊢ (Bicone.π b j ≫ Bicone.ι b j) ≫ m = Bicone.π b j ≫ s.ι.app { as := j }

Next tactic:
erw [Category.assoc, h ⟨j⟩]
theorem IsBilimit.total {f : J → C} {b : Bicone f} (i : b.IsBilimit) :
    ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt :=
  i.isLimit.hom_ext fun j => by
    

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
i : Bicone.IsBilimit b
j : Discrete J
⊢ (∑ j : J, Bicone.π b j ≫ Bicone.ι b j) ≫ (Bicone.toCone b).π.app j = 𝟙 b.pt ≫ (Bicone.toCone b).π.app j

Next tactic:
cases j
theorem IsBilimit.total {f : J → C} {b : Bicone f} (i : b.IsBilimit) :
    ∑ j : J, b.π j ≫ b.ι j = 𝟙 b.pt :=
  i.isLimit.hom_ext fun j => by
    cases j
    

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
b : Bicone f
i : Bicone.IsBilimit b
as✝ : J
⊢ (∑ j : J, Bicone.π b j ≫ Bicone.ι b j) ≫ (Bicone.toCone b).π.app { as := as✝ } =
    𝟙 b.pt ≫ (Bicone.toCone b).π.app { as := as✝ }

Next tactic:
simp [sum_comp, b.ι_π, comp_dite]
/-- In a preadditive category, any finite bicone which is a limit cone is in fact a bilimit
    bicone. -/
def isBilimitOfIsLimit {f : J → C} (t : Bicone f) (ht : IsLimit t.toCone) : t.IsBilimit :=
  isBilimitOfTotal _ <|
    ht.hom_ext fun j => by
      

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
t : Bicone f
ht : IsLimit (Bicone.toCone t)
j : Discrete J
⊢ (∑ j : J, Bicone.π t j ≫ Bicone.ι t j) ≫ (Bicone.toCone t).π.app j = 𝟙 t.pt ≫ (Bicone.toCone t).π.app j

Next tactic:
cases j
/-- In a preadditive category, any finite bicone which is a limit cone is in fact a bilimit
    bicone. -/
def isBilimitOfIsLimit {f : J → C} (t : Bicone f) (ht : IsLimit t.toCone) : t.IsBilimit :=
  isBilimitOfTotal _ <|
    ht.hom_ext fun j => by
      cases j
      

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
t : Bicone f
ht : IsLimit (Bicone.toCone t)
as✝ : J
⊢ (∑ j : J, Bicone.π t j ≫ Bicone.ι t j) ≫ (Bicone.toCone t).π.app { as := as✝ } =
    𝟙 t.pt ≫ (Bicone.toCone t).π.app { as := as✝ }

Next tactic:
simp [sum_comp, t.ι_π, dite_comp, comp_dite]
/-- We can turn any limit cone over a pair into a bilimit bicone. -/
def biconeIsBilimitOfLimitConeOfIsLimit {f : J → C} {t : Cone (Discrete.functor f)}
    (ht : IsLimit t) : (Bicone.ofLimitCone ht).IsBilimit :=
  isBilimitOfIsLimit _ <|
    IsLimit.ofIsoLimit ht <|
      Cones.ext (Iso.refl _)
        (by
          

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
t : Cone (Discrete.functor f)
ht : IsLimit t
⊢ ∀ (j : Discrete J), t.π.app j = (Iso.refl t.pt).hom ≫ (Bicone.toCone (Bicone.ofLimitCone ht)).π.app j

Next tactic:
rintro ⟨j⟩
/-- We can turn any limit cone over a pair into a bilimit bicone. -/
def biconeIsBilimitOfLimitConeOfIsLimit {f : J → C} {t : Cone (Discrete.functor f)}
    (ht : IsLimit t) : (Bicone.ofLimitCone ht).IsBilimit :=
  isBilimitOfIsLimit _ <|
    IsLimit.ofIsoLimit ht <|
      Cones.ext (Iso.refl _)
        (by
          rintro ⟨j⟩
          

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
t : Cone (Discrete.functor f)
ht : IsLimit t
j : J
⊢ t.π.app { as := j } = (Iso.refl t.pt).hom ≫ (Bicone.toCone (Bicone.ofLimitCone ht)).π.app { as := j }

Next tactic:
aesop_cat
/-- In a preadditive category, if the product over `f : J → C` exists,
    then the biproduct over `f` exists. -/
theorem HasBiproduct.of_hasProduct {J : Type} [Finite J] (f : J → C) [HasProduct f] :
    HasBiproduct f := by
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
J✝ : Type
inst✝² : Fintype J✝
J : Type
inst✝¹ : Finite J
f : J → C
inst✝ : HasProduct f
⊢ HasBiproduct f

Next tactic:
cases nonempty_fintype J
/-- In a preadditive category, if the product over `f : J → C` exists,
    then the biproduct over `f` exists. -/
theorem HasBiproduct.of_hasProduct {J : Type} [Finite J] (f : J → C) [HasProduct f] :
    HasBiproduct f := by
  cases nonempty_fintype J;
    

Proof state:
case intro
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Preadditive C
J✝ : Type
inst✝² : Fintype J✝
J : Type
inst✝¹ : Finite J
f : J → C
inst✝ : HasProduct f
val✝ : Fintype J
⊢ HasBiproduct f

Next tactic:
apply HasBiproduct.mk
      { bicone := _
        isBilimit := biconeIsBilimitOfLimitConeOfIsLimit (limit.isLimit _) }
/-- In a preadditive category, any finite bicone which is a colimit cocone is in fact a bilimit
    bicone. -/
def isBilimitOfIsColimit {f : J → C} (t : Bicone f) (ht : IsColimit t.toCocone) : t.IsBilimit :=
  isBilimitOfTotal _ <|
    ht.hom_ext fun j => by
      

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
t : Bicone f
ht : IsColimit (Bicone.toCocone t)
j : Discrete J
⊢ (Bicone.toCocone t).ι.app j ≫ ∑ j : J, Bicone.π t j ≫ Bicone.ι t j = (Bicone.toCocone t).ι.app j ≫ 𝟙 t.pt

Next tactic:
cases j
/-- In a preadditive category, any finite bicone which is a colimit cocone is in fact a bilimit
    bicone. -/
def isBilimitOfIsColimit {f : J → C} (t : Bicone f) (ht : IsColimit t.toCocone) : t.IsBilimit :=
  isBilimitOfTotal _ <|
    ht.hom_ext fun j => by
      cases j
      

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
t : Bicone f
ht : IsColimit (Bicone.toCocone t)
as✝ : J
⊢ (Bicone.toCocone t).ι.app { as := as✝ } ≫ ∑ j : J, Bicone.π t j ≫ Bicone.ι t j =
    (Bicone.toCocone t).ι.app { as := as✝ } ≫ 𝟙 t.pt

Next tactic:
simp_rw [Bicone.toCocone_ι_app, comp_sum, ← Category.assoc, t.ι_π, dite_comp]
/-- In a preadditive category, any finite bicone which is a colimit cocone is in fact a bilimit
    bicone. -/
def isBilimitOfIsColimit {f : J → C} (t : Bicone f) (ht : IsColimit t.toCocone) : t.IsBilimit :=
  isBilimitOfTotal _ <|
    ht.hom_ext fun j => by
      cases j
      simp_rw [Bicone.toCocone_ι_app, comp_sum, ← Category.assoc, t.ι_π, dite_comp]
      

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : Preadditive C
J : Type
inst✝ : Fintype J
f : J → C
t : Bicone f
ht : IsColimit (Bicone.toCocone t)
as✝ : J
⊢ (∑ x : J, if h : as✝ = x then eqToHom (_ : f as✝ = f x) ≫ Bicone.ι t x else 0 ≫ Bicone.ι t x) =
    Bicone.ι t as✝ ≫ 𝟙 t.pt

Next tactic:
simp