/-
Copyright (c) 2021 Scott Morrison. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Scott Morrison

! This file was ported from Lean 3 source module category_theory.linear.linear_functor
! leanprover-community/mathlib commit 10bf4f825ad729c5653adc039dafa3622e7f93c9
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.CategoryTheory.Preadditive.AdditiveFunctor
import Mathbin.CategoryTheory.Linear.Basic

/-!
# Linear Functors

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

An additive functor between two `R`-linear categories is called *linear*
if the induced map on hom types is a morphism of `R`-modules.

# Implementation details

`functor.linear` is a `Prop`-valued class, defined by saying that
for every two objects `X` and `Y`, the map
`F.map : (X ⟶ Y) → (F.obj X ⟶ F.obj Y)` is a morphism of `R`-modules.

-/

namespace CategoryTheory

variable (R : Type _) [Semiring R]

#print CategoryTheory.Functor.Linear /-
/-- An additive functor `F` is `R`-linear provided `F.map` is an `R`-module morphism. -/
class Functor.Linear {C D : Type _} [Category C] [Category D] [Preadditive C] [Preadditive D]
  [Linear R C] [Linear R D] (F : C ⥤ D) [F.Additive] : Prop where
  map_smul' : ∀ {X Y : C} {f : X ⟶ Y} {r : R}, F.map (r • f) = r • F.map f := by obviously
#align category_theory.functor.linear CategoryTheory.Functor.Linear
-/

section Linear

namespace Functor

section

variable {R} {C D : Type _} [Category C] [Category D] [Preadditive C] [Preadditive D]
  [CategoryTheory.Linear R C] [CategoryTheory.Linear R D] (F : C ⥤ D) [Additive F] [Linear R F]

/- warning: category_theory.functor.map_smul -> CategoryTheory.Functor.map_smul is a dubious translation:
lean 3 declaration is
  forall {R : Type.{u1}} [_inst_1 : Semiring.{u1} R] {C : Type.{u2}} {D : Type.{u3}} [_inst_2 : CategoryTheory.Category.{u4, u2} C] [_inst_3 : CategoryTheory.Category.{u5, u3} D] [_inst_4 : CategoryTheory.Preadditive.{u4, u2} C _inst_2] [_inst_5 : CategoryTheory.Preadditive.{u5, u3} D _inst_3] [_inst_6 : CategoryTheory.Linear.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4] [_inst_7 : CategoryTheory.Linear.{u1, u5, u3} R _inst_1 D _inst_3 _inst_5] (F : CategoryTheory.Functor.{u4, u5, u2, u3} C _inst_2 D _inst_3) [_inst_8 : CategoryTheory.Functor.Additive.{u2, u3, u4, u5} C D _inst_2 _inst_3 _inst_4 _inst_5 F] [_inst_9 : CategoryTheory.Functor.Linear.{u1, u2, u3, u4, u5} R _inst_1 C D _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 _inst_7 F _inst_8] {X : C} {Y : C} (r : R) (f : Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y), Eq.{succ u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (CategoryTheory.Functor.map.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X Y (SMul.smul.{u1, u4} R (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (SMulZeroClass.toHasSmul.{u1, u4} R (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (AddZeroClass.toHasZero.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (AddMonoid.toAddZeroClass.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (AddCommMonoid.toAddMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u4, u2} C _inst_2 _inst_4 X Y))))) (SMulWithZero.toSmulZeroClass.{u1, u4} R (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (MulZeroClass.toHasZero.{u1} R (MulZeroOneClass.toMulZeroClass.{u1} R (MonoidWithZero.toMulZeroOneClass.{u1} R (Semiring.toMonoidWithZero.{u1} R _inst_1)))) (AddZeroClass.toHasZero.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (AddMonoid.toAddZeroClass.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (AddCommMonoid.toAddMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u4, u2} C _inst_2 _inst_4 X Y))))) (MulActionWithZero.toSMulWithZero.{u1, u4} R (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (Semiring.toMonoidWithZero.{u1} R _inst_1) (AddZeroClass.toHasZero.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (AddMonoid.toAddZeroClass.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (AddCommMonoid.toAddMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u4, u2} C _inst_2 _inst_4 X Y))))) (Module.toMulActionWithZero.{u1, u4} R (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) _inst_1 (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u4, u2} C _inst_2 _inst_4 X Y)) (CategoryTheory.Linear.homModule.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4 _inst_6 X Y))))) r f)) (SMul.smul.{u1, u5} R (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (SMulZeroClass.toHasSmul.{u1, u5} R (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddZeroClass.toHasZero.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddMonoid.toAddZeroClass.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddCommMonoid.toAddMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (CategoryTheory.Preadditive.homGroup.{u5, u3} D _inst_3 _inst_5 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)))))) (SMulWithZero.toSmulZeroClass.{u1, u5} R (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (MulZeroClass.toHasZero.{u1} R (MulZeroOneClass.toMulZeroClass.{u1} R (MonoidWithZero.toMulZeroOneClass.{u1} R (Semiring.toMonoidWithZero.{u1} R _inst_1)))) (AddZeroClass.toHasZero.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddMonoid.toAddZeroClass.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddCommMonoid.toAddMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (CategoryTheory.Preadditive.homGroup.{u5, u3} D _inst_3 _inst_5 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)))))) (MulActionWithZero.toSMulWithZero.{u1, u5} R (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (Semiring.toMonoidWithZero.{u1} R _inst_1) (AddZeroClass.toHasZero.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddMonoid.toAddZeroClass.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddCommMonoid.toAddMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (CategoryTheory.Preadditive.homGroup.{u5, u3} D _inst_3 _inst_5 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)))))) (Module.toMulActionWithZero.{u1, u5} R (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) _inst_1 (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (CategoryTheory.Preadditive.homGroup.{u5, u3} D _inst_3 _inst_5 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y))) (CategoryTheory.Linear.homModule.{u1, u5, u3} R _inst_1 D _inst_3 _inst_5 _inst_7 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)))))) r (CategoryTheory.Functor.map.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X Y f))
