Theory Functors

theory Functors
imports Category
(*
Author: Alexander Katovsky
*)

header "Functor"

theory Functors
imports Category
begin

record ('o1, 'o2, 'm1, 'm2, 'a, 'b) Functor = 
  CatDom :: "('o1,'m1,'a)Category_scheme" 
  CatCod :: "('o2,'m2,'b)Category_scheme" 
  MapM :: "'m1 => 'm2" 

abbreviation
  FunctorMorApp :: "('o1, 'o2, 'm1, 'm2, 'a1, 'a2, 'a) Functor_scheme => 'm1 => 'm2" (infixr "##" 70) where
  "FunctorMorApp F m ≡ (MapM F) m"

definition
  MapO :: "('o1, 'o2, 'm1, 'm2, 'a1, 'a2, 'a) Functor_scheme => 'o1 => 'o2"  where
  "MapO F X ≡ THE Y . Y ∈ Obj(CatCod F) ∧  F ## (Id (CatDom F) X) = Id (CatCod F) Y"

abbreviation
  FunctorObjApp :: "('o1, 'o2, 'm1, 'm2, 'a1, 'a2, 'a) Functor_scheme => 'o1 => 'o2" (infixr "@@" 70) where
  "FunctorObjApp F X ≡ (MapO F X)"

locale PreFunctor = 
  fixes F :: "('o1, 'o2, 'm1, 'm2, 'a1, 'a2, 'a) Functor_scheme"  (structure) 
  assumes FunctorComp: "f ≈>CatDom F g ==> F ## (f ;;CatDom F g) = (F ## f) ;;CatCod F (F ## g)"
  and     FunctorId:   "X ∈ objCatDom F ==> ∃ Y ∈ objCatCod F . F ## (idCatDom F X) = idCatCod F Y"
  and     CatDom[simp]:      "Category(CatDom F)"
  and     CatCod[simp]:      "Category(CatCod F)"

locale FunctorM = PreFunctor +
  assumes     FunctorCompM: "f mapsCatDom F X to Y ==> (F ## f) mapsCatCod F (F @@ X) to (F @@ Y)"

locale FunctorExt = 
  fixes F :: "('o1, 'o2, 'm1, 'm2, 'a1, 'a2, 'a) Functor_scheme"  (structure) 
  assumes FunctorMapExt: "(MapM F) ∈ extensional (Mor (CatDom F))"

locale Functor = FunctorM + FunctorExt

definition 
  MakeFtor :: "('o1, 'o2, 'm1, 'm2, 'a, 'b,'r) Functor_scheme => ('o1, 'o2, 'm1, 'm2, 'a, 'b,'r) Functor_scheme" where
  "MakeFtor F ≡ (|
      CatDom = CatDom F , 
      CatCod = CatCod F , 
      MapM = restrict (MapM F) (Mor (CatDom F)) , 
      … = Functor.more F
  |)),"

lemma PreFunctorFunctor[simp]: "Functor F ==> PreFunctor F"
by (simp add: Functor_def FunctorM_def)

lemmas functor_simps = PreFunctor.FunctorComp PreFunctor.FunctorId

definition 
  functor_abbrev ("Ftor _ : _ --> _" [81]) where
  "Ftor F : A --> B ≡ (Functor F) ∧ (CatDom F = A) ∧ (CatCod F = B)"

lemma functor_abbrevE[elim]: "[|Ftor F : A --> B ; [|(Functor F) ; (CatDom F = A) ; (CatCod F = B)|] ==> R|] ==> R"
by (auto simp add: functor_abbrev_def)

definition
  functor_comp_def ("_ ≈>;;; _" [81]) where
  "functor_comp_def F G ≡ (Functor F) ∧ (Functor G) ∧ (CatDom G = CatCod F)"

lemma functor_comp_def[elim]: "[|F ≈>;;; G ; [|Functor F ; Functor G ; CatDom G = CatCod F|] ==> R|] ==> R"
by (auto simp add: functor_comp_def_def)

lemma (in Functor) FunctorMapsTo:
  assumes "f ∈ morCatDom F"
  shows   "F ## f mapsCatCod F (F @@ (domCatDom F f)) to (F @@ (codCatDom F f))"
proof-
  have "f mapsCatDom F (domCatDom F f) to (codCatDom F f)" using assms by auto
  thus ?thesis by (simp add: FunctorCompM[of f "domCatDom F f" "codCatDom F f"])
