l3lab/ntp-mathlib huggingface dataset:
protected theorem injective [DecidableEq α] (f : InjectiveFunction α) : Injective (apply f) := by
  cases' f with xs hperm hnodup
  generalize h₀ : List.map Sigma.fst xs = xs₀
  generalize h₁ : xs.map (@id ((Σ _ : α, α) → α) <| @Sigma.snd α fun _ : α => α) = xs₁
  dsimp [id] at h₁
  have hxs : xs = TotalFunction.List.toFinmap' (xs₀.zip xs₁) := by
    rw [← h₀, ← h₁, List.toFinmap']; clear h₀ h₁ xs₀ xs₁ hperm hnodup
    induction xs with
    | nil => simp only [List.zip_nil_right, List.map_nil]
    | cons xs_hd xs_tl xs_ih =>
      simp only [true_and_iff, Prod.toSigma, eq_self_iff_true, Sigma.eta, List.zip_cons_cons,
        List.map, List.cons_inj]
      

Proof state:
case cons
α : Type u
β : Type v
γ : Sort w
inst✝ : DecidableEq α
xs_hd : (_ : α) × α
xs_tl : List ((_ : α) × α)
xs_ih : xs_tl = map Prod.toSigma (zip (map Sigma.fst xs_tl) (map Sigma.snd xs_tl))
⊢ xs_tl = map Prod.toSigma (zipWith Prod.mk (map Sigma.fst xs_tl) (map Sigma.snd xs_tl))

Next tactic:
exact xs_ih
protected theorem injective [DecidableEq α] (f : InjectiveFunction α) : Injective (apply f) := by
  cases' f with xs hperm hnodup
  generalize h₀ : List.map Sigma.fst xs = xs₀
  generalize h₁ : xs.map (@id ((Σ _ : α, α) → α) <| @Sigma.snd α fun _ : α => α) = xs₁
  dsimp [id] at h₁
  have hxs : xs = TotalFunction.List.toFinmap' (xs₀.zip xs₁) := by
    rw [← h₀, ← h₁, List.toFinmap']; clear h₀ h₁ xs₀ xs₁ hperm hnodup
    induction xs with
    | nil => simp only [List.zip_nil_right, List.map_nil]
    | cons xs_hd xs_tl xs_ih =>
      simp only [true_and_iff, Prod.toSigma, eq_self_iff_true, Sigma.eta, List.zip_cons_cons,
        List.map, List.cons_inj]
      exact xs_ih
  

Proof state:
case mapToSelf
α : Type u
β : Type v
γ : Sort w
inst✝ : DecidableEq α
xs : List ((_ : α) × α)
hperm : map Sigma.fst xs ~ map Sigma.snd xs
hnodup : Nodup (map Sigma.snd xs)
xs₀ : List α
h₀ : map Sigma.fst xs = xs₀
xs₁ : List α
h₁ : map Sigma.snd xs = xs₁
hxs : xs = List.toFinmap' (zip xs₀ xs₁)
⊢ Injective (apply (mapToSelf xs hperm hnodup))

Next tactic:
revert hperm hnodup
protected theorem injective [DecidableEq α] (f : InjectiveFunction α) : Injective (apply f) := by
  cases' f with xs hperm hnodup
  generalize h₀ : List.map Sigma.fst xs = xs₀
  generalize h₁ : xs.map (@id ((Σ _ : α, α) → α) <| @Sigma.snd α fun _ : α => α) = xs₁
  dsimp [id] at h₁
  have hxs : xs = TotalFunction.List.toFinmap' (xs₀.zip xs₁) := by
    rw [← h₀, ← h₁, List.toFinmap']; clear h₀ h₁ xs₀ xs₁ hperm hnodup
    induction xs with
    | nil => simp only [List.zip_nil_right, List.map_nil]
    | cons xs_hd xs_tl xs_ih =>
      simp only [true_and_iff, Prod.toSigma, eq_self_iff_true, Sigma.eta, List.zip_cons_cons,
        List.map, List.cons_inj]
      exact xs_ih
  revert hperm hnodup
  

Proof state:
case mapToSelf
α : Type u
β : Type v
γ : Sort w
inst✝ : DecidableEq α
xs : List ((_ : α) × α)
xs₀ : List α
h₀ : map Sigma.fst xs = xs₀
xs₁ : List α
h₁ : map Sigma.snd xs = xs₁
hxs : xs = List.toFinmap' (zip xs₀ xs₁)
⊢ ∀ (hperm : map Sigma.fst xs ~ map Sigma.snd xs) (hnodup : Nodup (map Sigma.snd xs)),
    Injective (apply (mapToSelf xs hperm hnodup))

Next tactic:
rw [hxs]
protected theorem injective [DecidableEq α] (f : InjectiveFunction α) : Injective (apply f) := by
  cases' f with xs hperm hnodup
  generalize h₀ : List.map Sigma.fst xs = xs₀
  generalize h₁ : xs.map (@id ((Σ _ : α, α) → α) <| @Sigma.snd α fun _ : α => α) = xs₁
  dsimp [id] at h₁
  have hxs : xs = TotalFunction.List.toFinmap' (xs₀.zip xs₁) := by
    rw [← h₀, ← h₁, List.toFinmap']; clear h₀ h₁ xs₀ xs₁ hperm hnodup
    induction xs with
    | nil => simp only [List.zip_nil_right, List.map_nil]
    | cons xs_hd xs_tl xs_ih =>
      simp only [true_and_iff, Prod.toSigma, eq_self_iff_true, Sigma.eta, List.zip_cons_cons,
        List.map, List.cons_inj]
      exact xs_ih
  revert hperm hnodup
  rw [hxs]; 

Proof state:
case mapToSelf
α : Type u
β : Type v
γ : Sort w
inst✝ : DecidableEq α
xs : List ((_ : α) × α)
xs₀ : List α
h₀ : map Sigma.fst xs = xs₀
xs₁ : List α
h₁ : map Sigma.snd xs = xs₁
hxs : xs = List.toFinmap' (zip xs₀ xs₁)
⊢ ∀ (hperm : map Sigma.fst (List.toFinmap' (zip xs₀ xs₁)) ~ map Sigma.snd (List.toFinmap' (zip xs₀ xs₁)))
    (hnodup : Nodup (map Sigma.snd (List.toFinmap' (zip xs₀ xs₁)))),
    Injective (apply (mapToSelf (List.toFinmap' (zip xs₀ xs₁)) hperm hnodup))

Next tactic:
intros hperm hnodup
protected theorem injective [DecidableEq α] (f : InjectiveFunction α) : Injective (apply f) := by
  cases' f with xs hperm hnodup
  generalize h₀ : List.map Sigma.fst xs = xs₀
  generalize h₁ : xs.map (@id ((Σ _ : α, α) → α) <| @Sigma.snd α fun _ : α => α) = xs₁
  dsimp [id] at h₁
  have hxs : xs = TotalFunction.List.toFinmap' (xs₀.zip xs₁) := by
    rw [← h₀, ← h₁, List.toFinmap']; clear h₀ h₁ xs₀ xs₁ hperm hnodup
    induction xs with
    | nil => simp only [List.zip_nil_right, List.map_nil]
    | cons xs_hd xs_tl xs_ih =>
      simp only [true_and_iff, Prod.toSigma, eq_self_iff_true, Sigma.eta, List.zip_cons_cons,
        List.map, List.cons_inj]
      exact xs_ih
  revert hperm hnodup
  rw [hxs]; intros hperm hnodup
  

Proof state:
case mapToSelf
α : Type u
β : Type v
γ : Sort w
inst✝ : DecidableEq α
xs : List ((_ : α) × α)
xs₀ : List α
h₀ : map Sigma.fst xs = xs₀
xs₁ : List α
h₁ : map Sigma.snd xs = xs₁
hxs : xs = List.toFinmap' (zip xs₀ xs₁)
hperm : map Sigma.fst (List.toFinmap' (zip xs₀ xs₁)) ~ map Sigma.snd (List.toFinmap' (zip xs₀ xs₁))
hnodup : Nodup (map Sigma.snd (List.toFinmap' (zip xs₀ xs₁)))
⊢ Injective (apply (mapToSelf (List.toFinmap' (zip xs₀ xs₁)) hperm hnodup))

Next tactic:
apply InjectiveFunction.applyId_injective
protected theorem injective [DecidableEq α] (f : InjectiveFunction α) : Injective (apply f) := by
  cases' f with xs hperm hnodup
  generalize h₀ : List.map Sigma.fst xs = xs₀
  generalize h₁ : xs.map (@id ((Σ _ : α, α) → α) <| @Sigma.snd α fun _ : α => α) = xs₁
  dsimp [id] at h₁
  have hxs : xs = TotalFunction.List.toFinmap' (xs₀.zip xs₁) := by
    rw [← h₀, ← h₁, List.toFinmap']; clear h₀ h₁ xs₀ xs₁ hperm hnodup
    induction xs with
    | nil => simp only [List.zip_nil_right, List.map_nil]
    | cons xs_hd xs_tl xs_ih =>
      simp only [true_and_iff, Prod.toSigma, eq_self_iff_true, Sigma.eta, List.zip_cons_cons,
        List.map, List.cons_inj]
      exact xs_ih
  revert hperm hnodup
  rw [hxs]; intros hperm hnodup
  apply InjectiveFunction.applyId_injective
  · 

Proof state:
case mapToSelf.h₀
α : Type u
β : Type v
γ : Sort w
inst✝ : DecidableEq α
xs : List ((_ : α) × α)
xs₀ : List α
h₀ : map Sigma.fst xs = xs₀
xs₁ : List α
h₁ : map Sigma.snd xs = xs₁
hxs : xs = List.toFinmap' (zip xs₀ xs₁)
hperm : map Sigma.fst (List.toFinmap' (zip xs₀ xs₁)) ~ map Sigma.snd (List.toFinmap' (zip xs₀ xs₁))
hnodup : Nodup (map Sigma.snd (List.toFinmap' (zip xs₀ xs₁)))
⊢ Nodup xs₀

Next tactic:
rwa [← h₀, hxs, hperm.nodup_iff]
protected theorem injective [DecidableEq α] (f : InjectiveFunction α) : Injective (apply f) := by
  cases' f with xs hperm hnodup
  generalize h₀ : List.map Sigma.fst xs = xs₀
  generalize h₁ : xs.map (@id ((Σ _ : α, α) → α) <| @Sigma.snd α fun _ : α => α) = xs₁
  dsimp [id] at h₁
  have hxs : xs = TotalFunction.List.toFinmap' (xs₀.zip xs₁) := by
    rw [← h₀, ← h₁, List.toFinmap']; clear h₀ h₁ xs₀ xs₁ hperm hnodup
    induction xs with
    | nil => simp only [List.zip_nil_right, List.map_nil]
    | cons xs_hd xs_tl xs_ih =>
      simp only [true_and_iff, Prod.toSigma, eq_self_iff_true, Sigma.eta, List.zip_cons_cons,
        List.map, List.cons_inj]
      exact xs_ih
  revert hperm hnodup
  rw [hxs]; intros hperm hnodup
  apply InjectiveFunction.applyId_injective
  · rwa [← h₀, hxs, hperm.nodup_iff]
  · 

Proof state:
case mapToSelf.h₁
α : Type u
β : Type v
γ : Sort w
inst✝ : DecidableEq α
xs : List ((_ : α) × α)
xs₀ : List α
h₀ : map Sigma.fst xs = xs₀
xs₁ : List α
h₁ : map Sigma.snd xs = xs₁
hxs : xs = List.toFinmap' (zip xs₀ xs₁)
hperm : map Sigma.fst (List.toFinmap' (zip xs₀ xs₁)) ~ map Sigma.snd (List.toFinmap' (zip xs₀ xs₁))
hnodup : Nodup (map Sigma.snd (List.toFinmap' (zip xs₀ xs₁)))
⊢ xs₀ ~ xs₁

Next tactic:
rwa [← hxs, h₀, h₁] at hperm
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      

Proof state:
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
⊢ ∀ {W X Y Z : D} (f : W ⟶ X), f ⊗ 0 = 0

Next tactic:
intros
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      

Proof state:
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
W✝ X✝ Y✝ Z✝ : D
f✝ : W✝ ⟶ X✝
⊢ f✝ ⊗ 0 = 0

Next tactic:
apply F.toFunctor.map_injective
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      apply F.toFunctor.map_injective
      

Proof state:
case a
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
W✝ X✝ Y✝ Z✝ : D
f✝ : W✝ ⟶ X✝
⊢ F.map (f✝ ⊗ 0) = F.map 0

Next tactic:
simp [F.map_tensor]
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    zero_tensor := by
      

Proof state:
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
⊢ ∀ {W X Y Z : D} (f : Y ⟶ Z), 0 ⊗ f = 0

Next tactic:
intros
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    zero_tensor := by
      intros
      

Proof state:
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
W✝ X✝ Y✝ Z✝ : D
f✝ : Y✝ ⟶ Z✝
⊢ 0 ⊗ f✝ = 0

Next tactic:
apply F.toFunctor.map_injective
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    zero_tensor := by
      intros
      apply F.toFunctor.map_injective
      

Proof state:
case a
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
W✝ X✝ Y✝ Z✝ : D
f✝ : Y✝ ⟶ Z✝
⊢ F.map (0 ⊗ f✝) = F.map 0

Next tactic:
simp [F.map_tensor]
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    zero_tensor := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    tensor_add := by
      

Proof state:
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
⊢ ∀ {W X Y Z : D} (f : W ⟶ X) (g h : Y ⟶ Z), f ⊗ (g + h) = f ⊗ g + f ⊗ h

Next tactic:
intros
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    zero_tensor := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    tensor_add := by
      intros
      

Proof state:
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
W✝ X✝ Y✝ Z✝ : D
f✝ : W✝ ⟶ X✝
g✝ h✝ : Y✝ ⟶ Z✝
⊢ f✝ ⊗ (g✝ + h✝) = f✝ ⊗ g✝ + f✝ ⊗ h✝

Next tactic:
apply F.toFunctor.map_injective
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    zero_tensor := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    tensor_add := by
      intros
      apply F.toFunctor.map_injective
      

Proof state:
case a
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
W✝ X✝ Y✝ Z✝ : D
f✝ : W✝ ⟶ X✝
g✝ h✝ : Y✝ ⟶ Z✝
⊢ F.map (f✝ ⊗ (g✝ + h✝)) = F.map (f✝ ⊗ g✝ + f✝ ⊗ h✝)

Next tactic:
simp only [F.map_tensor, Functor.map_add, Preadditive.comp_add, Preadditive.add_comp,
        MonoidalPreadditive.tensor_add]
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    zero_tensor := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    tensor_add := by
      intros
      apply F.toFunctor.map_injective
      simp only [F.map_tensor, Functor.map_add, Preadditive.comp_add, Preadditive.add_comp,
        MonoidalPreadditive.tensor_add]
    add_tensor := by
      

Proof state:
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
⊢ ∀ {W X Y Z : D} (f g : W ⟶ X) (h : Y ⟶ Z), (f + g) ⊗ h = f ⊗ h + g ⊗ h

Next tactic:
intros
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    zero_tensor := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    tensor_add := by
      intros
      apply F.toFunctor.map_injective
      simp only [F.map_tensor, Functor.map_add, Preadditive.comp_add, Preadditive.add_comp,
        MonoidalPreadditive.tensor_add]
    add_tensor := by
      intros
      

Proof state:
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
W✝ X✝ Y✝ Z✝ : D
f✝ g✝ : W✝ ⟶ X✝
h✝ : Y✝ ⟶ Z✝
⊢ (f✝ + g✝) ⊗ h✝ = f✝ ⊗ h✝ + g✝ ⊗ h✝

Next tactic:
apply F.toFunctor.map_injective
/-- A faithful additive monoidal functor to a monoidal preadditive category
ensures that the domain is monoidal preadditive. -/
theorem monoidalPreadditive_of_faithful {D} [Category D] [Preadditive D] [MonoidalCategory D]
    (F : MonoidalFunctor D C) [Faithful F.toFunctor] [F.toFunctor.Additive] :
    MonoidalPreadditive D :=
  { tensor_zero := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    zero_tensor := by
      intros
      apply F.toFunctor.map_injective
      simp [F.map_tensor]
    tensor_add := by
      intros
      apply F.toFunctor.map_injective
      simp only [F.map_tensor, Functor.map_add, Preadditive.comp_add, Preadditive.add_comp,
        MonoidalPreadditive.tensor_add]
    add_tensor := by
      intros
      apply F.toFunctor.map_injective
      

Proof state:
case a
C : Type u_1
inst✝⁸ : Category.{u_4, u_1} C
inst✝⁷ : Preadditive C
inst✝⁶ : MonoidalCategory C
inst✝⁵ : MonoidalPreadditive C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : Preadditive D
inst✝² : MonoidalCategory D
F : MonoidalFunctor D C
inst✝¹ : Faithful F.toFunctor
inst✝ : Functor.Additive F.toFunctor
W✝ X✝ Y✝ Z✝ : D
f✝ g✝ : W✝ ⟶ X✝
h✝ : Y✝ ⟶ Z✝
⊢ F.map ((f✝ + g✝) ⊗ h✝) = F.map (f✝ ⊗ h✝ + g✝ ⊗ h✝)

Next tactic:
simp only [F.map_tensor, Functor.map_add, Preadditive.comp_add, Preadditive.add_comp,
        MonoidalPreadditive.add_tensor]
theorem tensor_sum {P Q R S : C} {J : Type*} (s : Finset J) (f : P ⟶ Q) (g : J → (R ⟶ S)) :
    (f ⊗ ∑ j in s, g j) = ∑ j in s, f ⊗ g j := by
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_3, u_1} C
inst✝² : Preadditive C
inst✝¹ : MonoidalCategory C
inst✝ : MonoidalPreadditive C
P Q R S : C
J : Type u_2
s : Finset J
f : P ⟶ Q
g : J → (R ⟶ S)
⊢ f ⊗ ∑ j in s, g j = ∑ j in s, f ⊗ g j

Next tactic:
rw [← tensor_id_comp_id_tensor]
theorem tensor_sum {P Q R S : C} {J : Type*} (s : Finset J) (f : P ⟶ Q) (g : J → (R ⟶ S)) :
    (f ⊗ ∑ j in s, g j) = ∑ j in s, f ⊗ g j := by
  rw [← tensor_id_comp_id_tensor]
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_3, u_1} C
inst✝² : Preadditive C
inst✝¹ : MonoidalCategory C
inst✝ : MonoidalPreadditive C
P Q R S : C
J : Type u_2
s : Finset J
f : P ⟶ Q
g : J → (R ⟶ S)
⊢ (f ⊗ 𝟙 R) ≫ (𝟙 Q ⊗ ∑ j in s, g j) = ∑ j in s, f ⊗ g j

Next tactic:
let tQ := (((tensoringLeft C).obj Q).mapAddHom : (R ⟶ S) →+ _)
theorem tensor_sum {P Q R S : C} {J : Type*} (s : Finset J) (f : P ⟶ Q) (g : J → (R ⟶ S)) :
    (f ⊗ ∑ j in s, g j) = ∑ j in s, f ⊗ g j := by
  rw [← tensor_id_comp_id_tensor]
  let tQ := (((tensoringLeft C).obj Q).mapAddHom : (R ⟶ S) →+ _)
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_3, u_1} C
inst✝² : Preadditive C
inst✝¹ : MonoidalCategory C
inst✝ : MonoidalPreadditive C
P Q R S : C
J : Type u_2
s : Finset J
f : P ⟶ Q
g : J → (R ⟶ S)
tQ : (R ⟶ S) →+ (((tensoringLeft C).obj Q).obj R ⟶ ((tensoringLeft C).obj Q).obj S) :=
  Functor.mapAddHom ((tensoringLeft C).obj Q)
⊢ (f ⊗ 𝟙 R) ≫ (𝟙 Q ⊗ ∑ j in s, g j) = ∑ j in s, f ⊗ g j

Next tactic:
change _ ≫ tQ _ = _
theorem tensor_sum {P Q R S : C} {J : Type*} (s : Finset J) (f : P ⟶ Q) (g : J → (R ⟶ S)) :
    (f ⊗ ∑ j in s, g j) = ∑ j in s, f ⊗ g j := by
  rw [← tensor_id_comp_id_tensor]
  let tQ := (((tensoringLeft C).obj Q).mapAddHom : (R ⟶ S) →+ _)
  change _ ≫ tQ _ = _
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_3, u_1} C
inst✝² : Preadditive C
inst✝¹ : MonoidalCategory C
inst✝ : MonoidalPreadditive C
P Q R S : C
J : Type u_2
s : Finset J
f : P ⟶ Q
g : J → (R ⟶ S)
tQ : (R ⟶ S) →+ (((tensoringLeft C).obj Q).obj R ⟶ ((tensoringLeft C).obj Q).obj S) :=
  Functor.mapAddHom ((tensoringLeft C).obj Q)
⊢ (f ⊗ 𝟙 R) ≫ tQ (∑ j in s, g j) = ∑ j in s, f ⊗ g j

Next tactic:
rw [map_sum, Preadditive.comp_sum]
theorem tensor_sum {P Q R S : C} {J : Type*} (s : Finset J) (f : P ⟶ Q) (g : J → (R ⟶ S)) :
    (f ⊗ ∑ j in s, g j) = ∑ j in s, f ⊗ g j := by
  rw [← tensor_id_comp_id_tensor]
  let tQ := (((tensoringLeft C).obj Q).mapAddHom : (R ⟶ S) →+ _)
  change _ ≫ tQ _ = _
  rw [map_sum, Preadditive.comp_sum]
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_3, u_1} C
inst✝² : Preadditive C
inst✝¹ : MonoidalCategory C
inst✝ : MonoidalPreadditive C
P Q R S : C
J : Type u_2
s : Finset J
f : P ⟶ Q
g : J → (R ⟶ S)
tQ : (R ⟶ S) →+ (((tensoringLeft C).obj Q).obj R ⟶ ((tensoringLeft C).obj Q).obj S) :=
  Functor.mapAddHom ((tensoringLeft C).obj Q)
⊢ ∑ j in s, (f ⊗ 𝟙 R) ≫ tQ (g j) = ∑ j in s, f ⊗ g j

Next tactic:
dsimp [Functor.mapAddHom]
theorem tensor_sum {P Q R S : C} {J : Type*} (s : Finset J) (f : P ⟶ Q) (g : J → (R ⟶ S)) :
    (f ⊗ ∑ j in s, g j) = ∑ j in s, f ⊗ g j := by
  rw [← tensor_id_comp_id_tensor]
  let tQ := (((tensoringLeft C).obj Q).mapAddHom : (R ⟶ S) →+ _)
  change _ ≫ tQ _ = _
  rw [map_sum, Preadditive.comp_sum]
  dsimp [Functor.mapAddHom]
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_3, u_1} C
inst✝² : Preadditive C
inst✝¹ : MonoidalCategory C
inst✝ : MonoidalPreadditive C
P Q R S : C
J : Type u_2
s : Finset J
f : P ⟶ Q
g : J → (R ⟶ S)
tQ : (R ⟶ S) →+ (((tensoringLeft C).obj Q).obj R ⟶ ((tensoringLeft C).obj Q).obj S) :=
  Functor.mapAddHom ((tensoringLeft C).obj Q)
⊢ ∑ j in s, (f ⊗ 𝟙 R) ≫ (𝟙 Q ⊗ g j) = ∑ j in s, f ⊗ g j

Next tactic:
simp only [tensor_id_comp_id_tensor]
theorem sum_tensor {P Q R S : C} {J : Type*} (s : Finset J) (f : P ⟶ Q) (g : J → (R ⟶ S)) :
    (∑ j in s, g j) ⊗ f = ∑ j in s, g j ⊗ f := by
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_3, u_1} C
inst✝² : Preadditive C
inst✝¹ : MonoidalCategory C
inst✝ : MonoidalPreadditive C
P Q R S : C
J : Type u_2
s : Finset J
f : P ⟶ Q
g : J → (R ⟶ S)
⊢ (∑ j in s, g j) ⊗ f = ∑ j in s, g j ⊗ f

Next tactic:
rw [← tensor_id_comp_id_tensor]