but is expected to have type
  forall {R : Type.{u1}} [_inst_1 : Semiring.{u1} R] {C : Type.{u4}} {D : Type.{u2}} [_inst_2 : CategoryTheory.Category.{u5, u4} C] [_inst_3 : CategoryTheory.Category.{u3, u2} D] [_inst_4 : CategoryTheory.Preadditive.{u5, u4} C _inst_2] [_inst_5 : CategoryTheory.Preadditive.{u3, u2} D _inst_3] [_inst_6 : CategoryTheory.Linear.{u1, u5, u4} R _inst_1 C _inst_2 _inst_4] [_inst_7 : CategoryTheory.Linear.{u1, u3, u2} R _inst_1 D _inst_3 _inst_5] (F : CategoryTheory.Functor.{u5, u3, u4, u2} C _inst_2 D _inst_3) [_inst_8 : CategoryTheory.Functor.Additive.{u4, u2, u5, u3} C D _inst_2 _inst_3 _inst_4 _inst_5 F] [_inst_9 : CategoryTheory.Functor.Linear.{u1, u4, u2, u5, u3} R _inst_1 C D _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 _inst_7 F _inst_8] {X : C} {Y : C} (r : R) (f : Quiver.Hom.{succ u5, u4} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) X Y), Eq.{succ u3} (Quiver.Hom.{succ u3, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (Prefunctor.map.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X Y (HSMul.hSMul.{u1, u5, u5} R (Quiver.Hom.{succ u5, u4} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) X Y) (Quiver.Hom.{succ u5, u4} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) X Y) (instHSMul.{u1, u5} R (Quiver.Hom.{succ u5, u4} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) X Y) (SMulZeroClass.toSMul.{u1, u5} R (Quiver.Hom.{succ u5, u4} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) X Y) (CategoryTheory.Limits.HasZeroMorphisms.Zero.{u5, u4} C _inst_2 (CategoryTheory.Preadditive.preadditiveHasZeroMorphisms.{u5, u4} C _inst_2 _inst_4) X Y) (SMulWithZero.toSMulZeroClass.{u1, u5} R (Quiver.Hom.{succ u5, u4} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) X Y) (MonoidWithZero.toZero.{u1} R (Semiring.toMonoidWithZero.{u1} R _inst_1)) (CategoryTheory.Limits.HasZeroMorphisms.Zero.{u5, u4} C _inst_2 (CategoryTheory.Preadditive.preadditiveHasZeroMorphisms.{u5, u4} C _inst_2 _inst_4) X Y) (MulActionWithZero.toSMulWithZero.{u1, u5} R (Quiver.Hom.{succ u5, u4} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) X Y) (Semiring.toMonoidWithZero.{u1} R _inst_1) (CategoryTheory.Limits.HasZeroMorphisms.Zero.{u5, u4} C _inst_2 (CategoryTheory.Preadditive.preadditiveHasZeroMorphisms.{u5, u4} C _inst_2 _inst_4) X Y) (Module.toMulActionWithZero.{u1, u5} R (Quiver.Hom.{succ u5, u4} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) X Y) _inst_1 (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u4} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u5, u4} C _inst_2 _inst_4 X Y)) (CategoryTheory.Linear.homModule.{u1, u5, u4} R _inst_1 C _inst_2 _inst_4 _inst_6 X Y)))))) r f)) (HSMul.hSMul.{u1, u3, u3} R (Quiver.Hom.{succ u3, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (Quiver.Hom.{succ u3, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (instHSMul.{u1, u3} R (Quiver.Hom.{succ u3, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (SMulZeroClass.toSMul.{u1, u3} R (Quiver.Hom.{succ u3, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (CategoryTheory.Limits.HasZeroMorphisms.Zero.{u3, u2} D _inst_3 (CategoryTheory.Preadditive.preadditiveHasZeroMorphisms.{u3, u2} D _inst_3 _inst_5) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (SMulWithZero.toSMulZeroClass.{u1, u3} R (Quiver.Hom.{succ u3, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (MonoidWithZero.toZero.{u1} R (Semiring.toMonoidWithZero.{u1} R _inst_1)) (CategoryTheory.Limits.HasZeroMorphisms.Zero.{u3, u2} D _inst_3 (CategoryTheory.Preadditive.preadditiveHasZeroMorphisms.{u3, u2} D _inst_3 _inst_5) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (MulActionWithZero.toSMulWithZero.{u1, u3} R (Quiver.Hom.{succ u3, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (Semiring.toMonoidWithZero.{u1} R _inst_1) (CategoryTheory.Limits.HasZeroMorphisms.Zero.{u3, u2} D _inst_3 (CategoryTheory.Preadditive.preadditiveHasZeroMorphisms.{u3, u2} D _inst_3 _inst_5) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (Module.toMulActionWithZero.{u1, u3} R (Quiver.Hom.{succ u3, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) _inst_1 (AddCommGroup.toAddCommMonoid.{u3} (Quiver.Hom.{succ u3, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y)) (CategoryTheory.Preadditive.homGroup.{u3, u2} D _inst_3 _inst_5 (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y))) (CategoryTheory.Linear.homModule.{u1, u3, u2} R _inst_1 D _inst_3 _inst_5 _inst_7 (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) Y))))))) r (Prefunctor.map.{succ u5, succ u3, u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u4} C (CategoryTheory.Category.toCategoryStruct.{u5, u4} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u3, u2} D (CategoryTheory.Category.toCategoryStruct.{u3, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u3, u4, u2} C _inst_2 D _inst_3 F) X Y f))
Case conversion may be inaccurate. Consider using '#align category_theory.functor.map_smul CategoryTheory.Functor.map_smulₓ'. -/
@[simp]
theorem map_smul {X Y : C} (r : R) (f : X ⟶ Y) : F.map (r • f) = r • F.map f :=
  Functor.Linear.map_smul'
#align category_theory.functor.map_smul CategoryTheory.Functor.map_smul

instance : Linear R (𝟭 C) where

instance {E : Type _} [Category E] [Preadditive E] [CategoryTheory.Linear R E] (G : D ⥤ E)
    [Additive G] [Linear R G] : Linear R (F ⋙ G) where

variable (R)

/- warning: category_theory.functor.map_linear_map -> CategoryTheory.Functor.mapLinearMap is a dubious translation:
lean 3 declaration is
  forall (R : Type.{u1}) [_inst_1 : Semiring.{u1} R] {C : Type.{u2}} {D : Type.{u3}} [_inst_2 : CategoryTheory.Category.{u4, u2} C] [_inst_3 : CategoryTheory.Category.{u5, u3} D] [_inst_4 : CategoryTheory.Preadditive.{u4, u2} C _inst_2] [_inst_5 : CategoryTheory.Preadditive.{u5, u3} D _inst_3] [_inst_6 : CategoryTheory.Linear.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4] [_inst_7 : CategoryTheory.Linear.{u1, u5, u3} R _inst_1 D _inst_3 _inst_5] (F : CategoryTheory.Functor.{u4, u5, u2, u3} C _inst_2 D _inst_3) [_inst_8 : CategoryTheory.Functor.Additive.{u2, u3, u4, u5} C D _inst_2 _inst_3 _inst_4 _inst_5 F] [_inst_9 : CategoryTheory.Functor.Linear.{u1, u2, u3, u4, u5} R _inst_1 C D _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 _inst_7 F _inst_8] {X : C} {Y : C}, LinearMap.{u1, u1, u4, u5} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u4, u2} C _inst_2 _inst_4 X Y)) (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (CategoryTheory.Preadditive.homGroup.{u5, u3} D _inst_3 _inst_5 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y))) (CategoryTheory.Linear.homModule.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4 _inst_6 X Y) (CategoryTheory.Linear.homModule.{u1, u5, u3} R _inst_1 D _inst_3 _inst_5 _inst_7 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y))
but is expected to have type
  forall (R : Type.{u1}) [_inst_1 : Semiring.{u1} R] {C : Type.{u2}} {D : Type.{u3}} [_inst_2 : CategoryTheory.Category.{u4, u2} C] [_inst_3 : CategoryTheory.Category.{u5, u3} D] [_inst_4 : CategoryTheory.Preadditive.{u4, u2} C _inst_2] [_inst_5 : CategoryTheory.Preadditive.{u5, u3} D _inst_3] [_inst_6 : CategoryTheory.Linear.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4] [_inst_7 : CategoryTheory.Linear.{u1, u5, u3} R _inst_1 D _inst_3 _inst_5] (F : CategoryTheory.Functor.{u4, u5, u2, u3} C _inst_2 D _inst_3) [_inst_8 : CategoryTheory.Functor.Additive.{u2, u3, u4, u5} C D _inst_2 _inst_3 _inst_4 _inst_5 F] [_inst_9 : CategoryTheory.Functor.Linear.{u1, u2, u3, u4, u5} R _inst_1 C D _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 _inst_7 F _inst_8] {X : C} {Y : C}, LinearMap.{u1, u1, u4, u5} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (Prefunctor.obj.{succ u4, succ u5, u2, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u4, u5, u2, u3} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u4, succ u5, u2, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u4, u5, u2, u3} C _inst_2 D _inst_3 F) Y)) (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u4, u2} C _inst_2 _inst_4 X Y)) (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (Prefunctor.obj.{succ u4, succ u5, u2, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u4, u5, u2, u3} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u4, succ u5, u2, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u4, u5, u2, u3} C _inst_2 D _inst_3 F) Y)) (CategoryTheory.Preadditive.homGroup.{u5, u3} D _inst_3 _inst_5 (Prefunctor.obj.{succ u4, succ u5, u2, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u4, u5, u2, u3} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u4, succ u5, u2, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u4, u5, u2, u3} C _inst_2 D _inst_3 F) Y))) (CategoryTheory.Linear.homModule.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4 _inst_6 X Y) (CategoryTheory.Linear.homModule.{u1, u5, u3} R _inst_1 D _inst_3 _inst_5 _inst_7 (Prefunctor.obj.{succ u4, succ u5, u2, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u4, u5, u2, u3} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u4, succ u5, u2, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u4, u5, u2, u3} C _inst_2 D _inst_3 F) Y))
Case conversion may be inaccurate. Consider using '#align category_theory.functor.map_linear_map CategoryTheory.Functor.mapLinearMapₓ'. -/
/-- `F.map_linear_map` is an `R`-linear map whose underlying function is `F.map`. -/
@[simps]
def mapLinearMap {X Y : C} : (X ⟶ Y) →ₗ[R] F.obj X ⟶ F.obj Y :=
  { F.mapAddHom with map_smul' := fun r f => F.map_smul r f }
#align category_theory.functor.map_linear_map CategoryTheory.Functor.mapLinearMap

/- warning: category_theory.functor.coe_map_linear_map -> CategoryTheory.Functor.coe_mapLinearMap is a dubious translation:
lean 3 declaration is
  forall (R : Type.{u1}) [_inst_1 : Semiring.{u1} R] {C : Type.{u2}} {D : Type.{u3}} [_inst_2 : CategoryTheory.Category.{u4, u2} C] [_inst_3 : CategoryTheory.Category.{u5, u3} D] [_inst_4 : CategoryTheory.Preadditive.{u4, u2} C _inst_2] [_inst_5 : CategoryTheory.Preadditive.{u5, u3} D _inst_3] [_inst_6 : CategoryTheory.Linear.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4] [_inst_7 : CategoryTheory.Linear.{u1, u5, u3} R _inst_1 D _inst_3 _inst_5] (F : CategoryTheory.Functor.{u4, u5, u2, u3} C _inst_2 D _inst_3) [_inst_8 : CategoryTheory.Functor.Additive.{u2, u3, u4, u5} C D _inst_2 _inst_3 _inst_4 _inst_5 F] [_inst_9 : CategoryTheory.Functor.Linear.{u1, u2, u3, u4, u5} R _inst_1 C D _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 _inst_7 F _inst_8] {X : C} {Y : C}, Eq.{max (succ u4) (succ u5)} ((Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) -> (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y))) (coeFn.{max (succ u4) (succ u5), max (succ u4) (succ u5)} (LinearMap.{u1, u1, u4, u5} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u4, u2} C _inst_2 _inst_4 X Y)) (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (CategoryTheory.Preadditive.homGroup.{u5, u3} D _inst_3 _inst_5 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y))) (CategoryTheory.Linear.homModule.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4 _inst_6 X Y) (CategoryTheory.Linear.homModule.{u1, u5, u3} R _inst_1 D _inst_3 _inst_5 _inst_7 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y))) (fun (_x : LinearMap.{u1, u1, u4, u5} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u4, u2} C _inst_2 _inst_4 X Y)) (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (CategoryTheory.Preadditive.homGroup.{u5, u3} D _inst_3 _inst_5 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y))) (CategoryTheory.Linear.homModule.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4 _inst_6 X Y) (CategoryTheory.Linear.homModule.{u1, u5, u3} R _inst_1 D _inst_3 _inst_5 _inst_7 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y))) => (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) -> (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y))) (LinearMap.hasCoeToFun.{u1, u1, u4, u5} R R (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) _inst_1 _inst_1 (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} C (CategoryTheory.Category.toCategoryStruct.{u4, u2} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u4, u2} C _inst_2 _inst_4 X Y)) (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} D (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} D (CategoryTheory.Category.toCategoryStruct.{u5, u3} D _inst_3)) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (CategoryTheory.Preadditive.homGroup.{u5, u3} D _inst_3 _inst_5 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y))) (CategoryTheory.Linear.homModule.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4 _inst_6 X Y) (CategoryTheory.Linear.homModule.{u1, u5, u3} R _inst_1 D _inst_3 _inst_5 _inst_7 (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X) (CategoryTheory.Functor.obj.{u4, u5, u2, u3} C _inst_2 D _inst_3 F Y)) (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (CategoryTheory.Functor.mapLinearMap.{u1, u2, u3, u4, u5} R _inst_1 C D _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 _inst_7 F _inst_8 _inst_9 X Y)) (CategoryTheory.Functor.map.{u4, u5, u2, u3} C _inst_2 D _inst_3 F X Y)