qed

lemma (in Functor) FunctorCodDom: 
  assumes "f ∈ morCatDom F"
  shows "domCatCod F(F ## f) = F @@ (domCatDom F f)" and "codCatCod F(F ## f) = F @@ (codCatDom F f)"
proof-
  have "F ## f mapsCatCod F (F @@ (domCatDom F f)) to (F @@ (codCatDom F f))" using assms by (simp add: FunctorMapsTo)
  thus "domCatCod F(F ## f) = F @@ (domCatDom F f)" and "codCatCod F(F ## f) = F @@ (codCatDom F f)"
    by auto
qed

lemma (in Functor) FunctorCompPreserved: "f ∈ morCatDom F ==> F ## f ∈ morCatCod F"
by (auto dest:FunctorMapsTo)

lemma (in Functor) FunctorCompDef: 
  assumes "f ≈>CatDom F g" shows "(F ## f) ≈>CatCod F (F ## g)"
proof(auto simp add: CompDefined_def)
  show "F ## f ∈ morCatCod F" and "F ## g ∈ morCatCod F" using assms by (auto simp add: FunctorCompPreserved)
  have "f ∈ morCatDom F" and "g ∈ morCatDom F" using assms by auto
  hence a: "codCatCod F (F ## f) = F @@ (codCatDom F f)" and b: "domCatCod F(F ## g) = F @@ (domCatDom F g)"
    by (simp add: FunctorCodDom)+
  have "codCatCod F (F ## f) = F @@ (domCatDom F g)" using assms a by auto
  also have "... = domCatCod F (F ## g)" using b by simp
  finally show "codCatCod F (F ## f) = domCatCod F (F ## g)" .
qed

lemma FunctorComp: "[|Ftor F : A --> B ; f ≈>A g|] ==> F ## (f ;;A g) = (F ## f) ;;B (F ## g)"
by (auto simp add: PreFunctor.FunctorComp)

lemma FunctorCompDef: "[|Ftor F : A --> B ; f ≈>A g|] ==> (F ## f) ≈>B (F ## g)"
by (auto simp add: Functor.FunctorCompDef)

lemma FunctorMapsTo: 
  assumes "Ftor F : A --> B" and "f mapsA X to Y" 
  shows "(F ## f) mapsB (F @@ X) to (F @@ Y)"
proof-
  have b: "CatCod F = B" and a: "CatDom F = A" and ff: "Functor F" using assms by auto
  have df: "(domCatDom F f) = X" and cf: "(codCatDom F f) = Y" using a assms by auto
  have "f ∈ morCatDom F" using assms by auto
  hence "F ## f mapsCatCod F (F @@ (domCatDom F f)) to (F @@ (codCatDom F f))" using ff
    by (simp add: Functor.FunctorMapsTo) 
  thus ?thesis using df cf b by simp
qed

lemma (in PreFunctor) FunctorId2: 
  assumes "X ∈ objCatDom F"
  shows   "F @@ X ∈ objCatCod F ∧ F ## (idCatDom F X) = idCatCod F (F @@ X)"
