Theory Functors

(*
Author: Alexander Katovsky
*)

section "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 Fg  F ## (f ;;CatDom Fg) = (F ## f) ;;CatCod F(F ## g)"
  and     FunctorId:   "X  objCatDom F  Y  objCatCod F. F ## (idCatDom FX) = idCatCod FY"
  and     CatDom[simp]:      "Category(CatDom F)"
  and     CatCod[simp]:      "Category(CatCod F)"

locale FunctorM = PreFunctor +
  assumes     FunctorCompM: "f mapsCatDom FX 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 Ff)) to (F @@ (codCatDom Ff))"
proof-
  have "f mapsCatDom F(domCatDom Ff) to (codCatDom Ff)" using assms by auto
  thus ?thesis by (simp add: FunctorCompM[of f "domCatDom Ff" "codCatDom Ff"])
qed

lemma (in Functor) FunctorCodDom: 
  assumes "f  morCatDom F⇙"
  shows "domCatCod F(F ## f) = F @@ (domCatDom Ff)" and "codCatCod F(F ## f) = F @@ (codCatDom Ff)"
proof-
  have "F ## f mapsCatCod F(F @@ (domCatDom Ff)) to (F @@ (codCatDom Ff))" using assms by (simp add: FunctorMapsTo)
  thus "domCatCod F(F ## f) = F @@ (domCatDom Ff)" and "codCatCod F(F ## f) = F @@ (codCatDom Ff)"
    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 Fg" 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 Ff)" and b: "domCatCod F(F ## g) = F @@ (domCatDom Fg)"
    by (simp add: FunctorCodDom)+
  have "codCatCod F(F ## f) = F @@ (domCatDom Fg)" 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 ≈>Ag  F ## (f ;;Ag) = (F ## f) ;;B(F ## g)"
by (auto simp add: PreFunctor.FunctorComp)

lemma FunctorCompDef: "Ftor F : A  B ; f ≈>Ag  (F ## f) ≈>B(F ## g)"
by (auto simp add: Functor.FunctorCompDef)

lemma FunctorMapsTo: 
  assumes "Ftor F : A  B" and "f mapsAX 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 Ff) = X" and cf: "(codCatDom Ff) = Y" using a assms by auto
  have "f  morCatDom F⇙" using assms by auto
  hence "F ## f mapsCatCod F(F @@ (domCatDom Ff)) to (F @@ (codCatDom Ff))" 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 FX) = idCatCod F(F @@ X)"
proof-
  let ?Q = "λ E Y . Y  objCatCod F E = idCatCod FY"
  let ?P = "?Q (F ## (idCatDom FX))"
  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 Ff)"
by (simp add: FunctorCodDom)

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

lemma (in Functor) FunctorId3Dom:
  assumes "f  morCatDom F⇙"
  shows   "F ## (idCatDom F(domCatDom Ff)) = idCatCod F(domCatCod F(F ## f))"
proof-
  have "(domCatDom Ff)  objCatDom F⇙" using assms by (simp add: Category.Cdom)
  hence "F ## (idCatDom F(domCatDom Ff)) = idCatCod F(F @@ (domCatDom Ff))" 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 Ff)) = idCatCod F(codCatCod F(F ## f))"
proof-
  have "(codCatDom Ff)  objCatDom F⇙" using assms by (simp add: Category.Ccod)
  hence "F ## (idCatDom F(codCatDom Ff)) = idCatCod F(F @@ (codCatDom Ff))" 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 FX) = idCatCod FY  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 FX  morCatDom F⇙"
    proof-
      have "Category (CatDom F)" using assms by (simp add: PreFunctor_def)
      hence "idCatDom FX mapsCatDom FX 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 FX  mapsCatDom FX to X" using assms(2) by (auto simp add: Category.Cidm)
    hence "idCatDom FX  morCatDom F⇙" by auto
    hence "MakeFtor F ## idCatDom (MakeFtor F)X = F ## idCatDom FX" 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 Fg"
  and "F ≈>;;; G"
  shows "G ## (F ## (f ;;CatDom Fg)) = (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 Fg) = (F ## f) ;;CatCod F(F ## g)" using assms
    by (auto simp add: PreFunctor.FunctorComp)
  hence "G ## (F ## (f ;;CatDom Fg)) = 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 FX)) = 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 FX) = 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 Ff))) to (G @@ (F @@ (codCatDom Ff)))"
proof-
  have "f  morCatDom F Functor F" using assms by (auto simp add: FunctorComp'_def)
  hence "(F ## f) mapsCatDom G(F @@ (domCatDom Ff)) to (F @@ (codCatDom Ff))" 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 Ff)" "F @@ (codCatDom Ff)"])
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 Ff))) to (G @@ (F @@ (codCatDom Ff)))"
    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 Fk"
  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 Fk))" 
    proof(rule Category.Inverse_relI)
      show "Category (CatCod F)" by simp
      show "(F ## k) ≈>CatCod F(F ## (CinvCatDom Fk))" 
        by (rule FunctorCompDef, simp add: Category.IsoCompInv assms)
      show "(F ## k) ;;CatCod F(F ## (CinvCatDom Fk)) = idCatCod F(domCatCod F(F ## k))" 
      proof-
        have      "(F ## k) ;;CatCod F(F ## (CinvCatDom Fk)) = F ## (k ;;CatDom F(CinvCatDom Fk))" using assms
          by(auto simp add: FunctorComp Category.IsoCompInv)
        also have "... = F ## (idCatDom F(domCatDom Fk))" 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 Fk)) ;;CatCod F(F ## k) = idCatCod F(codCatCod F(F ## k))" 
      proof-
        have      "(F ## (CinvCatDom Fk)) ;;CatCod F(F ## k) = F ## ((CinvCatDom Fk) ;;CatDom Fk)" using assms
          by(auto simp add: FunctorComp Category.InvCompIso)
        also have "... = F ## (idCatDom F(codCatDom Fk))" 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 FA to B)  (F ## f = h)"
  and Faithful: "f mapsCatDom FA to B ; g mapsCatDom FA 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