but is expected to have type
  forall (R : Type.{u1}) [_inst_1 : Semiring.{u1} R] {C : Type.{u3}} {D : Type.{u2}} [_inst_2 : CategoryTheory.Category.{u5, u3} C] [_inst_3 : CategoryTheory.Category.{u4, u2} D] [_inst_4 : CategoryTheory.Preadditive.{u5, u3} C _inst_2] [_inst_5 : CategoryTheory.Preadditive.{u4, u2} D _inst_3] [_inst_6 : CategoryTheory.Linear.{u1, u5, u3} R _inst_1 C _inst_2 _inst_4] [_inst_7 : CategoryTheory.Linear.{u1, u4, u2} R _inst_1 D _inst_3 _inst_5] (F : CategoryTheory.Functor.{u5, u4, u3, u2} C _inst_2 D _inst_3) [_inst_8 : CategoryTheory.Functor.Additive.{u3, u2, u5, u4} C D _inst_2 _inst_3 _inst_4 _inst_5 F] [_inst_9 : CategoryTheory.Functor.Linear.{u1, u3, u2, u5, u4} R _inst_1 C D _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 _inst_7 F _inst_8] {X : C} {Y : C}, Eq.{max (succ u5) (succ u4)} (forall (ᾰ : Quiver.Hom.{succ u5, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) X Y), (fun (x._@.Mathlib.Algebra.Module.LinearMap._hyg.6190 : Quiver.Hom.{succ u5, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) X Y) => Quiver.Hom.{succ u4, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) Y)) ᾰ) (FunLike.coe.{max (succ u5) (succ u4), succ u5, succ u4} (LinearMap.{u1, u1, u5, u4} R R _inst_1 _inst_1 (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1)) (Quiver.Hom.{succ u5, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) X Y) (Quiver.Hom.{succ u4, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) Y)) (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u5, u3} C _inst_2 _inst_4 X Y)) (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) Y)) (CategoryTheory.Preadditive.homGroup.{u4, u2} D _inst_3 _inst_5 (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) Y))) (CategoryTheory.Linear.homModule.{u1, u5, u3} R _inst_1 C _inst_2 _inst_4 _inst_6 X Y) (CategoryTheory.Linear.homModule.{u1, u4, u2} R _inst_1 D _inst_3 _inst_5 _inst_7 (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) Y))) (Quiver.Hom.{succ u5, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) X Y) (fun (_x : Quiver.Hom.{succ u5, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) X Y) => (fun (x._@.Mathlib.Algebra.Module.LinearMap._hyg.6190 : Quiver.Hom.{succ u5, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) X Y) => Quiver.Hom.{succ u4, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) Y)) _x) (LinearMap.instFunLikeLinearMap.{u1, u1, u5, u4} R R (Quiver.Hom.{succ u5, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) X Y) (Quiver.Hom.{succ u4, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) Y)) _inst_1 _inst_1 (AddCommGroup.toAddCommMonoid.{u5} (Quiver.Hom.{succ u5, u3} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) X Y) (CategoryTheory.Preadditive.homGroup.{u5, u3} C _inst_2 _inst_4 X Y)) (AddCommGroup.toAddCommMonoid.{u4} (Quiver.Hom.{succ u4, u2} D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) Y)) (CategoryTheory.Preadditive.homGroup.{u4, u2} D _inst_3 _inst_5 (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) Y))) (CategoryTheory.Linear.homModule.{u1, u5, u3} R _inst_1 C _inst_2 _inst_4 _inst_6 X Y) (CategoryTheory.Linear.homModule.{u1, u4, u2} R _inst_1 D _inst_3 _inst_5 _inst_7 (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X) (Prefunctor.obj.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) Y)) (RingHom.id.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_1))) (CategoryTheory.Functor.mapLinearMap.{u1, u3, u2, u5, u4} R _inst_1 C D _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 _inst_7 F _inst_8 _inst_9 X Y)) (Prefunctor.map.{succ u5, succ u4, u3, u2} C (CategoryTheory.CategoryStruct.toQuiver.{u5, u3} C (CategoryTheory.Category.toCategoryStruct.{u5, u3} C _inst_2)) D (CategoryTheory.CategoryStruct.toQuiver.{u4, u2} D (CategoryTheory.Category.toCategoryStruct.{u4, u2} D _inst_3)) (CategoryTheory.Functor.toPrefunctor.{u5, u4, u3, u2} C _inst_2 D _inst_3 F) X Y)
Case conversion may be inaccurate. Consider using '#align category_theory.functor.coe_map_linear_map CategoryTheory.Functor.coe_mapLinearMapₓ'. -/
theorem coe_mapLinearMap {X Y : C} : ⇑(F.mapLinearMap R : (X ⟶ Y) →ₗ[R] _) = @map C _ D _ F X Y :=
  rfl
#align category_theory.functor.coe_map_linear_map CategoryTheory.Functor.coe_mapLinearMap

end

section InducedCategory

variable {C : Type _} {D : Type _} [Category D] [Preadditive D] [CategoryTheory.Linear R D]
  (F : C → D)

#print CategoryTheory.Functor.inducedFunctorLinear /-
instance inducedFunctorLinear : Functor.Linear R (inducedFunctor F) where
#align category_theory.functor.induced_functor_linear CategoryTheory.Functor.inducedFunctorLinear
-/

end InducedCategory

/- warning: category_theory.functor.full_subcategory_inclusion_linear -> CategoryTheory.Functor.fullSubcategoryInclusionLinear is a dubious translation:
lean 3 declaration is
  forall (R : Type.{u1}) [_inst_1 : Semiring.{u1} R] {C : Type.{u2}} [_inst_2 : CategoryTheory.Category.{u3, u2} C] [_inst_3 : CategoryTheory.Preadditive.{u3, u2} C _inst_2] [_inst_4 : CategoryTheory.Linear.{u1, u3, u2} R _inst_1 C _inst_2 _inst_3] (Z : C -> Prop), CategoryTheory.Functor.Linear.{u1, u2, u2, u3, u3} R _inst_1 (CategoryTheory.FullSubcategoryₓ.{u3, u2} C _inst_2 Z) C (CategoryTheory.InducedCategory.category.{u3, u2, u2} (CategoryTheory.FullSubcategoryₓ.{u3, u2} C _inst_2 Z) C _inst_2 (CategoryTheory.FullSubcategoryₓ.obj.{u3, u2} C _inst_2 Z)) _inst_2 (CategoryTheory.Preadditive.fullSubcategory.{u3, u2} C _inst_2 _inst_3 Z) _inst_3 (CategoryTheory.Linear.fullSubcategory.{u1, u3, u2} C _inst_2 _inst_3 R _inst_1 _inst_4 Z) _inst_4 (CategoryTheory.fullSubcategoryInclusion.{u3, u2} C _inst_2 Z) (CategoryTheory.Functor.fullSubcategoryInclusion_additive.{u2, u3} C _inst_2 _inst_3 Z)
but is expected to have type
  forall (R : Type.{u1}) [_inst_1 : Semiring.{u1} R] {C : Type.{u2}} [_inst_2 : CategoryTheory.Category.{u3, u2} C] [_inst_3 : CategoryTheory.Preadditive.{u3, u2} C _inst_2] [_inst_4 : CategoryTheory.Linear.{u1, u3, u2} R _inst_1 C _inst_2 _inst_3] (Z : C -> Prop), CategoryTheory.Functor.Linear.{u1, u2, u2, u3, u3} R _inst_1 (CategoryTheory.FullSubcategory.{u2} C Z) C (CategoryTheory.FullSubcategory.category.{u3, u2} C _inst_2 Z) _inst_2 (CategoryTheory.Preadditive.fullSubcategory.{u3, u2} C _inst_2 _inst_3 Z) _inst_3 (CategoryTheory.Linear.fullSubcategory.{u1, u3, u2} C _inst_2 _inst_3 R _inst_1 _inst_4 Z) _inst_4 (CategoryTheory.fullSubcategoryInclusion.{u3, u2} C _inst_2 Z) (CategoryTheory.Functor.fullSubcategoryInclusion_additive.{u2, u3} C _inst_2 _inst_3 Z)