proof-
  let ?Q = "λ E Y . Y ∈ objCatCod F ∧ E = idCatCod F Y"
  let ?P = "?Q (F ## (idCatDom F X))"
  from assms FunctorId obtain Y where "?P Y" by auto
  moreover  { 
    fix y e z have "[|?Q e y ; ?Q e z|] ==> y = z"
      by (auto intro: Category.IdInj[of "CatCod F" y z])
  }
  ultimately have "∃! Z . ?P Z" by auto
  hence "?P (THE Y . ?P Y)" by (rule theI')
  thus ?thesis by (auto simp add: MapO_def)
qed

lemma FunctorId:
  assumes "Ftor F : C --> D" and "X ∈ Obj C"
  shows "F ## (Id C X) = Id D (F @@ X)"
proof-
  have "CatDom F = C" and "CatCod F = D" and "PreFunctor F" using assms by auto
  thus ?thesis using assms PreFunctor.FunctorId2[of F X] by simp
qed

lemma (in Functor) DomFunctor: "f ∈ morCatDom F ==> domCatCod F (F ## f) = F @@ (domCatDom F f)"
by (simp add: FunctorCodDom)

lemma (in Functor) CodFunctor: "f ∈ morCatDom F ==> codCatCod F (F ## f) = F @@ (codCatDom F f)"
by (simp add: FunctorCodDom) 

lemma (in Functor) FunctorId3Dom:
  assumes "f ∈ morCatDom F"
  shows   "F ## (idCatDom F (domCatDom F f)) = idCatCod F (domCatCod F (F ## f))"
proof-
  have "(domCatDom F f) ∈ objCatDom F" using assms by (simp add: Category.Cdom)
  hence "F ## (idCatDom F (domCatDom F f)) = idCatCod F (F @@ (domCatDom F f))" by (simp add: FunctorId2)
  also have "... = idCatCod F (domCatCod F (F ## f))" using assms by (simp add: DomFunctor)
  finally show ?thesis by simp
qed

lemma (in Functor) FunctorId3Cod:
  assumes "f ∈ morCatDom F"
  shows   "F ## (idCatDom F (codCatDom F f)) = idCatCod F (codCatCod F (F ## f))"
proof-
  have "(codCatDom F f) ∈ objCatDom F" using assms by (simp add: Category.Ccod)
  hence "F ## (idCatDom F (codCatDom F f)) = idCatCod F (F @@ (codCatDom F f))" by (simp add: FunctorId2)
  also have "... = idCatCod F (codCatCod F (F ## f))" using assms by (simp add: CodFunctor)
  finally show ?thesis by simp
qed

lemma (in PreFunctor) FmToFo: "[|X ∈ objCatDom F ; Y ∈ objCatCod F ; F ## (idCatDom F X) = idCatCod F Y|] ==> F @@ X = Y"
  by (auto simp add: FunctorId2 intro: Category.IdInj[of "CatCod F" "F @@ X" Y])

lemma MakeFtorPreFtor: 
  assumes "PreFunctor F" shows "PreFunctor (MakeFtor F)"
proof-
  {
    fix X assume a: "X ∈ objCatDom F" have "idCatDom F X ∈ morCatDom F"
    proof-
      have "Category (CatDom F)" using assms by (simp add: PreFunctor_def)
      hence "idCatDom F X mapsCatDom F X to X" using a by (simp add: Category.Cidm)
      thus ?thesis using a by (auto)
    qed
  }
  thus "PreFunctor (MakeFtor F)" using assms
    by(auto simp add: PreFunctor_def MakeFtor_def Category.MapsToMorDomCod)
qed

lemma MakeFtorMor: "f ∈ morCatDom F ==> MakeFtor F ## f = F ## f"
by(simp add: MakeFtor_def)

lemma MakeFtorObj: 
  assumes "PreFunctor F" and "X ∈ objCatDom F"
  shows "MakeFtor F @@ X = F @@ X"
proof-
  have "X ∈ objCatDom (MakeFtor F)" using assms(2) by (simp add: MakeFtor_def)
  moreover have "(F @@ X) ∈ objCatCod (MakeFtor F)" using assms by (simp add: PreFunctor.FunctorId2 MakeFtor_def)
  moreover have "MakeFtor F ## idCatDom (MakeFtor F) X = idCatCod (MakeFtor F) (F @@ X)" 
  proof-
    have "Category (CatDom F)" using assms(1) by (simp add: PreFunctor_def)
    hence "idCatDom F X  mapsCatDom F X to X" using assms(2) by (auto simp add: Category.Cidm)
    hence "idCatDom F X ∈ morCatDom F" by auto
    hence "MakeFtor F ## idCatDom (MakeFtor F) X = F ## idCatDom F X" by (simp add: MakeFtor_def)
    also have "... = idCatCod F (F @@ X)" using assms by (simp add: PreFunctor.FunctorId2)
    finally show ?thesis by (simp add: MakeFtor_def)
  qed
  moreover have "PreFunctor (MakeFtor F)" using assms(1) by (simp add: MakeFtorPreFtor)
  ultimately show ?thesis by (simp add: PreFunctor.FmToFo)
qed

lemma MakeFtor: assumes "FunctorM F" shows "Functor (MakeFtor F)" 
proof(intro_locales)
  show "PreFunctor (MakeFtor F)" using assms by (simp add: MakeFtorPreFtor FunctorM_def)
  show "FunctorM_axioms (MakeFtor F)"
  proof(auto simp add: FunctorM_axioms_def)
    {
      fix f X Y assume aa: "f mapsCatDom (MakeFtor F) X to Y"
      show "((MakeFtor F) ## f) mapsCatCod (MakeFtor F) ((MakeFtor F) @@ X) to ((MakeFtor F) @@ Y)"
      proof-
        have "((MakeFtor F) ## f) = F ## f" using aa by (auto simp add: MakeFtor_def)
        moreover have "((MakeFtor F) @@ X) = F @@ X" and "((MakeFtor F) @@ Y) = F @@ Y"
        proof-
          have "Category (CatDom F)" using assms by (simp add: FunctorM_def PreFunctor_def)
          hence "X ∈ objCatDom F" and "Y ∈ objCatDom F" 
            using aa by (auto simp add: Category.MapsToObj MakeFtor_def)
          moreover have "PreFunctor F" using assms(1) by (simp add: FunctorM_def)
          ultimately show "((MakeFtor F) @@ X) = F @@ X" and "((MakeFtor F) @@ Y) = F @@ Y"
            by (simp add: MakeFtorObj)+
        qed
        moreover have "F ## f mapsCatCod F (F @@ X) to (F @@ Y)" using assms(1) aa 
          by (simp add: FunctorM.FunctorCompM MakeFtor_def)
        ultimately show ?thesis by (simp add: MakeFtor_def)
      qed
    }
  qed
  show "FunctorExt (MakeFtor F)" by(simp add: FunctorExt_def MakeFtor_def)
qed

definition 
  IdentityFunctor' :: "('o,'m,'a) Category_scheme => ('o,'o,'m,'m,'a,'a) Functor" ("FId' _" [70]) where
  "IdentityFunctor' C ≡ (|CatDom = C , CatCod = C , MapM = (λ f . f) |)),"