Case conversion may be inaccurate. Consider using '#align category_theory.functor.full_subcategory_inclusion_linear CategoryTheory.Functor.fullSubcategoryInclusionLinearₓ'. -/
instance fullSubcategoryInclusionLinear {C : Type _} [Category C] [Preadditive C]
    [CategoryTheory.Linear R C] (Z : C → Prop) : (fullSubcategoryInclusion Z).Linear R where
#align category_theory.functor.full_subcategory_inclusion_linear CategoryTheory.Functor.fullSubcategoryInclusionLinear

section

variable {R} {C D : Type _} [Category C] [Category D] [Preadditive C] [Preadditive D] (F : C ⥤ D)
  [Additive F]

#print CategoryTheory.Functor.natLinear /-
instance natLinear : F.Linear ℕ where map_smul' X Y f r := F.mapAddHom.map_nsmul f r
#align category_theory.functor.nat_linear CategoryTheory.Functor.natLinear
-/

/- warning: category_theory.functor.int_linear -> CategoryTheory.Functor.intLinear is a dubious translation:
lean 3 declaration is
  forall {C : Type.{u1}} {D : Type.{u2}} [_inst_2 : CategoryTheory.Category.{u3, u1} C] [_inst_3 : CategoryTheory.Category.{u4, u2} D] [_inst_4 : CategoryTheory.Preadditive.{u3, u1} C _inst_2] [_inst_5 : CategoryTheory.Preadditive.{u4, u2} D _inst_3] (F : CategoryTheory.Functor.{u3, u4, u1, u2} C _inst_2 D _inst_3) [_inst_6 : CategoryTheory.Functor.Additive.{u1, u2, u3, u4} C D _inst_2 _inst_3 _inst_4 _inst_5 F], CategoryTheory.Functor.Linear.{0, u1, u2, u3, u4} Int Int.semiring C D _inst_2 _inst_3 _inst_4 _inst_5 (CategoryTheory.Linear.preadditiveIntLinear.{u3, u1} C _inst_2 _inst_4) (CategoryTheory.Linear.preadditiveIntLinear.{u4, u2} D _inst_3 _inst_5) F _inst_6
but is expected to have type
  forall {C : Type.{u1}} {D : Type.{u2}} [_inst_2 : CategoryTheory.Category.{u3, u1} C] [_inst_3 : CategoryTheory.Category.{u4, u2} D] [_inst_4 : CategoryTheory.Preadditive.{u3, u1} C _inst_2] [_inst_5 : CategoryTheory.Preadditive.{u4, u2} D _inst_3] (F : CategoryTheory.Functor.{u3, u4, u1, u2} C _inst_2 D _inst_3) [_inst_6 : CategoryTheory.Functor.Additive.{u1, u2, u3, u4} C D _inst_2 _inst_3 _inst_4 _inst_5 F], CategoryTheory.Functor.Linear.{0, u1, u2, u3, u4} Int Int.instSemiringInt C D _inst_2 _inst_3 _inst_4 _inst_5 (CategoryTheory.Linear.preadditiveIntLinear.{u3, u1} C _inst_2 _inst_4) (CategoryTheory.Linear.preadditiveIntLinear.{u4, u2} D _inst_3 _inst_5) F _inst_6
Case conversion may be inaccurate. Consider using '#align category_theory.functor.int_linear CategoryTheory.Functor.intLinearₓ'. -/
instance intLinear : F.Linear ℤ
    where map_smul' X Y f r := (F.mapAddHom : (X ⟶ Y) →+ (F.obj X ⟶ F.obj Y)).map_zsmul f r
#align category_theory.functor.int_linear CategoryTheory.Functor.intLinear

variable [CategoryTheory.Linear ℚ C] [CategoryTheory.Linear ℚ D]

#print CategoryTheory.Functor.ratLinear /-
instance ratLinear : F.Linear ℚ where map_smul' X Y f r := F.mapAddHom.toRatLinearMap.map_smul r f
#align category_theory.functor.rat_linear CategoryTheory.Functor.ratLinear
-/

end

end Functor

namespace Equivalence

variable {C D : Type _} [Category C] [Category D] [Preadditive C] [Linear R C] [Preadditive D]
  [Linear R D]

/- warning: category_theory.equivalence.inverse_linear -> CategoryTheory.Equivalence.inverseLinear is a dubious translation:
lean 3 declaration is
  forall (R : Type.{u1}) [_inst_1 : Semiring.{u1} R] {C : Type.{u2}} {D : Type.{u3}} [_inst_2 : CategoryTheory.Category.{u4, u2} C] [_inst_3 : CategoryTheory.Category.{u5, u3} D] [_inst_4 : CategoryTheory.Preadditive.{u4, u2} C _inst_2] [_inst_5 : CategoryTheory.Linear.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4] [_inst_6 : CategoryTheory.Preadditive.{u5, u3} D _inst_3] [_inst_7 : CategoryTheory.Linear.{u1, u5, u3} R _inst_1 D _inst_3 _inst_6] (e : CategoryTheory.Equivalence.{u4, u5, u2, u3} C _inst_2 D _inst_3) [_inst_8 : CategoryTheory.Functor.Additive.{u2, u3, u4, u5} C D _inst_2 _inst_3 _inst_4 _inst_6 (CategoryTheory.Equivalence.functor.{u4, u5, u2, u3} C _inst_2 D _inst_3 e)] [_inst_9 : CategoryTheory.Functor.Linear.{u1, u2, u3, u4, u5} R _inst_1 C D _inst_2 _inst_3 _inst_4 _inst_6 _inst_5 _inst_7 (CategoryTheory.Equivalence.functor.{u4, u5, u2, u3} C _inst_2 D _inst_3 e) _inst_8], CategoryTheory.Functor.Linear.{u1, u3, u2, u5, u4} R _inst_1 D C _inst_3 _inst_2 _inst_6 _inst_4 _inst_7 _inst_5 (CategoryTheory.Equivalence.inverse.{u4, u5, u2, u3} C _inst_2 D _inst_3 e) (CategoryTheory.Equivalence.inverse_additive.{u2, u3, u4, u5} C D _inst_2 _inst_3 _inst_4 _inst_6 e _inst_8)
but is expected to have type
  forall (R : Type.{u1}) [_inst_1 : Semiring.{u1} R] {C : Type.{u2}} {D : Type.{u3}} [_inst_2 : CategoryTheory.Category.{u4, u2} C] [_inst_3 : CategoryTheory.Category.{u5, u3} D] [_inst_4 : CategoryTheory.Preadditive.{u4, u2} C _inst_2] [_inst_5 : CategoryTheory.Linear.{u1, u4, u2} R _inst_1 C _inst_2 _inst_4] [_inst_6 : CategoryTheory.Preadditive.{u5, u3} D _inst_3] [_inst_7 : CategoryTheory.Linear.{u1, u5, u3} R _inst_1 D _inst_3 _inst_6] (e : CategoryTheory.Equivalence.{u4, u5, u2, u3} C D _inst_2 _inst_3) [_inst_8 : CategoryTheory.Functor.Additive.{u2, u3, u4, u5} C D _inst_2 _inst_3 _inst_4 _inst_6 (CategoryTheory.Equivalence.functor.{u4, u5, u2, u3} C D _inst_2 _inst_3 e)] [_inst_9 : CategoryTheory.Functor.Linear.{u1, u2, u3, u4, u5} R _inst_1 C D _inst_2 _inst_3 _inst_4 _inst_6 _inst_5 _inst_7 (CategoryTheory.Equivalence.functor.{u4, u5, u2, u3} C D _inst_2 _inst_3 e) _inst_8], CategoryTheory.Functor.Linear.{u1, u3, u2, u5, u4} R _inst_1 D C _inst_3 _inst_2 _inst_6 _inst_4 _inst_7 _inst_5 (CategoryTheory.Equivalence.inverse.{u4, u5, u2, u3} C D _inst_2 _inst_3 e) (CategoryTheory.Equivalence.inverse_additive.{u2, u3, u4, u5} C D _inst_2 _inst_3 _inst_4 _inst_6 e _inst_8)
Case conversion may be inaccurate. Consider using '#align category_theory.equivalence.inverse_linear CategoryTheory.Equivalence.inverseLinearₓ'. -/
instance inverseLinear (e : C ≌ D) [e.Functor.Additive] [e.Functor.Linear R] : e.inverse.Linear R
    where map_smul' X Y r f := by
    apply e.functor.map_injective
    simp
#align category_theory.equivalence.inverse_linear CategoryTheory.Equivalence.inverseLinear

end Equivalence

end Linear

end CategoryTheory


import syntax.consistency
import syntax.CLLemmas
import semantics.model
import tactic.induction

local attribute [instance] classical.prop_decidable

open set list

----------------------------------------------------------
-- Set Helper Functions
----------------------------------------------------------
def union_neq_univ_left {α : Type} {A B : set α} (h : A ∪ B ⊂ univ) :
  A ≠ univ :=
ne_of_ssubset (ssubset_of_subset_of_ssubset (subset_union_left A B) h)

def union_neq_univ_right {α : Type} {A B : set α} (h : A ∪ B ⊂ univ) :
  B ≠ univ :=
ne_of_ssubset (ssubset_of_subset_of_ssubset (subset_union_right A B) h)

----------------------------------------------------------
-- Canonical Frame Defintions and Lemmas
----------------------------------------------------------
namespace canonical

-- Define States
----------------------------------------------------------
-- S is the set of all maximal CL-consistent set of formulas
def states (form : Type) [pf : Pformula form] [pax : Pformula_ax form] :=
{Γ : (set (form)) // (max_ax_consistent Γ)}

/-- Allows us to write `φ ∈ s` instead of `φ ∈ s.val` -/
instance states.set_like {form : Type} [pf : Pformula form] [pax : Pformula_ax form] :
  set_like (states form) form :=
{ coe := λ s, s.1,
  coe_injective' := subtype.coe_injective }

-- Tilde
def tilde {form : Type} [pf : Pformula form] [pax : Pformula_ax form]
  (states : Type) [sl : set_like states form] (φ : form) : set states :=
{s : states | φ ∈ s}

lemma h_tilde_compl {form : Type} [pf : Pformula form] [pax : Pformula_ax form]
  (states : Type) [sl : set_like states form] (φ : form) :
  tilde states (¬' φ) = (tilde states φ)ᶜ :=
begin
  ext s,
  unfold tilde,
  split,
  { intros hx hf,
    apply contra_containts_pr_false,
    exact contra_containts_pr_false x.2 hf hx, },
  { intros hx,
    exact not_in_from_notin x.2 hx, },
end

-- States is not empty
----------------------------------------------------------
lemma hs (form : Type) [pf : Pformula form] [pax : Pformula_ax form]
  (hnpr : ¬ ⊢' (⊥': form )) : nonempty (states form) :=
begin
  -- Any consistent set Σ (eg{⊤}) can be extended to the maximally CL-consistent
  -- set of formulas Σ′ ⊇ Σ,by Lindenbaum’s lemma
  unfold states,
  rw nonempty_subtype,
  exact max_ax_exists hnpr,
end

-- Define E
----------------------------------------------------------
def E {agents form : Type}
  [pf : Pformula form] [pax : Pformula_ax form] [clf : CLformula agents form]
  (s : states form) (G : set agents) :=
{X | ite (G = univ)
-- condition G = N
--  X ∈ E(s)(N) iff ∀φ˜ ⊆ Xᶜ : [∅]φ /∈ s, where φ˜ := {t ∈ S| φ ∈ t}, and Xᶜ := S\X
(∀ φ, {t : (states form) | φ ∈ (t.val)} ⊆ Xᶜ → (['∅] φ) ∉ s.val)
-- condition G ≠ N
--  When G ≠ N : X ∈ E(s)(G) iff ∃φ˜ ⊆ X : [G]φ ∈ s
(∃ φ, {t : (states form) | φ ∈ (t.val)} ⊆ X ∧ (['G] φ) ∈ s.val)}

-- Semi-liveness
----------------------------------------------------------
lemma semi_liveness {agents form : Type}
  [pf : Pformula form] [pax : Pformula_ax form] [clf : CLformula agents form]
  (s : states form) {G : set agents} (hG : G ⊂ univ) : ∅ ∉ E (s) (G) :=
begin
-- Let G ⊂ N. Assume towards contradiction that ∅ ∈ E(s)(G)
  unfold E,
  intros hf,
  --  ∃φ˜ ⊆ ∅ : [G]φ ∈ s, from hf, by definition EC
  simp [ne_of_ssubset hG] at hf,

  -- ⊢ φ ↔ ⊥, because {φ} cannot be extended into a maximally
  -- consistent set (by hf), so {φ} must be inconsistent.
  cases hf with φ hφ,
  have hiffbot : ⊢' (φ ↔' ⊥'), from set_empty_iff_false hφ.left,

  -- ⊢ [G]φ ↔ [G]⊥, from hiffbot, by axiom (Eq)
  have hiffGbot : ⊢' ((['G] φ) ↔' (['G] ⊥')), from Eq _ _ _ hiffbot,
    -- simp at *,

  -- [G]⊥ ∈ s, from 2.1.5 and 2.1.3.
  have h : (['G] ⊥') ∈ s.1,
    from max_ax_contains_by_set_proof s.2 hφ.right (iff_l hiffGbot),

  -- Contradiction from axiom (⊥) : ¬[G]⊥ and h
  apply ax_neg_containts_pr_false s.2 h (Bot _),
end

-- Semi-safety
----------------------------------------------------------
lemma semi_safety {agents form : Type}
  [pf : Pformula form] [pax : Pformula_ax form] [clf : CLformula agents form]
  (s : states form) {G : set agents} (hG : G ⊂ univ) : univ ∈ E (s) (G) :=
begin
  -- Let G ⊂ N
  unfold E,
  have hG' : G ≠ univ, from ne_of_ssubset hG,
  simp [hG'] at *,
  clear hG',

  --  [G]⊤ ∈ s and ⊤˜ = S, from axiom (⊤) : [G]⊤, and definition S
  have hT : (['G] ⊤') ∈ s.val,
    from max_ax_contains_taut s.2 (Top _),

  --  ∃φ˜ ⊆ S : [G]φ ∈ s, where φ = ⊤ from hTop
  apply exists.intro (⊤' : form),
  exact hT,
end

-- Semi-monotonicity
----------------------------------------------------------
lemma semi_mono {agents form : Type}
  [pf : Pformula form] [pax : Pformula_ax form] [clf : CLformula agents form]
  (s : states form) {G : set agents} {X Y : set (states form)}
  (hG : G ⊂ univ) (hXY : X ⊆ Y) (hX : X ∈ E (s) (G)) : Y ∈ E (s) (G) :=
begin
  unfold E at *,
  -- Let G ⊂ N and X ⊆ Y ⊆ S, where X ∈ E(s)(G)
  -- ∃φ˜ ⊆ X : [G]φ ∈ s, from hX, by definition EC
  have hG' : G ≠ univ, from ne_of_ssubset hG,
  simp [hG'] at *,
  clear hG',

  -- φ ⊆ Y : [G]φ ∈ s, because ˜φ ⊆ X ⊆ Y
  cases hX with φ hφ,
  apply exists.intro φ,
  split,
  { exact subset.trans hφ.left hXY, },
  { exact hφ.right, },
end

-- Semi-superadditivity
----------------------------------------------------------
lemma semi_superadd {agents form : Type}
  [pf : Pformula form] [pax : Pformula_ax form] [clf : CLformula agents form]
  (s : states form) {G F : set agents} {X Y : set (states form)}
  (hunion : G ∪ F ⊂ univ) (hX : X ∈ E (s) (G)) (hY : Y ∈ E (s) (F)) (hintGF : G ∩ F = ∅) :
  X ∩ Y ∈ E (s) (G ∪ F) :=
begin
  unfold E at *,
  -- Let G, F ⊆ N (where G ∩ F = ∅ and G ∪ F ⊂ N) and X, Y ⊆ S,
  -- where X ∈ E(s)(G) and Y ∈ E(s)(F)
  -- ∃φ˜ ⊆ X and ∃ψ˜ ⊆ Y , such that [G]φ ∈ s and [F]ψ ∈ s, from 2.4.1, by definition EC
  have hunion' : G ∪ F ≠ univ, from ne_of_ssubset hunion,
  simp [hunion', union_neq_univ_left hunion, union_neq_univ_right hunion] at *,
  clear hunion',
  cases hX with φ, cases hY with ψ,
  apply exists.intro (φ ∧' ψ),

  -- [G∪F](φ ∧ ψ) ∈ s, from hX_h.right and hY_h.right,
  -- by axiom (S) : ([G]φ∧[F]ψ) → [G ∪ F](φ ∧ ψ)
  have hand : ((['G] φ) ∧' (['F] ψ)) ∈ s.1,
    from max_ax_contains_by_set_proof_2h s.2 hX_h.right hY_h.right (p4 _ _),
  have hunionand : ((['(G ∪ F)] (φ ∧' ψ)) ∈ s.1),
    from max_ax_contains_by_set_proof s.2 hand ((S _ _ _ _) hintGF),

  -- (φ ∧ ψ)˜ ⊆ X ∩ Y : [G ∪ F](φ ∧ ψ) ∈ s, from hX_h.left and hY_h.left and hunionand
  split,
  { split,
    { have hsubset : {t : (states form) | φ ∧' ψ ∈ t.val} ⊆ {t : (states form) | φ ∈ t.val}, from
      begin
        rw set.subset_def,
        intros t ht, simp at *,
        exact max_ax_contains_by_set_proof t.2 ht (p5 _ _),
      end,
      exact subset.trans hsubset hX_h.left, },
    { have hsubset : {t : (states form) | φ ∧' ψ ∈ t.val} ⊆ {t : (states form) | ψ ∈ t.val}, from
      begin
        rw set.subset_def,
        intros t ht, simp at *,
        exact max_ax_contains_by_set_proof t.2 ht (p6 _ _),
      end,
      exact subset.trans hsubset hY_h.left, }, },
  { exact hunionand, },
end

-- Regularity
----------------------------------------------------------
lemma regularity {agents form : Type} [ha : nonempty agents]
  [pf : Pformula form] [pax : Pformula_ax form] [clf : CLformula agents form]
  (s : states form) {G : set agents} {X : set (states form)}
  (h : X ∈ E (s) (G)) : (Xᶜ ∉ E (s) (Gᶜ)) :=
begin
  unfold E at *,
  cases eq_or_ssubset_of_subset (subset_univ G),
  { -- case : G = N
    -- by definition E and first order logic
    simp [h_1, (ne_of_ssubset (empty_subset_univ ha))] at *,
    exact h, },

  { cases em (G = ∅),

    { -- case : G = ∅
      -- by definition E and first order logic
      simp [(ne_of_ssubset h_1), h_2, (ne_of_ssubset (empty_subset_univ ha))] at *,
      exact h, },

    { -- case : G ̸= N and G ̸= N :
      -- Let X ⊆ S, where X ∈ E(s)(G). ∃φ˜ ⊆ X : [G]φ ∈ s, by definition EC
      simp [(ne_of_ssubset h_1), h_2] at *,
      cases h with φ h, cases h,
      intros ψ hψ,

      -- Assume by contradiction that Xᶜ ∈ E(s)(Gᶜ)
      by_contradiction hf,

      -- [G ∪ Gᶜ = N](φ ∧ ψ) ∈ s, from h_right and hf,
      -- by axiom S [G]φ ∧ [Gᶜ]ψ → [G ∪ Gᶜ = N](φ ∧ ψ) ∈ s
      have hS : (['(G ∪ Gᶜ)] (φ ∧' ψ)) ∈ s.val,

      { have hand : ((['G] φ) ∧' (['Gᶜ] ψ)) ∈ s.1,
        from max_ax_contains_by_set_proof_2h s.2 h_right hf (p4 _ _),
        apply max_ax_contains_by_set_proof s.2 hand,
        apply (S _ _ _ _),
        simp, },
      simp at hS,

      -- (φ ∧ ψ)˜ = ∅, because X and Xᶜ are disjoint, meaning φ˜ and ψ˜ are disjoint
      have hemptyint : {t : (states form) | (φ ∈ t.val)} ∩ {t : (states form) | (ψ ∈ t.val)} = ∅, from
        begin
          rw set.eq_empty_iff_forall_not_mem,
          intros t hf,
          rw set.subset_def at *,
          cases em (t ∈ X),

          { simp at hψ hf,
            apply hψ,
            exact hf.right,
            exact h, },

          { apply h,
            apply h_left t hf.left, },
        end,
      have hempty : {t : (states form) | (φ ∧' ψ ∈ t.val)} ⊆ ∅,

      { intros t hf',
        simp[set.subset_empty_iff, set.eq_empty_iff_forall_not_mem] at hf',
        have hφ : φ ∈ t.1, from max_ax_contains_by_set_proof t.2 hf' (p5 _ _),
        have hψ : ψ ∈ t.1, from max_ax_contains_by_set_proof t.2 hf' (p6 _ _),
        rw set.eq_empty_iff_forall_not_mem at hemptyint,
        apply hemptyint t,
        simp,
        split, exact hφ, exact hψ, },

      -- ⊢ (φ ∧ ψ) ↔ ⊥, because {(φ ∧ ψ)} cannot be extended into
      -- a maximally consistent set (by 3.3.6), so {(φ ∧ ψ)} must be inconsistent.
      have hiffbot : ⊢' ((φ ∧' ψ) ↔' ⊥'), from set_empty_iff_false hempty,

      -- ⊢ [N](φ ∧ ψ) ↔ [N]⊥, from 3.3.7, by axiom (Eq)
      have hiffNbot : ⊢' ((['univ] (φ ∧' ψ)) ↔' (['univ] ⊥')),
        from (Eq _ _ _) hiffbot,
      simp at *,

      -- [N]⊥ ∈ s, from 3.3.7 and 3.3.5.
      have h : (['univ] ⊥') ∈ s.1, from
      begin
        apply max_ax_contains_by_set_proof s.2 hS,
        apply iff_l,
        simp only [ax_and] at *,
        apply hiffNbot,
      end,

      -- Contradiction from axiom (⊥) : ¬[N]⊥ and 3.3.8
      exact ax_neg_containts_pr_false s.2 h (Bot _), }, },
end

-- N maximality
----------------------------------------------------------
lemma N_maximality {agents form : Type} [ha : nonempty agents]
  [pf : Pformula form] [pax : Pformula_ax form] [clf : CLformula agents form]
  (s : states form) {X : set (states form)}
  (h : Xᶜ ∉ E (s) (∅)) : X ∈ E (s) (univ) :=
begin
  unfold E at *,
  simp [(ne_of_ssubset (empty_subset_univ ha))] at *,
  intros φ hX,
  exact h φ hX,
end

----------------------------------------------------------
-- Canonical Frame Constructions
----------------------------------------------------------

@[simps?] def canonicalCL (agents form : Type) [ha : nonempty agents]
 [pf : Pformula form] [pax : Pformula_ax form] [clf : CLformula agents form]
 (hnpr : ¬ ⊢' ⊥') : frameCL agents :=
{ states := states form,
  hs := hs form hnpr,
  -- E is a playable Effectivity Function
  E :=
    begin
      --  Showing that an effectivity function E(s) is semi-playable,
      -- regular and N-maximal, suffices to prove that E(s) is playable
      let semi : semi_playable_effectivity_struct agents (states form) :=
      { E             := E,
        semi_liveness := semi_liveness,
        semi_safety   := semi_safety,
        semi_mono     := semi_mono,
        semi_superadd := semi_superadd, },

      exact playable_from_semi_Nmax_reg (states form) semi N_maximality regularity,
    end, }

def canonical_model_CL (agents form : Type) [ha : nonempty agents]
 [pf : Pformula form] [pax : Pformula_ax form] [clf : CLformula agents form]
 (hnpr : ¬ ⊢' (⊥' : form)) : modelCL agents :=
{ f := canonicalCL agents form hnpr,
  -- V is as usual, such that s ∈ V (p) iff p ∈ s
  v := λ  n, {s | (Pformula.var n) ∈ s.1} }

@[simps?] def canonical_CLK {agents : Type} (form : Type)
  [ha : nonempty agents] [hN : fintype agents]
  [pf : Pformula form] [pax : Pformula_ax form]
  [clf : CLformula agents form] [kf: Kformula agents form]
  (hnpr : ¬ ⊢' (⊥' : form)) : frameCLK agents :=
{ rel := λ i : agents, λ s, {t | {φ | K' (i) (φ) ∈ s.1} = {φ | K' (i) (φ) ∈ t.1}},
  rfl := by simp,
  sym := λ i s t ht, eq.symm ht,
  trans := λ i s t u hst htu, (rfl.congr htu).mp hst,
  .. canonicalCL agents form hnpr }

end canonical


--import mathlib.tactic.basic
--import mathlib.tactic.cases
--import mathlib.init.data.nat.basic
import tactic.induction
import data.set.basic
import logic.equiv.basic
import data.nat

#eval 123 -- and more

#eval lean.version

lemma min_add_add (l m n : ℕ) :
min (m + l) (n + l) = min m n + l :=
begin
  cases' classical.em (m ≤ n),
  case inl {
    simp [min, h] },
  case inr {
    simp [min, h] }
end


/-
Copyright (c) 2018 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro
-/
import tactic.norm_num

/-!
# The `abel` tactic

Evaluate expressions in the language of additive, commutative monoids and groups.

-/

namespace tactic
namespace abel

/-- The `context` for a call to `abel`.

Stores a few options for this call, and caches some common subexpressions
such as typeclass instances and `0 : α`.
-/
meta structure context :=
(red : transparency)
(α : expr)
(univ : level)
(α0 : expr)
(is_group : bool)
(inst : expr)

/-- Populate a `context` object for evaluating `e`, up to reducibility level `red`. -/
meta def mk_context (red : transparency) (e : expr) : tactic context :=
do α ← infer_type e,
   c ← mk_app ``add_comm_monoid [α] >>= mk_instance,
   cg ← try_core (mk_app ``add_comm_group [α] >>= mk_instance),
   u ← mk_meta_univ,
   infer_type α >>= unify (expr.sort (level.succ u)),
   u ← get_univ_assignment u,
   α0 ← expr.of_nat α 0,
   match cg with
   | (some cg) := return ⟨red, α, u, α0, tt, cg⟩
   | _ := return ⟨red, α, u, α0, ff, c⟩
   end

/-- Apply the function `n : ∀ {α} [inst : add_whatever α], _` to the
implicit parameters in the context, and the given list of arguments. -/
meta def context.app (c : context) (n : name) (inst : expr) : list expr → expr :=
(@expr.const tt n [c.univ] c.α inst).mk_app

/-- Apply the function `n : ∀ {α} [inst α], _` to the implicit parameters in the
context, and the given list of arguments.

Compared to `context.app`, this takes the name of the typeclass, rather than an
inferred typeclass instance.
-/
meta def context.mk_app (c : context) (n inst : name) (l : list expr) : tactic expr :=
do m ← mk_instance ((expr.const inst [c.univ] : expr) c.α), return $ c.app n m l

/-- Add the letter "g" to the end of the name, e.g. turning `term` into `termg`.

This is used to choose between declarations taking `add_comm_monoid` and those
taking `add_comm_group` instances.
-/
meta def add_g : name → name
| (name.mk_string s p) := name.mk_string (s ++ "g") p
| n := n

/-- Apply the function `n : ∀ {α} [add_comm_{monoid,group} α]` to the given
list of arguments.

Will use the `add_comm_{monoid,group}` instance that has been cached in the context.
-/
meta def context.iapp (c : context) (n : name) : list expr → expr :=
c.app (if c.is_group then add_g n else n) c.inst

def term {α} [add_comm_monoid α] (n : ℕ) (x a : α) : α := n • x + a
def termg {α} [add_comm_group α] (n : ℤ) (x a : α) : α := n • x + a

/-- Evaluate a term with coefficient `n`, atom `x` and successor terms `a`. -/
meta def context.mk_term (c : context) (n x a : expr) : expr := c.iapp ``term [n, x, a]

/-- Interpret an integer as a coefficient to a term. -/
meta def context.int_to_expr (c : context) (n : ℤ) : tactic expr :=
expr.of_int (if c.is_group then `(ℤ) else `(ℕ)) n

meta inductive normal_expr : Type
| zero (e : expr) : normal_expr
| nterm (e : expr) (n : expr × ℤ) (x : expr) (a : normal_expr) : normal_expr

meta def normal_expr.e : normal_expr → expr
| (normal_expr.zero e) := e
| (normal_expr.nterm e _ _ _) := e

meta instance : has_coe normal_expr expr := ⟨normal_expr.e⟩
meta instance : has_coe_to_fun normal_expr (λ _, expr → expr) := ⟨λ e, ⇑(e : expr)⟩

meta def normal_expr.term' (c : context) (n : expr × ℤ) (x : expr) (a : normal_expr) :
  normal_expr :=
normal_expr.nterm (c.mk_term n.1 x a) n x a

meta def normal_expr.zero' (c : context) : normal_expr := normal_expr.zero c.α0

meta def normal_expr.to_list : normal_expr → list (ℤ × expr)
| (normal_expr.zero _) := []
| (normal_expr.nterm _ (_, n) x a) := (n, x) :: a.to_list

open normal_expr

meta def normal_expr.to_string (e : normal_expr) : string :=
" + ".intercalate $ (to_list e).map $
λ ⟨n, e⟩, to_string n ++ " • (" ++ to_string e ++ ")"

meta def normal_expr.pp (e : normal_expr) : tactic format :=
do l ← (to_list e).mmap (λ ⟨n, e⟩, do
  pe ← pp e, return (to_fmt n ++ " • (" ++ pe ++ ")")),
  return $ format.join $ l.intersperse ↑" + "

meta instance : has_to_tactic_format normal_expr := ⟨normal_expr.pp⟩

meta def normal_expr.refl_conv (e : normal_expr) : tactic (normal_expr × expr) :=
do p ← mk_eq_refl e, return (e, p)

theorem const_add_term {α} [add_comm_monoid α] (k n x a a') (h : k + a = a') :
  k + @term α _ n x a = term n x a' := by simp [h.symm, term]; ac_refl

theorem term_add_const {α} [add_comm_monoid α] (n x a k a') (h : a + k = a') :
  @term α _ n x a + k = term n x a' := by simp [h.symm, term, add_assoc]

theorem term_add_constg {α} [add_comm_group α] (n x a k a') (h : a + k = a') :
  @termg α _ n x a + k = termg n x a' := by simp [h.symm, termg, add_assoc]

theorem term_add_term {α} [add_comm_monoid α] (n₁ x a₁ n₂ a₂ n' a')
  (h₁ : n₁ + n₂ = n') (h₂ : a₁ + a₂ = a') :
  @term α _ n₁ x a₁ + @term α _ n₂ x a₂ = term n' x a' :=
by simp [h₁.symm, h₂.symm, term, add_nsmul]; ac_refl

theorem term_add_termg {α} [add_comm_group α] (n₁ x a₁ n₂ a₂ n' a')
  (h₁ : n₁ + n₂ = n') (h₂ : a₁ + a₂ = a') :
  @termg α _ n₁ x a₁ + @termg α _ n₂ x a₂ = termg n' x a' :=
by simp [h₁.symm, h₂.symm, termg, add_zsmul]; ac_refl

theorem zero_term {α} [add_comm_monoid α] (x a) : @term α _ 0 x a = a :=
by simp [term, zero_nsmul, one_nsmul]

theorem zero_termg {α} [add_comm_group α] (x a) : @termg α _ 0 x a = a :=
by simp [termg]

meta def eval_add (c : context) : normal_expr → normal_expr → tactic (normal_expr × expr)
| (zero _) e₂ := do
  p ← mk_app ``zero_add [e₂],
  return (e₂, p)
| e₁ (zero _) := do
  p ← mk_app ``add_zero [e₁],
  return (e₁, p)
| he₁@(nterm e₁ n₁ x₁ a₁) he₂@(nterm e₂ n₂ x₂ a₂) :=
  (do
    is_def_eq x₁ x₂ c.red,
    (n', h₁) ← mk_app ``has_add.add [n₁.1, n₂.1] >>= norm_num.eval_field,
    (a', h₂) ← eval_add a₁ a₂,
    let k := n₁.2 + n₂.2,
    let p₁ := c.iapp ``term_add_term [n₁.1, x₁, a₁, n₂.1, a₂, n', a', h₁, h₂],
    if k = 0 then do
      p ← mk_eq_trans p₁ (c.iapp ``zero_term [x₁, a']),
      return (a', p)
    else return (term' c (n', k) x₁ a', p₁))
  <|> if expr.lex_lt x₁ x₂ then do
    (a', h) ← eval_add a₁ he₂,
    return (term' c n₁ x₁ a', c.iapp ``term_add_const [n₁.1, x₁, a₁, e₂, a', h])
  else do
    (a', h) ← eval_add he₁ a₂,
    return (term' c n₂ x₂ a', c.iapp ``const_add_term [e₁, n₂.1, x₂, a₂, a', h])

theorem term_neg {α} [add_comm_group α] (n x a n' a')
  (h₁ : -n = n') (h₂ : -a = a') :
  -@termg α _ n x a = termg n' x a' :=
by simp [h₂.symm, h₁.symm, termg]; ac_refl

meta def eval_neg (c : context) : normal_expr → tactic (normal_expr × expr)
| (zero e) := do
  p ← c.mk_app ``neg_zero ``neg_zero_class [],
  return (zero' c, p)
| (nterm e n x a) := do
  (n', h₁) ← mk_app ``has_neg.neg [n.1] >>= norm_num.eval_field,
  (a', h₂) ← eval_neg a,
  return (term' c (n', -n.2) x a',
    c.app ``term_neg c.inst [n.1, x, a, n', a', h₁, h₂])

def nat_smul_inst {α} [add_comm_monoid α] : has_smul ℕ α := by apply_instance
def nat_smul_instg {α} [add_comm_group α] : has_smul ℕ α := by apply_instance
def int_smul_instg {α} [add_comm_group α] : has_smul ℤ α := by apply_instance

def smul {α} [add_comm_monoid α] (n : ℕ) (x : α) : α := n • x
def smulg {α} [add_comm_group α] (n : ℤ) (x : α) : α := n • x

theorem zero_smul {α} [add_comm_monoid α] (c) : smul c (0 : α) = 0 :=
by simp [smul, nsmul_zero]

theorem zero_smulg {α} [add_comm_group α] (c) : smulg c (0 : α) = 0 :=
by simp [smulg, zsmul_zero]

theorem term_smul {α} [add_comm_monoid α] (c n x a n' a')
  (h₁ : c * n = n') (h₂ : smul c a = a') :
  smul c (@term α _ n x a) = term n' x a' :=
by simp [h₂.symm, h₁.symm, term, smul, nsmul_add, mul_nsmul]

theorem term_smulg {α} [add_comm_group α] (c n x a n' a')
  (h₁ : c * n = n') (h₂ : smulg c a = a') :
  smulg c (@termg α _ n x a) = termg n' x a' :=
by simp [h₂.symm, h₁.symm, termg, smulg, zsmul_add, mul_zsmul]

meta def eval_smul (c : context) (k : expr × ℤ) :
  normal_expr → tactic (normal_expr × expr)
| (zero _) := return (zero' c, c.iapp ``zero_smul [k.1])
| (nterm e n x a) := do
  (n', h₁) ← mk_app ``has_mul.mul [k.1, n.1] >>= norm_num.eval_field,
  (a', h₂) ← eval_smul a,
  return (term' c (n', k.2 * n.2) x a',
    c.iapp ``term_smul [k.1, n.1, x, a, n', a', h₁, h₂])

theorem term_atom {α} [add_comm_monoid α] (x : α) : x = term 1 x 0 :=
by simp [term]

theorem term_atomg {α} [add_comm_group α] (x : α) : x = termg 1 x 0 :=
by simp [termg]

meta def eval_atom (c : context) (e : expr) : tactic (normal_expr × expr) :=
do n1 ← c.int_to_expr 1,
   return (term' c (n1, 1) e (zero' c), c.iapp ``term_atom [e])

lemma unfold_sub {α} [subtraction_monoid α] (a b c : α) (h : a + -b = c) : a - b = c :=
by rw [sub_eq_add_neg, h]

theorem unfold_smul {α} [add_comm_monoid α] (n) (x y : α)
  (h : smul n x = y) : n • x = y := h

theorem unfold_smulg {α} [add_comm_group α] (n : ℕ) (x y : α)
  (h : smulg (int.of_nat n) x = y) : (n : ℤ) • x = y := h

theorem unfold_zsmul {α} [add_comm_group α] (n : ℤ) (x y : α)
  (h : smulg n x = y) : n • x = y := h

lemma subst_into_smul {α} [add_comm_monoid α]
  (l r tl tr t) (prl : l = tl) (prr : r = tr)
  (prt : @smul α _ tl tr = t) : smul l r = t :=
by simp [prl, prr, prt]

lemma subst_into_smulg {α} [add_comm_group α]
  (l r tl tr t) (prl : l = tl) (prr : r = tr)
  (prt : @smulg α _ tl tr = t) : smulg l r = t :=
by simp [prl, prr, prt]

lemma subst_into_smul_upcast {α} [add_comm_group α]
  (l r tl zl tr t) (prl₁ : l = tl) (prl₂ : ↑tl = zl) (prr : r = tr)
  (prt : @smulg α _ zl tr = t) : smul l r = t :=
by simp [← prt, prl₁, ← prl₂, prr, smul, smulg]

/-- Normalize a term `orig` of the form `smul e₁ e₂` or `smulg e₁ e₂`.
  Normalized terms use `smul` for monoids and `smulg` for groups,
  so there are actually four cases to handle:
  * Using `smul` in a monoid just simplifies the pieces using `subst_into_smul`
  * Using `smulg` in a group just simplifies the pieces using `subst_into_smulg`
  * Using `smul a b` in a group requires converting `a` from a nat to an int and
    then simplifying `smulg ↑a b` using `subst_into_smul_upcast`
  * Using `smulg` in a monoid is impossible (or at least out of scope),
    because you need a group argument to write a `smulg` term -/
meta def eval_smul' (c : context) (eval : expr → tactic (normal_expr × expr))
  (is_smulg : bool) (orig e₁ e₂ : expr) : tactic (normal_expr × expr) :=
do (e₁', p₁) ← norm_num.derive e₁ <|> refl_conv e₁,
  match if is_smulg then e₁'.to_int else coe <$> e₁'.to_nat with
  | some n := do
    (e₂', p₂) ← eval e₂,
    if c.is_group = is_smulg then do
      (e', p) ← eval_smul c (e₁', n) e₂',
      return (e', c.iapp ``subst_into_smul [e₁, e₂, e₁', e₂', e', p₁, p₂, p])
    else do
      guardb c.is_group,
      ic ← mk_instance_cache `(ℤ),
      nc ← mk_instance_cache `(ℕ),
      (ic, zl) ← ic.of_int n,
      (_, _, _, p₁') ← norm_num.prove_nat_uncast ic nc zl,
      (e', p) ← eval_smul c (zl, n) e₂',
      return (e', c.app ``subst_into_smul_upcast c.inst [e₁, e₂, e₁', zl, e₂', e', p₁, p₁', p₂, p])
  | none := eval_atom c orig
  end

meta def eval (c : context) : expr → tactic (normal_expr × expr)
| `(%%e₁ + %%e₂) := do
  (e₁', p₁) ← eval e₁,
  (e₂', p₂) ← eval e₂,
  (e', p') ← eval_add c e₁' e₂',
  p ← c.mk_app ``norm_num.subst_into_add ``has_add [e₁, e₂, e₁', e₂', e', p₁, p₂, p'],
  return (e', p)
| `(%%e₁ - %%e₂) := do
  e₂' ← mk_app ``has_neg.neg [e₂],
  e ← mk_app ``has_add.add [e₁, e₂'],
  (e', p) ← eval e,
  p' ← c.mk_app ``unfold_sub ``subtraction_monoid [e₁, e₂, e', p],
  return (e', p')
| `(- %%e) := do
  (e₁, p₁) ← eval e,
  (e₂, p₂) ← eval_neg c e₁,
  p ← c.mk_app ``norm_num.subst_into_neg ``has_neg [e, e₁, e₂, p₁, p₂],
  return (e₂, p)
| `(add_monoid.nsmul %%e₁ %%e₂) := do
  n ← if c.is_group then mk_app ``int.of_nat [e₁] else return e₁,
  (e', p) ← eval $ c.iapp ``smul [n, e₂],
  return (e', c.iapp ``unfold_smul [e₁, e₂, e', p])
| `(sub_neg_monoid.zsmul %%e₁ %%e₂) := do
  guardb c.is_group,
  (e', p) ← eval $ c.iapp ``smul [e₁, e₂],
  return (e', c.app ``unfold_zsmul c.inst [e₁, e₂, e', p])
| e@`(@has_smul.smul nat %%α %%inst %%e₁ %%e₂) := do
  let inst' := c.iapp ``nat_smul_inst [],
  mcond (succeeds (is_def_eq inst inst'))
    (eval_smul' c eval ff e e₁ e₂)
    (eval_atom c e)
| e@`(@has_smul.smul int %%α %%inst %%e₁ %%e₂) := do
  -- if we're not a group there's no canonical instance available
  tt ← pure c.is_group | eval_atom c e,
  let inst' := c.app ``int_smul_instg c.inst [],
  mcond (succeeds (is_def_eq inst inst'))
    (eval_smul' c eval tt e e₁ e₂)
    (eval_atom c e)
| e@`(smul %%e₁ %%e₂) := eval_smul' c eval ff e e₁ e₂
| e@`(smulg %%e₁ %%e₂) := eval_smul' c eval tt e e₁ e₂
| e@`(@has_zero.zero _ _) := mcond (succeeds (is_def_eq e c.α0))
  (mk_eq_refl c.α0 >>= λ p, pure (zero' c, p))
  (eval_atom c e)
| e := eval_atom c e

meta def eval' (c : context) (e : expr) : tactic (expr × expr) :=
do (e', p) ← eval c e, return (e', p)

@[derive has_reflect]
inductive normalize_mode | raw | term

instance : inhabited normalize_mode := ⟨normalize_mode.term⟩

meta def normalize (red : transparency) (mode := normalize_mode.term) (e : expr) :
  tactic (expr × expr) := do
pow_lemma ← simp_lemmas.mk.add_simp ``pow_one,
let lemmas := match mode with
| normalize_mode.term :=
  [``term.equations._eqn_1, ``termg.equations._eqn_1, ``add_zero, ``one_nsmul, ``one_zsmul,
    ``zsmul_zero]
| _ := []
end,
lemmas ← lemmas.mfoldl simp_lemmas.add_simp simp_lemmas.mk,
(_, e', pr) ← ext_simplify_core () {}
  simp_lemmas.mk (λ _, failed) (λ _ _ _ _ e, do
    c ← mk_context red e,
    (new_e, pr) ← match mode with
    | normalize_mode.raw := eval' c
    | normalize_mode.term := trans_conv (eval' c)
                               (λ e, do (e', prf, _) ← simplify lemmas [] e, return (e', prf))
    end e,
    guard (¬ new_e =ₐ e),
    return ((), new_e, some pr, ff))
   (λ _ _ _ _ _, failed) `eq e,
return (e', pr)

end abel

namespace interactive
open tactic.abel

setup_tactic_parser

/-- Tactic for solving equations in the language of
*additive*, commutative monoids and groups.
This version of `abel` fails if the target is not an equality
that is provable by the axioms of commutative monoids/groups.

`abel1!` will use a more aggressive reducibility setting to identify atoms.
This can prove goals that `abel` cannot, but is more expensive.
-/
meta def abel1 (red : parse (tk "!")?) : tactic unit :=
do `(%%e₁ = %%e₂) ← target,
  c ← mk_context (if red.is_some then semireducible else reducible) e₁,
  (e₁', p₁) ← eval c e₁,
  (e₂', p₂) ← eval c e₂,
  is_def_eq e₁' e₂',
  p ← mk_eq_symm p₂ >>= mk_eq_trans p₁,
  tactic.exact p

meta def abel.mode : lean.parser abel.normalize_mode :=
with_desc "(raw|term)?" $
do mode ← ident?, match mode with
| none       := return abel.normalize_mode.term
| some `term := return abel.normalize_mode.term
| some `raw  := return abel.normalize_mode.raw
| _          := failed
end

/--
Evaluate expressions in the language of *additive*, commutative monoids and groups.
It attempts to prove the goal outright if there is no `at`
specifier and the target is an equality, but if this
fails, it falls back to rewriting all monoid expressions into a normal form.
If there is an `at` specifier, it rewrites the given target into a normal form.

`abel!` will use a more aggressive reducibility setting to identify atoms.
This can prove goals that `abel` cannot, but is more expensive.
```lean
example {α : Type*} {a b : α} [add_comm_monoid α] : a + (b + a) = a + a + b := by abel
example {α : Type*} {a b : α} [add_comm_group α] : (a + b) - ((b + a) + a) = -a := by abel
example {α : Type*} {a b : α} [add_comm_group α] (hyp : a + a - a = b - b) : a = 0 :=
by { abel at hyp, exact hyp }
example {α : Type*} {a b : α} [add_comm_group α] : (a + b) - (id a + b) = 0 := by abel!
```
-/
meta def abel (red : parse (tk "!")?) (SOP : parse abel.mode) (loc : parse location) :
  tactic unit :=
match loc with
| interactive.loc.ns [none] := abel1 red
| _ := failed
end <|>
do ns ← loc.get_locals,
   let red := if red.is_some then semireducible else reducible,
   tt ← tactic.replace_at (normalize red SOP) ns loc.include_goal
      | fail "abel failed to simplify",
   when loc.include_goal $ try tactic.reflexivity

add_tactic_doc
{ name        := "abel",
  category    := doc_category.tactic,
  decl_names  := [`tactic.interactive.abel],
  tags        := ["arithmetic", "decision procedure"] }

end interactive
end tactic


example (P Q : Type) : (P → Q) → ((Q → empty) → (P → empty)) :=
begin
intros f h p,
apply h,
apply f,
exact p,
end