definition 
  IdentityFunctor ("FId _" [70]) where
  "IdentityFunctor C ≡ MakeFtor(IdentityFunctor' C)"

lemma IdFtor'PreFunctor: "Category C ==> PreFunctor (FId' C)"
by(auto simp add: PreFunctor_def IdentityFunctor'_def)

lemma IdFtor'Obj:
  assumes "Category C" and "X ∈ objCatDom (FId' C)"
  shows "(FId' C) @@ X = X"
proof-
  have "(FId' C) ## idCatDom (FId' C) X = idCatCod (FId' C) X" by(simp add: IdentityFunctor'_def)
  moreover have "X ∈ objCatCod (FId' C)" using assms by (simp add: IdentityFunctor'_def)
  ultimately show ?thesis using assms by (simp add: PreFunctor.FmToFo IdFtor'PreFunctor)
qed

lemma IdFtor'FtorM:  
  assumes "Category C" shows "FunctorM (FId' C)"
proof(auto simp add: FunctorM_def IdFtor'PreFunctor assms FunctorM_axioms_def)
  {
    fix f X Y assume a: "f mapsCatDom (FId' C) X to Y" 
    show "((FId' C) ## f) mapsCatCod (FId' C) ((FId' C) @@ X) to ((FId' C) @@ Y)"
    proof-
      have "X ∈ objCatDom (FId' C)" and "Y ∈ objCatDom (FId' C)"
        using a assms by (simp add: Category.MapsToObj IdentityFunctor'_def)+
      moreover have "(FId' C) ## f = f" and "CatDom (FId' C) = CatCod (FId' C)" by (simp add: IdentityFunctor'_def)+
      ultimately show ?thesis using assms a by(simp add: IdFtor'Obj)
    qed
  }
qed

lemma IdFtorFtor:  "Category C ==> Functor (FId C)"
by (auto simp add: IdentityFunctor_def IdFtor'FtorM intro: MakeFtor)

definition 
  ConstFunctor' :: "('o1,'m1,'a) Category_scheme => 
                  ('o2,'m2,'b) Category_scheme => 'o2 => ('o1,'o2,'m1,'m2,'a,'b) Functor"  where
  "ConstFunctor' A B b ≡ (|
         CatDom = A , 
         CatCod = B , 
         MapM = (λ f . (Id B) b)
  |)),"

definition "ConstFunctor A B b ≡ MakeFtor(ConstFunctor' A B b)"

lemma ConstFtor' : 
  assumes "Category A" "Category B" "b ∈ (Obj B)"
  shows   "PreFunctor (ConstFunctor' A B b)"
  and     "FunctorM (ConstFunctor' A B b)"
proof-
  show "PreFunctor (ConstFunctor' A B b)" using assms
    apply (subst PreFunctor_def)
    apply (rule conjI)+
    by (auto simp add: ConstFunctor'_def Category.Simps Category.CatIdCompId)
  moreover 
  {
    fix X  assume "X ∈ objA" "b ∈ objB" "PreFunctor (ConstFunctor' A B b)" 
    hence "(ConstFunctor' A B b) @@ X = b"
      by (auto simp add: ConstFunctor'_def PreFunctor.FmToFo Category.Simps)
  }
  ultimately show "FunctorM (ConstFunctor' A B b)" using assms
    by (intro_locales, auto simp add: ConstFunctor'_def Category.Simps FunctorM_axioms_def)
qed

lemma ConstFtor: 
  assumes "Category A" "Category B" "b ∈ (Obj B)"
  shows "Functor (ConstFunctor A B b)"
by (auto simp add: assms ConstFtor' ConstFunctor_def MakeFtor)

definition 
  UnitFunctor :: "('o,'m,'a) Category_scheme => ('o,unit,'m,unit,'a,unit) Functor"  where
  "UnitFunctor C ≡ ConstFunctor C UnitCategory ()"

lemma UnitFtor: 
  assumes "Category C" 
  shows "Functor(UnitFunctor C)"
proof-
  have "() ∈ objUnitCategory" by (simp add: UnitCategory_def MakeCatObj)
  hence "Functor(ConstFunctor C UnitCategory ())" using assms 
    by (simp add: ConstFtor)
  thus ?thesis by (simp add: UnitFunctor_def)
qed

definition
  FunctorComp' :: "('o1,'o2,'m1,'m2,'a1,'a2) Functor => ('o2,'o3,'m2,'m3,'b1,'b2) Functor
                    => ('o1,'o3,'m1,'m3,'a1,'b2) Functor" (infixl ";;:" 71) where
  "FunctorComp' F G ≡ (|
        CatDom = CatDom F , 
        CatCod = CatCod G ,
        MapM   = λ f . (MapM G)((MapM F) f)
  |)),"

definition FunctorComp (infixl ";;;" 71) where "FunctorComp F G ≡ MakeFtor (FunctorComp' F G)"

lemma FtorCompComp':
  assumes "f ≈>CatDom F g"
  and "F ≈>;;; G"
  shows "G ## (F ## (f ;;CatDom F g)) = (G ## (F ## f)) ;;CatCod G (G ## (F ## g))"
proof-
  have [simp]: "PreFunctor G ∧ PreFunctor F" using assms by auto
  have [simp]: "(F ## f) ≈>CatDom G (F ## g)" using assms by (auto simp add: Functor.FunctorCompDef[of F f g])
  have "F ## (f ;;CatDom F g) = (F ## f) ;;CatCod F (F ## g)" using assms
    by (auto simp add: PreFunctor.FunctorComp)
  hence "G ## (F ## (f ;;CatDom F g)) = G ## ((F ## f) ;;CatCod F (F ## g))" by simp
  also have "... = G ## ((F ## f) ;;CatDom G (F ## g))" using assms by auto
  also have "... = (G ## (F ## f)) ;;CatCod G (G ## (F ## g))"
    by (simp add: PreFunctor.FunctorComp[of G "(F ## f)" "(F ## g)"])
  finally show ?thesis by simp
qed

lemma FtorCompId: 
  assumes a: "X ∈ (Obj (CatDom F))"
  and "F ≈>;;; G"
  shows "G ## (F ## (idCatDom F X)) = idCatCod G(G @@ (F @@ X)) ∧ G @@ (F @@ X) ∈ (Obj (CatCod G))"
proof-
  have [simp]: "PreFunctor G ∧ PreFunctor F" using assms by auto
  have b: "(F @@ X) ∈ objCatDom G" using assms
    by (auto simp add: PreFunctor.FunctorId2)
  have "G ## F ## (idCatDom F X) = G ## (idCatCod F(F @@ X))" using b a
    by (simp add: PreFunctor.FunctorId2[of F "X"])
  also have "... = G ## (idCatDom G(F @@ X))" using assms by auto
  also have "... = idCatCod G(G @@ (F @@ X)) ∧ G @@ (F @@ X) ∈ (Obj (CatCod G))" using b
    by (simp add: PreFunctor.FunctorId2[of G "(F @@ X)"])
  finally show ?thesis by simp
qed

lemma FtorCompIdDef: 
  assumes a: "X ∈ (Obj (CatDom F))" and b: "PreFunctor (F ;;: G)" 
  and "F ≈>;;; G"
  shows "(F ;;: G) @@ X = (G @@ (F @@ X))"
proof-
  have "(F ;;: G) ## (idCatDom (F ;;: G)(X)) = G ## (F ## (idCatDom F(X)))" using assms
    by (simp add: FunctorComp'_def)
  also have "... = idCatCod G(G @@ (F @@ (X)))" using assms a
    by(auto simp add: FtorCompId[of _ F G])
  finally have "(F ;;: G) ## (idCatDom (F ;;: G)(X)) = idCatCod (F ;;: G)(G @@ (F @@ X))" using assms
    by (simp add: FunctorComp'_def)
  moreover have "G @@ (F @@ (X)) ∈ (Obj (CatCod (F ;;: G)))" using assms a
    by(auto simp add: FtorCompId[of _ F G] FunctorComp'_def)
  moreover have "X ∈ objCatDom (F ;;: G)" using a by (simp add: FunctorComp'_def)
  ultimately show ?thesis using b 
    by (simp add: PreFunctor.FmToFo[of "F ;;: G" X "G @@ (F @@ X)"])
qed

lemma FunctorCompMapsTo: 
  assumes "f ∈ morCatDom (F ;;: G)" and "F ≈>;;; G"
  shows "(G ## (F ## f)) mapsCatCod G (G @@ (F @@ (domCatDom F f))) to (G @@ (F @@ (codCatDom F f)))"
proof-
  have "f ∈ morCatDom F ∧ Functor F" using assms by (auto simp add: FunctorComp'_def)
  hence "(F ## f) mapsCatDom G (F @@ (domCatDom F f)) to (F @@ (codCatDom F f))" using assms 
    by (auto simp add: Functor.FunctorMapsTo[of F f])
  moreover have "FunctorM G" using assms by (auto simp add: FunctorComp_def Functor_def)
  ultimately show ?thesis by(simp add: FunctorM.FunctorCompM[of G "F ## f" "F @@ (domCatDom F f)" "F @@ (codCatDom F f)"])
qed

lemma FunctorCompMapsTo2:
  assumes "f ∈ morCatDom (F ;;: G)" 
  and "F ≈>;;; G"
  and "PreFunctor (F ;;: G)" 
  shows "((F ;;: G) ## f) mapsCatCod (F ;;: G) ((F ;;: G) @@ (domCatDom (F ;;: G) f)) to 
                                               ((F ;;: G) @@ (codCatDom (F ;;: G) f))"
proof-
  have "Category (CatDom (F ;;: G))" using assms by (simp add: PreFunctor_def) 
  hence 1: "(domCatDom (F ;;: G) f) ∈ objCatDom F ∧ (codCatDom (F ;;: G) f) ∈ objCatDom F" using assms 
    by (auto simp add: Category.Simps FunctorComp'_def)
  have "(G ## (F ## f)) mapsCatCod G (G @@ (F @@ (domCatDom F f))) to (G @@ (F @@ (codCatDom F f)))"
    using assms by (auto simp add: FunctorCompMapsTo[of f F G])
  moreover have "CatDom F = CatDom(F ;;: G) ∧ CatCod G = CatCod(F ;;: G) ∧ (G ## (F ## f)) = ((F ;;: G) ## f)" using assms
    by (simp add: FunctorComp'_def)
  moreover have "(F ;;: G) @@ (domCatDom (F ;;: G) f) = (G @@ (F @@ (domCatDom(F ;;: G) f))) ∧
        (F ;;: G) @@ (codCatDom (F ;;: G) f) = (G @@ (F @@ (codCatDom(F ;;: G) f)))" 
    by (auto simp add: FtorCompIdDef[of _ F G] 1 assms)
  ultimately show ?thesis by auto
qed

lemma FunctorCompMapsTo3:
  assumes "f mapsCatDom (F ;;: G) X to Y"
  and "F ≈>;;; G"
  and "PreFunctor (F ;;: G)" 
  shows "F ;;: G ## f mapsCatCod (F ;;: G) F ;;: G @@ X to F ;;: G @@ Y"
proof-
  have  "f ∈ morCatDom (F ;;: G)" 
    and "domCatDom (F ;;: G) f = X" 
    and "codCatDom (F ;;: G) f = Y" using assms by auto
  thus ?thesis using assms by (auto intro: FunctorCompMapsTo2)
qed

lemma FtorCompPreFtor:
  assumes "F ≈>;;; G"
  shows   "PreFunctor (F ;;: G)"
proof-
  have 1: "PreFunctor G ∧ PreFunctor F" using assms by auto
  show "PreFunctor (F ;;: G)" using assms
  proof(auto simp add: PreFunctor_def FunctorComp'_def Category.Simps
       FtorCompId[of _ F G] intro:FtorCompComp')
    show "Category (CatDom F)" and "Category (CatCod G)" using assms 1 by (auto simp add: PreFunctor_def)
  qed
qed

lemma FtorCompM : 
  assumes "F ≈>;;; G"
  shows   "FunctorM (F ;;: G)"
proof(auto simp only: FunctorM_def)
  show 1: "PreFunctor (F ;;: G)" using assms by (rule FtorCompPreFtor)
  {
    fix X Y f assume a: "f mapsCatDom (F ;;: G) X to Y"
    have "F ;;: G ## f mapsCatCod (F ;;: G) F ;;: G @@ X to F ;;: G @@ Y" 
      using a assms 1 by (rule FunctorCompMapsTo3)
  }
  thus "FunctorM_axioms (F ;;: G)" 
    by(auto simp add: 1 FunctorM_axioms_def)
qed

lemma FtorComp:   
  assumes "F ≈>;;; G"
  shows   "Functor (F ;;; G)"
proof-
  have "FunctorM (F ;;: G)" using assms by (rule FtorCompM)
  thus ?thesis by (simp add: FunctorComp_def MakeFtor)
qed

lemma (in Functor) FunctorPreservesIso: 
  assumes     "cisoCatDom F k"
  shows       "cisoCatCod F (F ## k)"
proof-
  have [simp]: "k ∈ morCatDom F" using assms by (simp add: Category.IsoIsMor)
  have "cinvCatCod F (F ## k) (F ## (CinvCatDom F k))" 
    proof(rule Category.Inverse_relI)
      show "Category (CatCod F)" by simp
      show "(F ## k) ≈>CatCod F (F ## (CinvCatDom F k))" 
        by (rule FunctorCompDef, simp add: Category.IsoCompInv assms)
      show "(F ## k) ;;CatCod F (F ## (CinvCatDom F k)) = idCatCod F (domCatCod F (F ## k))" 
      proof-
        have      "(F ## k) ;;CatCod F (F ## (CinvCatDom F k)) = F ## (k ;;CatDom F (CinvCatDom F k))" using assms
          by(auto simp add: FunctorComp Category.IsoCompInv)
        also have "... = F ## (idCatDom F (domCatDom F k))" using assms by (simp add: Category.IsoInvId2)
        also have "... = idCatCod F (domCatCod F (F ## k))" by (simp add: FunctorId3Dom) 
        finally show ?thesis by simp
      qed 
      show "(F ## (CinvCatDom F k)) ;;CatCod F (F ## k) = idCatCod F (codCatCod F (F ## k))" 
      proof-
        have      "(F ## (CinvCatDom F k)) ;;CatCod F (F ## k) = F ## ((CinvCatDom F k) ;;CatDom F  k)" using assms
          by(auto simp add: FunctorComp Category.InvCompIso)
        also have "... = F ## (idCatDom F (codCatDom F k))" using assms by (simp add: Category.IsoInvId1)
        also have "... = idCatCod F (codCatCod F (F ## k))" using assms by (simp add: FunctorId3Cod) 
        finally show ?thesis by simp
      qed   
    qed
  thus ?thesis by(auto simp add: isomorphism_def)
qed

declare PreFunctor.CatDom[simp] PreFunctor.CatCod [simp]

lemma FunctorMFunctor[simp]: "Functor F ==> FunctorM F"
by (simp add: Functor_def)

locale Equivalence = Functor +
  assumes Full: "[|A ∈ Obj (CatDom F) ; B ∈ Obj (CatDom F) ; 
                  h mapsCatCod F (F @@ A) to (F @@ B)|] ==>
                 ∃ f . (f mapsCatDom F A to B) ∧ (F ## f = h)"
  and Faithful: "[|f mapsCatDom F A to B ; g mapsCatDom F A to B ; F ## f = F ## g|] ==> f = g"
  and IsoDense: "C ∈ Obj (CatCod F) ==> ∃ A ∈ Obj (CatDom F) . ObjIso (CatCod F) (F @@ A) C"

end