Theory SetCat

theory SetCat
imports Functors Universe
(*
Author: Alexander Katovsky
*)

header "The Category of Sets"

theory SetCat
imports Functors Universe
begin

notation (xsymbols) Elem (infixl "|∈|" 70)
notation (xsymbols) HOLZF.subset (infixl "|⊆|" 71)
notation (xsymbols) CartProd (infixl "|×|" 75)

definition 
  ZFfun :: "ZF => ZF => (ZF => ZF) => ZF" where
  "ZFfun d r f ≡ Opair (Opair d r) (Lambda d f)"

definition
  ZFfunDom :: "ZF => ZF" ("|dom|_" [72] 72) where
  "ZFfunDom f ≡ Fst (Fst f)"

definition
  ZFfunCod :: "ZF => ZF" ("|cod|_" [72] 72) where
  "ZFfunCod f ≡ Snd (Fst f)"

definition
  ZFfunApp :: "ZF => ZF => ZF" (infixl "|@|" 73) where
  "ZFfunApp f x ≡ app (Snd f) x"

definition 
  ZFfunComp :: "ZF => ZF => ZF" (infixl "|o|" 72) where
  "ZFfunComp f g ≡ ZFfun ( |dom| f) ( |cod| g) (λx. g |@| (f |@| x))"

definition 
  isZFfun :: "ZF => bool" where
  "isZFfun drf ≡ let f = Snd drf in
                 isOpair drf ∧ isOpair (Fst drf) ∧ isFun f ∧ (f |⊆| (Domain f) |×| (Range f))
                 ∧ (Domain f = |dom| drf) ∧ (Range f |⊆| |cod| drf)"

lemma isZFfunE[elim]: "[|isZFfun f ; 
  [|isOpair f ; isOpair (Fst f) ; isFun (Snd f) ; 
  ((Snd f) |⊆| (Domain (Snd f)) |×| (Range (Snd f))) ; 
  (Domain (Snd f) = |dom| f) ∧ (Range (Snd f) |⊆| |cod| f)|] ==> R|] ==> R"
  by (auto simp add: isZFfun_def Let_def)

definition  
  SET' :: "(ZF, ZF) Category" where
  "SET' ≡ (|
      Category.Obj = {x . True} , 
      Category.Mor = {f . isZFfun f} ,
      Category.Dom = ZFfunDom , 
      Category.Cod = ZFfunCod , 
      Category.Id = λx. ZFfun x x (λx . x) , 
      Category.Comp = ZFfunComp
  |)),"

definition "SET ≡ MakeCat SET'"

lemma ZFfunDom: "|dom| (ZFfun A B f) = A"
by (auto simp add: ZFfun_def ZFfunDom_def Fst)

lemma ZFfunCod: "|cod| (ZFfun A B f) = B"
by (auto simp add: ZFfun_def ZFfunCod_def Snd Fst)

lemma SETfun: 
  assumes "∀ x . x |∈| A --> (f x) |∈| B"
  shows   "isZFfun (ZFfun A B f)"
proof(auto simp add: isZFfun_def ZFfun_def isOpair Fst Snd 
    ZFfunCod_def ZFfunDom_def isFun_Lambda domain_Lambda Let_def)
  {
    fix x
    have "x |∈| Range (Lambda A f) ==> x |∈| B"
      apply(insert isFun_Lambda[of A f])
      apply (drule fun_range_witness[of "Lambda A f" x], simp)
      by (auto simp add: domain_Lambda Lambda_app assms)
  }
  thus "subset (Range (Lambda A f)) B"
    by (auto simp add: subset_def)
  {
    fix x
    have "x |∈| (Lambda A f) ==> x |∈| A |×| Range (Lambda A f)" 
      by(auto simp add: CartProd Lambda_def Repl Range)
  }
  thus "(Lambda A f) |⊆| (A |×| Range (Lambda A f))"
    by (auto simp add: HOLZF.subset_def)
qed

lemma ZFCartProd: 
  assumes "x |∈| A |×| B"
  shows   "Fst x |∈| A ∧ Snd x |∈| B ∧ isOpair x"
proof-
  from CartProd obtain a b 
    where "a |∈| A" 
    and   "b |∈| B" 
    and   "x = Opair a b" using assms by auto
  thus ?thesis using assms by (auto simp add: Fst Snd isOpair_def)
qed

lemma ZFfunDomainOpair:
  assumes "isFun f"
  and     "x |∈| Domain f"
  shows   "Opair x (app f x) |∈| f"
proof-
  have "∃! y . Opair x y |∈| f" using assms by (auto simp add: unique_fun_value)
  thus "Opair x (app f x) |∈| f" by (auto simp add: app_def intro: theI')
qed
  
lemma ZFFunToLambda: 
  assumes 1: "isFun f"
  and     2: "f |⊆| (Domain f) |×| (Range f)"
  shows   "f = Lambda (Domain f) (λx. app f x)"
proof(subst Ext, rule allI, rule iffI)
  {
    fix x assume a: "x |∈| f" show "x |∈| Lambda (Domain f) (λx. app f x)" 
    proof(simp add: Lambda_def Repl, rule exI[of _ "(Fst x)"], rule conjI)
      have b:"isOpair x ∧ Fst x |∈| Domain f" using 2 a by (auto simp add: subset_def ZFCartProd)
      thus "Fst x |∈| Domain f" ..
      hence "Opair (Fst x) (app f (Fst x)) |∈| f" using 1 by (simp add: ZFfunDomainOpair)
      moreover have "Opair (Fst x) (Snd x) |∈| f" using a 2 by (auto simp add: FstSnd subset_def b)
      ultimately have "Snd x = (app f (Fst x))" using 1 by (auto simp add: isFun_def)
      hence "Opair (Fst x) (app f (Fst x)) = Opair (Fst x) (Snd x)" by simp
      also have "... = x"  using b by (simp add: FstSnd)
      finally show "x = Opair (Fst x) (app f (Fst x))" ..
    qed
  }
  moreover 
  {
    fix x assume a: "x |∈| Lambda (Domain f) (λx. app f x)" show "x |∈| f"
      proof-
        from Lambda_def obtain a where "a |∈| Domain f ∧ x = Opair a (app f a)" 
          using a by (auto simp add: Repl)
        thus ?thesis using a 1 by (auto simp add: ZFfunDomainOpair)
      qed
  }
qed   

lemma ZFfunApp: 
  assumes "x |∈| A"
  shows   "(ZFfun A B f) |@| x = f x"
proof-
  have "(ZFfun A B f) |@| x = app (Lambda A f) x" by (simp add: ZFfun_def ZFfunApp_def Snd)
  also have "... = f x" using assms by (simp add: Lambda_app)
  finally show ?thesis .
qed

lemma ZFfun: 
  assumes "isZFfun f" 
  shows   "f = ZFfun ( |dom| f) ( |cod| f) (λx. f |@| x)"
proof(auto simp add: ZFfun_def)
  have "isOpair f ∧ isOpair (Fst f)" using assms by (simp add: isZFfun_def[of f] Let_def)
  hence "f = Opair (Opair (Fst (Fst f)) (Snd (Fst f))) (Snd f)" by (simp add: FstSnd)
  hence "f = Opair (Opair ( |dom| f) ( |cod| f)) (Snd f)" using assms by (simp add: ZFfunDom_def ZFfunCod_def)
  moreover have "Snd f = Lambda ( |dom| f) (λx . f |@| x)" 
  proof-
    have "|dom| f = Domain (Snd f)" using assms by (simp add: isZFfun_def[of f] Let_def)
    moreover have "isFun (Snd f)" using assms by (simp add: isZFfun_def[of f] Let_def)
    moreover have "(λx . f |@| x) = (λx . app (Snd f) x)"  by(simp add: ZFfunApp_def)
    moreover have "(Snd f) |⊆| (Domain (Snd f)) |×| (Range (Snd f))" using assms
      by (auto simp add: isZFfun_def[of f] Let_def)
    ultimately show ?thesis apply simp by(rule ZFFunToLambda[of "Snd f"])
  qed
  ultimately show "f = Opair (Opair ( |dom| f) ( |cod| f)) (Lambda ( |dom| f) (λx . f |@| x))" by simp
qed

lemma ZFfun_ext: 
  assumes "∀ x . x |∈| A --> f x = g x" 
  shows   "(ZFfun A B f) = (ZFfun A B g)"
proof-
  have "Lambda A f = Lambda A g" using assms by (auto simp add: Lambda_ext)
  thus ?thesis by (simp add: ZFfun_def)
qed

lemma ZFfunExt:
  assumes "|dom| f = |dom| g" and "|cod| f = |cod| g" and funf: "isZFfun f" and fung: "isZFfun g"
  and "!! x . x |∈| ( |dom| f) ==> f |@| x = g |@| x"
  shows "f = g"
proof-
  have 1: "f = ZFfun ( |dom| f) ( |cod| f) (λx. f |@| x)" using funf by (rule ZFfun)
  have "g = ZFfun ( |dom| g) ( |cod| g) (λx. g |@| x)" using fung by (rule ZFfun)
  hence 2: "g = ZFfun ( |dom| f) ( |cod| f) (λx. g |@| x)" using assms by simp
  have "ZFfun ( |dom| f) ( |cod| f) (λx. f |@| x) = ZFfun ( |dom| f) ( |cod| f) (λx. g |@| x)" 
    using assms by (simp add: ZFfun_ext)
  thus ?thesis using 1 2 by simp
qed  

lemma ZFfunDomAppCod: 
  assumes "isZFfun f"
  and     "x |∈| |dom|f"
  shows   "f |@| x |∈| |cod|f"
proof(simp add: ZFfunApp_def)
  have "app (Snd f) x |∈| Range (Snd f)" using assms by (auto simp add: fun_value_in_range )
  thus "app (Snd f) x |∈| |cod|f" using assms by (auto simp add: HOLZF.subset_def)
qed

lemma ZFfunComp: 
  assumes "∀ x . x |∈| A --> f x |∈| B"
  shows   "(ZFfun A B f) |o| (ZFfun B C g) = ZFfun A C (g o f)"
proof (simp add: ZFfunComp_def ZFfunDom ZFfunCod)
  {
    fix x assume a: "x |∈| A"
    have "ZFfun B C g  |@| (ZFfun A B f |@| x) = (g o f) x" 
      proof-
        have "(ZFfun A B f |@| x) = f x" using a by (simp add: ZFfunApp)
        hence "ZFfun B C g  |@| (ZFfun A B f |@| x) = g (f x)" using assms a by (simp add: ZFfunApp)
        thus ?thesis by simp
      qed
  }
  thus "ZFfun A C (λx. ZFfun B C g |@| (ZFfun A B f |@| x)) = ZFfun A C (g o f)"
    by (simp add: ZFfun_ext)
qed

lemma ZFfunCompApp: 
  assumes a:"isZFfun f" and b:"isZFfun g" and c:"|dom|g = |cod|f"
  shows "f |o| g = ZFfun ( |dom| f) ( |cod| g) (λ x . g |@| (f |@| x))"
proof-
  have 1: "f = ZFfun ( |dom| f) ( |cod| f) (λ x . f |@| x)" using a by (rule ZFfun)
  have 2: "g = ZFfun ( |dom| g) ( |cod| g) (λ x . g |@| x)" using b by (rule ZFfun)
  have 3: "∀ x . x |∈| |dom|f --> (λx. f |@| x) x |∈| |cod|f" using a by (simp add: ZFfunDomAppCod)
  hence 4: "∀ x . x |∈| |dom|f --> (λx. g |@| (f |@| x)) x |∈| |cod|g" 
    using a b c by (simp add: ZFfunDomAppCod)
  have "f |o| g = ZFfun ( |dom| f) ( |cod| f) (λ x . f |@| x) |o|
    ZFfun ( |cod| f) ( |cod| g) (λ x . g |@| x)" using 1 2 c by simp
  hence "f |o| g = ZFfun ( |dom| f) ( |cod| g) (λ x . g |@| (f |@| x))"
    using 3 by (simp add: ZFfunComp comp_def)
  thus ?thesis using 4 by (simp add: SETfun)
qed  

lemma ZFfunCompAppZFfun: 
  assumes "isZFfun f" and "isZFfun g" and "|dom|g = |cod|f"
  shows   "isZFfun (f |o| g)"
proof-
  have "f |o| g = ZFfun ( |dom| f) ( |cod| g) (λ x . g |@| (f |@| x))" using assms
    by (simp add: ZFfunCompApp)
  moreover have "∀ x . x |∈| |dom|f --> ((λ x . g |@| (f |@| x)) x) |∈| |cod|g" using assms
    by (simp add: ZFfunDomAppCod)
  ultimately show ?thesis by (simp add: SETfun)
qed

lemma ZFfunCompAssoc:
  assumes a: "isZFfun f" and b:"isZFfun h" and c:"|cod|g = |dom|h" 
  and d:"isZFfun g" and e:"|cod|f = |dom|g"
  shows "f |o| g |o| h = f |o| (g |o| h)"
proof-
  have 1: "f = ZFfun ( |dom| f) ( |cod| f) (λ x . f |@| x)" using a by (rule ZFfun)
  have 2: "g = ZFfun ( |dom| g) ( |cod| g) (λ x . g |@| x)" using d by (rule ZFfun)
  have 3: "h = ZFfun ( |dom| h) ( |cod| h) (λ x . h |@| x)" using b by (rule ZFfun)
  have 4: "∀ x . x |∈| |dom|f --> (λx. f |@| x) x |∈| |cod|f" using a by (simp add: ZFfunDomAppCod)
  have "(f |o| g) |o| h = ZFfun ( |dom| f) ( |cod| h) (λ x . h |@| (g |@| (f |@| x)))"
  proof-
    have 5: "∀ x . x |∈| |dom|f --> (λx. g |@| (f |@| x)) x |∈| |cod|g" 
      using 4 e d by (simp add: ZFfunDomAppCod)
    have "(f |o| g) |o| h = (ZFfun ( |dom| f) ( |cod| f) (λ x . f |@| x) |o|
      ZFfun ( |cod| f) ( |cod| g) (λ x . g |@| x)) |o|
      ZFfun ( |cod| g) ( |cod| h) (λ x . h |@| x)" 
      using 1 2 3 c e by (simp)
    thus ?thesis using 4 5 by (simp add: ZFfunComp comp_def)
  qed
  moreover have "f |o| (g |o| h) = ZFfun ( |dom| f) ( |cod| h) (λ x . h |@| (g |@| (f |@| x)))"
  proof-
    have 5: "∀ x . x |∈| |dom|g --> (λx. g |@| x) x |∈| |cod|g" using d by (simp add: ZFfunDomAppCod)
    have "f |o| (g |o| h) = ZFfun ( |dom| f) ( |dom| g) (λ x . f |@| x) |o|
      (ZFfun ( |dom| g) ( |cod| g) (λ x . g |@| x) |o|
      ZFfun ( |cod| g) ( |cod| h) (λ x . h |@| x))" 
      using 1 2 3 c e by (simp)
    thus ?thesis using 4 e 5 by (simp add: ZFfunComp comp_def)
  qed
  ultimately show ?thesis by simp
qed
  
lemma ZFfunCompAppDomCod: 
  assumes "isZFfun f" and "isZFfun g" and "|dom|g = |cod|f"
  shows   "|dom| (f |o| g) = |dom| f ∧ |cod| (f |o| g) = |cod| g"
proof-
  have "f |o| g = ZFfun ( |dom| f) ( |cod| g) (λ x . g |@| (f |@| x))" using assms
    by (simp add: ZFfunCompApp)
  thus ?thesis by (simp add: ZFfunDom ZFfunCod)
qed

lemma ZFfunIdLeft: 
  assumes a: "isZFfun f" shows "(ZFfun ( |dom|f) ( |dom|f) (λx. x)) |o| f = f"
proof-
  let ?g = "(ZFfun ( |dom|f) ( |dom|f) (λx. x))"
  have "ZFfun ( |dom| f) ( |cod| f) (λ x . f |@| x) = ?g |o| f" using a 
    by (simp add: ZFfun_ext ZFfunApp ZFfunCompApp SETfun ZFfunCod ZFfunDom)
  moreover have "f = ZFfun ( |dom| f) ( |cod| f) (λ x . f |@| x)" using a by (rule ZFfun)
  ultimately show ?thesis by simp
qed

lemma ZFfunIdRight:
  assumes a: "isZFfun f" shows "f |o| (ZFfun ( |cod|f) ( |cod|f) (λx. x)) = f"
proof-
  let ?g = "(ZFfun ( |cod|f) ( |cod|f) (λx. x))"
  have 1: "∀ x . x |∈| |dom|f --> (λx. f |@| x) x |∈| |cod|f" using a by (simp add: ZFfunDomAppCod)
  have "ZFfun ( |dom| f) ( |cod| f) (λ x . f |@| x) = f |o| ?g" using a 1
    by (simp add: ZFfun_ext ZFfunApp ZFfunCompApp SETfun ZFfunCod ZFfunDom)
  moreover have "f = ZFfun ( |dom| f) ( |cod| f) (λ x . f |@| x)" using a by (rule ZFfun)
  ultimately show ?thesis by simp
qed

lemma SETCategory: "Category(SET)"
proof-
  have "Category_axioms SET'"  
    by (auto simp add: Category_axioms_def SET'_def ZFfunCompAppDomCod 
      ZFfunCompAppZFfun ZFfunCompAssoc ZFfunIdLeft ZFfunIdRight ZFfunDom ZFfunCod SETfun MapsTo_def CompDefined_def)
  thus ?thesis by (auto simp add: SET_def MakeCat)
qed

lemma SETobj: "X ∈ Obj (SET)"
by (simp add: SET_def SET'_def MakeCat_def)

lemma SETcod: "isZFfun (ZFfun A B f) ==> codSET ZFfun A B f = B"
by(simp add: SET_def MakeCat_def SET'_def ZFfunCod)

lemma SETmor: "(isZFfun f) = (f ∈ morSET)"
by(simp add: SET_def MakeCat_def SET'_def)

lemma SETdom: "isZFfun (ZFfun A B f) ==> domSET ZFfun A B f = A"
by(simp add: SET_def MakeCat_def SET'_def ZFfunDom)

lemma SETId: assumes "x |∈| X" shows "(Id SET X) |@| x = x"
proof-
  have "X ∈ Obj SET" by (simp add: SET_def SET'_def MakeCat_def)
  hence "isZFfun(Id SET X)" by (simp add: SETCategory Category.CatIdInMor SETmor)
  moreover have "(Id SET X) = ZFfun X X (λx. x)" using assms by (simp add: SET_def SET'_def MakeCat_def)
  ultimately show ?thesis using assms by (simp add: ZFfunApp)
qed

lemma SETCompE[elim]: "[|f ≈>SET g ; [|isZFfun f ; isZFfun g ; |cod| f = |dom| g|] ==> R|] ==> R"
by (auto simp add: SET_def SET'_def MakeCat_def)

lemma SETmapsTo: "f mapsSET X to Y ==> isZFfun f ∧ |dom| f = X ∧ |cod| f = Y"
by(auto simp add: MapsTo_def SET_def SET'_def MakeCat_def)

lemma SETComp: assumes "f ≈>SET g" shows "f ;;SET g = f |o| g"
proof-
  have a: "f ≈>MakeCat SET' g" using assms by (simp add: SET_def)
  have "f ;;SET g = f ;;MakeCat SET' g" by (simp add: SET_def)
  also have "... = f ;;SET' g" using a  by (simp  add: MakeCatComp2)
  finally show ?thesis by (simp add: SET'_def)
qed

lemma SETCompAt:
  assumes "f ≈>SET g" and "x |∈|  |dom| f" shows "(f ;;SET g) |@| x = g |@| (f |@| x)"
proof-
  have "f ;;SET g = f |o| g" using assms by (simp add: SETComp)
  also have "... = ZFfun ( |dom| f) ( |cod| g) (λ x . g |@| (f |@| x))" using assms by (auto simp add: ZFfunCompApp)
  finally show ?thesis using assms by (simp add: ZFfunApp)
qed

lemma SETZFfun: 
  assumes "f mapsSET X to Y" shows "f = ZFfun X Y (λx . f |@| x)"
proof-
  have "isZFfun f"  using assms by (auto simp add: SETmor)
  hence "f = ZFfun ( |dom| f) ( |cod| f) (λx. f |@| x)" by (simp add: ZFfun)
  moreover have "|dom| f = X" and "|cod| f = Y" using assms by (auto simp add: SET_def SET'_def MakeCat_def)
  ultimately show ?thesis by (simp)
qed  

lemma SETfunDomAppCod:
  assumes "f mapsSET X to Y" and "x |∈| X"
  shows "f |@| x |∈| Y"
proof-
  have 1: "isZFfun f" and "|dom| f = X" and 2: "|cod| f = Y" using assms by (auto simp add: SETmapsTo)
  hence "x |∈| |dom| f" using assms by simp
  hence "f |@| x |∈| |cod| f" using 1 by (simp add: ZFfunDomAppCod)  
  thus ?thesis using 2 by simp
qed

(*Locally Small Category has an injective map from the morphisms to ZF*)
record ('o,'m) LSCategory = "('o,'m) Category" +
  mor2ZF :: "'m => ZF" ("m2z\<index>_" [70] 70)

definition 
  ZF2mor ("z2m\<index>_" [70] 70) where
  "ZF2mor C f ≡ THE m . m ∈ morC ∧ m2zC m = f"

definition
  "HOMCollection C X Y ≡ {m2zC f | f . f mapsC X to Y}"

definition
  HomSet ("Hom\<index> _ _" [65, 65] 65)  where
  "HomSet C X Y ≡ implode (HOMCollection C X Y)"

locale LSCategory = Category +
  assumes mor2ZFInj: "[|x ∈ mor ; y ∈ mor ; m2z x = m2z y|] ==> x = y"
  and HOMSetIsSet: "[|X ∈ obj ; Y ∈ obj|] ==> HOMCollection C X Y ∈ range explode"
  and m2zExt: "mor2ZF C ∈ extensional (Mor C)"

lemma [elim]: "[|LSCategory C ; 
  [|Category C ; [|x ∈ morC ; y ∈ morC ; m2zC x = m2zC y|] ==>  x = y;
  [|X ∈ objC ; Y ∈ objC|] ==> HOMCollection C X Y ∈ range explode|] ==> R|] ==> R"
by(simp add: LSCategory_def LSCategory_axioms_def)

definition
  HomFtorMap :: "('o,'m,'a) LSCategory_scheme => 'o => 'm => ZF" ("Hom\<index>[_,_]" [65,65] 65) where
  "HomFtorMap C X g ≡ ZFfun (HomC X (domC g)) (HomC X (codC g)) (λ f . m2zC ((z2mC f) ;;C g))"

definition 
  HomFtor' :: "('o,'m,'a) LSCategory_scheme => 'o => 
      ('o,ZF,'m,ZF,(|mor2ZF :: 'm => ZF, … :: 'a|)),,unit) Functor" ("HomP\<index>[_,\<emdash>]" [65] 65) where
  "HomFtor' C X ≡ (|
        CatDom = C, 
        CatCod = SET ,
        MapM   = λ g . HomC[X,g]
  |)),"

definition HomFtor ("Hom\<index>[_,\<emdash>]" [65] 65) where "HomFtor C X ≡ MakeFtor (HomFtor' C X)"

lemma [simp]: "LSCategory C ==> Category C"
  by (simp add: LSCategory_def)

lemma (in LSCategory) m2zz2m: 
  assumes "f maps X to Y" shows "(m2z f) |∈| (Hom X Y)"
proof-
  have "X ∈ Obj C" and "Y ∈ Obj C" using assms by (simp add: MapsToObj)+
  hence "HOMCollection C X Y ∈ range explode" using assms by (simp add: HOMSetIsSet)
  moreover have "(m2z f) ∈ HOMCollection C X Y" using assms by (auto simp add: HOMCollection_def)
  ultimately have "(m2z f) |∈| implode (HOMCollection C X Y)" by (simp add: Elem_implode)
  thus ?thesis by (simp add: HomSet_def) 
qed

lemma (in LSCategory) m2zz2mInv: 
  assumes "f ∈ mor"
  shows "z2m (m2z f) = f"
proof-
  have 1: "f ∈ mor ∧ m2z f = m2z f" using assms by simp
  moreover have "∃! m . m ∈ mor ∧ m2z m = (m2z f)" 
  proof(rule ex_ex1I)
    show "∃ m . m ∈ mor ∧ m2z m = (m2z f)" 
      by(rule exI[of _ f], insert 1, simp)
    {
      fix m y assume "m ∈ mor ∧ m2z m = (m2z f)" and "y ∈ mor ∧ m2z y = (m2z f)"
      thus "m = y" by(simp add: mor2ZFInj)
    }
  qed
  ultimately show ?thesis by(simp add: ZF2mor_def the1_equality)
qed

lemma (in LSCategory) z2mm2z: 
  assumes "X ∈ obj" and "Y ∈ obj" and "f |∈| (Hom X Y)"
  shows "z2m f maps X to Y ∧ m2z (z2m f) = f"
proof-
  have 1: "∃ m . m maps X to Y ∧ m2z m = f"
  proof-
    have "HOMCollection C X Y ∈ range explode" using assms by (simp add: HOMSetIsSet)
    moreover have "f |∈| implode (HOMCollection C X Y)" using assms(3) by (simp add: HomSet_def)
    ultimately have "f ∈ HOMCollection C X Y" by (simp add: HOLZF.Elem_implode)
    thus ?thesis by (auto simp add: HOMCollection_def)
  qed
  have 2: "∃! m . m ∈ mor ∧ m2z m = f" 
  proof(rule ex_ex1I)
    show "∃ m . m ∈ mor ∧ m2z m = f"
    proof-
      from 1 obtain m where "m ∈ mor ∧ m2z m = f" by auto
      thus ?thesis by auto
    qed
    {
      fix m y assume "m ∈ mor ∧ m2z m = f" and "y ∈ mor ∧ m2z y = f"
      thus "m = y" by(simp add: mor2ZFInj)
    }
  qed
  thus ?thesis
  proof-
    from 1 obtain a where 3: "a maps X to Y ∧ m2z a = f" by auto
    have 4: "a ∈ mor" using 3 by auto
    have "z2m f = a" 
      apply (auto simp add: 3 ZF2mor_def[of _ f])
      apply (rule the1_equality[of "λ m . m ∈ mor ∧ m2z m = f" a])
      apply (auto simp add: 2 3 4)
      done
    thus ?thesis by (simp add: 3)
  qed
qed

lemma  HomFtorMapLemma1: 
  assumes a: "LSCategory C" and b: "X ∈ objC" and c: "f ∈ morC" and d: "x |∈| (HomC X (domC f))"
  shows "(m2zC ((z2mC x) ;;C f)) |∈| (HomC X (codC f))"
proof-
  have 1: "domC f ∈ objC" and 2: "codC f ∈ objC" using a c by (simp add: Category.Simps)+
  have "z2mC x mapsC X to (domC f)"  using a b d 1 by (auto simp add: LSCategory.z2mm2z)
  hence "(z2mC x) ;;C f mapsC X to (codC f)" using a c by (auto intro: Category.Ccompt)
  hence "(m2zC ((z2mC x) ;;C f)) |∈| (HomC X (codC f))" using a b d 2 
    by (auto simp add: LSCategory.m2zz2m)
  thus ?thesis using c by (simp add: Category.Simps)
qed

lemma HomFtorInMor':
  assumes "LSCategory C" and "X ∈ objC" and "f ∈ morC"
  shows "HomC[X,f] ∈ morSET'" 
proof(simp add: HomFtorMap_def)
  {
    fix x assume "x |∈| (HomC X domC f)" 
    hence "m2zC ((z2mC x) ;;C f) |∈| (HomC X codC f)" using assms by (blast intro: HomFtorMapLemma1)
  }
  hence "∀ x . x |∈| (HomC X domC f) --> (m2zC ((z2mC x) ;;C f)) |∈| (HomC X codC f)" by (simp)
  hence "isZFfun (ZFfun (HomC X domC f) (HomC X codC f) (λ x . m2zC ((z2mC x) ;;C f)))"
    by (simp add: SETfun)
  thus "ZFfun (HomC X domC f) (HomC X codC f) (λ x . m2zC ((z2mC x) ;;C f)) ∈ morSET'"
    by (simp add: SET'_def)
qed

lemma HomFtorMor':
  assumes "LSCategory C" and "X ∈ objC" and "f ∈ morC"
  shows   "HomC[X,f] mapsSET' HomC X (domC f) to HomC X (codC f)"  
proof-
  have "HomC[X,f] ∈ morSET'" using assms by (simp add: HomFtorInMor')
  moreover have "domSET' (HomC[X,f]) = HomC X (domC f)"
    by(simp add: HomFtorMap_def SET'_def ZFfunDom)
  moreover have "codSET' (HomC[X,f]) = HomC X (codC f)"
    by(simp add: HomFtorMap_def SET'_def ZFfunCod)
  ultimately show ?thesis by (auto simp add: SET_def)
qed

lemma HomFtorMapsTo:
  "[|LSCategory C ; X ∈ objC ; f ∈ morC |] ==> HomC[X,f] mapsSET HomC X (domC f) to HomC X (codC f)"
by (simp add: HomFtorMor' SET_def MakeCatMapsTo)

lemma HomFtorMor:
  assumes "LSCategory C" and "X ∈ objC" and "f ∈ morC" 
  shows "HomC[X,f] ∈ Mor SET" and "domSET (HomC[X,f]) = HomC X (domC f)" 
  and "codSET (HomC[X,f]) = HomC X (codC f)"
proof-
  have "HomC[X,f] mapsSET HomC X (domC f) to HomC X (codC f)" using assms by (simp add: HomFtorMapsTo)
  thus "HomC[X,f] ∈ Mor SET" and "domSET (HomC[X,f]) = HomC X (domC f)" and "codSET (HomC[X,f]) = HomC X (codC f)"
    by auto
qed

lemma HomFtorCompDef':
  assumes "LSCategory C" and "X ∈ objC" and "f ≈>C g" 
  shows   "(HomC[X,f]) ≈>SET' (HomC[X,g])"
proof(rule CompDefinedI)
  have a: "f ∈ morC" and b: "g ∈ morC" using assms(3) by auto 
  thus "HomC[X,f] ∈ morSET'" and "HomC[X,g] ∈ morSET'" using assms by (simp add:HomFtorInMor')+
  have "(HomC[X,f]) mapsSET' HomC X domC f to HomC X codC f"
    and "(HomC[X,g]) mapsSET' HomC X domC g to HomC X codC g" using assms a b by (simp add: HomFtorMor')+
  hence "codSET' (HomC[X,f]) = HomC X (codC f)" 
    and "domSET' (HomC[X,g]) = HomC X (domC g)" by auto
  moreover have "(codC f) = (domC g)" using assms(3) by auto
  ultimately show "codSET' (HomC[X,f]) = domSET' (HomC[X,g])" by simp
qed

lemma HomFtorDist': 
  assumes a: "LSCategory C" and b: "X ∈ objC" and c: "f ≈>C g"
  shows   "(HomC[X,f]) ;;SET' (HomC[X,g]) = HomC[X,f ;;C g]"
proof-
  let ?A = "(HomC X domC f)"
  let ?B = "(HomC X domC g)"
  let ?C = "(HomC X codC g)"
  let ?f = "(λh. m2zC ((z2mC h) ;;C f))"
  let ?g = "(λf. m2zC ((z2mC f) ;;C g))"
  have 1: "codC f = domC g" using c by auto
  have 2: "domC (f ;;C g) = domC f" and 3: "codC (f ;;C g) = codC g" using assms 
    by (auto simp add: Category.MapsToMorDomCod)
  have "(HomC[X,f]) ;;SET' (HomC[X,g]) = (ZFfun ?A (HomC X codC f) ?f) |o| (ZFfun ?B ?C ?g)" 
    by (simp add: HomFtorMap_def SET'_def)
  also have "... = (ZFfun ?A ?B ?f) |o| (ZFfun ?B ?C ?g)" using 1 by simp
  also have "... = ZFfun ?A ?C (?g o ?f)" 
  proof(rule ZFfunComp, rule allI, rule impI)
    {
      fix h assume aa: "h |∈| ?A" show "?f h |∈| ?B"
      proof-
        have "f ∈ morC" using assms by auto
        hence "?f h |∈| (HomC X codC f)" using assms aa by (simp add: HomFtorMapLemma1)
        thus ?thesis using 1 by simp
      qed
    }
  qed
  also have "... = ZFfun ?A ?C (λh. m2zC ((z2mC h) ;;C (f ;;C g)))"
  proof(rule ZFfun_ext, rule allI, rule impI, simp add: comp_def)
    {
      fix h assume aa: "h |∈| ?A" 
      show "m2zC ((z2mC (m2zC((z2mC h) ;;C f))) ;;C g) = m2zC ((z2mC h) ;;C (f ;;C g))"
      proof-
        have bb: "(z2mC h) ≈>C f" 
        proof(rule CompDefinedI)
          show "f ∈ morC" using c by auto
          hence "domC f ∈ objC" using a by (simp add: Category.Cdom)
          hence "(z2mC h) mapsC X to domC f" using assms aa by (simp add: LSCategory.z2mm2z)
          thus "(z2mC h) ∈ morC" and "codC (z2mC h) = domC f" by auto
        qed
        hence "(z2mC h) ;;C f ∈ morC" using a by (simp add: Category.MapsToMorDomCod)
        hence "z2mC (m2zC ((z2mC h) ;;C f)) = (z2mC h) ;;C f" using a by (simp add: LSCategory.m2zz2mInv)
        hence "m2zC ((z2mC (m2zC((z2mC h) ;;C f))) ;;C g) = m2zC (((z2mC h) ;;C f) ;;C g)" by simp
        also have "... = m2zC ((z2mC h) ;;C (f ;;C g))" using bb c a by (simp add: Category.Cassoc)
        finally show ?thesis .
      qed
    }
  qed
  also have "... = ZFfun (HomC X domC (f ;;C g)) (HomC X codC (f ;;C g)) (λh. m2zC ((z2mC h) ;;C (f ;;C g)))"
    using 2 3 by simp
  also have "... = HomC[X,f ;;C g]" by (simp add:  HomFtorMap_def)
  finally show ?thesis by (auto simp add: SET_def)
qed

lemma HomFtorDist:
  assumes "LSCategory C" and "X ∈ objC" and "f ≈>C g"
  shows   "(HomC[X,f]) ;;SET (HomC[X,g]) = HomC[X,f ;;C g]"
proof-
  have "(HomC[X,f]) ;;SET' (HomC[X,g]) = HomC[X,f ;;C g]" using assms by (simp add: HomFtorDist')
  moreover have "(HomC[X,f]) ≈>SET' (HomC[X,g])" using assms by (simp add: HomFtorCompDef')
  ultimately show ?thesis by (simp add: MakeCatComp SET_def)
qed

lemma HomFtorId':
  assumes a: "LSCategory C" and b: "X ∈ objC" and c: "Y ∈ objC"
  shows   "HomC[X,idC Y] = idSET' (HomC X Y)"
proof-
  have "(idC Y) mapsC Y to Y" using a c by (simp add: Category.Simps)
  hence 1: "(domC (idC Y)) = Y" and 2: "(codC (idC Y)) = Y" by auto
  have "HomC[X,idC Y] = ZFfun (HomC X (domC (idC Y))) (HomC X (codC (idC Y))) (λ f . m2zC ((z2mC f) ;;C (idC Y)))"
    by (simp add: HomFtorMap_def)
  also have "... = ZFfun (HomC X Y) (HomC X Y) (λ f . m2zC ((z2mC f) ;;C (idC Y)))" using 1 2 by simp
  also have "... = ZFfun (HomC X Y) (HomC X Y) (λ f . f)" 
  proof(rule ZFfun_ext, rule allI, rule impI)
    {
      fix h assume aa: "h |∈| (HomC X Y)" show "m2zC ((z2mC h) ;;C (idC Y)) = h"
      proof-
        have "(z2mC h) mapsC X to Y" and bb: "m2zC (z2mC h) = h" 
          using assms aa by (simp add: LSCategory.z2mm2z)+
        hence "(z2mC h) ;;C (idC Y) = (z2mC h)" using a by (auto simp add: Category.Simps)
        hence "m2zC ((z2mC h) ;;C (idC Y)) = m2zC (z2mC h)" by simp
        also have "... = h" using bb .
        finally show ?thesis .
      qed
    }
  qed
  finally show ?thesis by (simp add: SET'_def)
qed

lemma HomFtorId: 
  assumes "LSCategory C" and "X ∈ objC" and "Y ∈ objC"
  shows   "HomC[X,idC Y] = idSET (HomC X Y)"
proof-
  have "HomC[X,idC Y] = idSET' (HomC X Y)" using assms by (simp add: HomFtorId')
  moreover have "(HomC X Y) ∈ objSET'" by (simp add: SET'_def)
  ultimately show ?thesis by (simp add: MakeCatId SET_def)
qed

lemma HomFtorObj':
  assumes a: "LSCategory C"
  and     b: "PreFunctor (HomPC[X,\<emdash>])"  and c: "X ∈ objC" and d: "Y ∈ objC"
  shows   "(HomPC[X,\<emdash>]) @@ Y = HomC X Y" 
proof-
  let ?F = "(HomFtor' C X)"
  have "?F ## (idCatDom ?F Y) = HomC[X,idC Y]" by (simp add: HomFtor'_def)
  also have "... = idCatCod ?F (HomC X Y)" using assms by (simp add: HomFtorId HomFtor'_def)
  finally have "?F ## (idCatDom ?F Y) = idCatCod ?F (HomC X Y)" by simp
  moreover have "HomC X Y ∈ objCatCod ?F" using assms 
    by (simp add: HomFtorId HomFtor'_def SET_def SET'_def MakeCatObj)
  moreover have "Y ∈ objCatDom ?F" using d by (simp add: HomFtor'_def)
  ultimately show ?thesis using b by(simp add: PreFunctor.FmToFo[of ?F Y "HomC X Y"])
qed

lemma HomFtorFtor': 
  assumes a: "LSCategory C"
  and     b: "X ∈ objC"
  shows   "FunctorM (HomPC[X,\<emdash>])"
proof(intro_locales)
  show PF: "PreFunctor (HomPC[X,\<emdash>])"
  proof(auto simp add: HomFtor'_def PreFunctor_def SETCategory a HomFtorDist b)
    {
      fix Z assume aa: "Z ∈ objC" 
      show "∃ Y ∈ objSET . HomC[X,idC Z] = idSET Y"
      proof(rule_tac x="HomC X Z" in Set.rev_bexI)
        show "HomC X Z ∈ objSET" by (simp add: SET_def SET'_def MakeCatObj) 
        show "HomC[X,idC Z] = idSET (HomC X Z)" using assms aa by(simp add:HomFtorId)
      qed
    }
  qed
  {
    fix f Z Y assume aa: "f mapsC Z to Y" 
    have "(HomPC[X,\<emdash>]) ## f mapsSET ((HomPC[X,\<emdash>]) @@ Z) to ((HomPC[X,\<emdash>]) @@ Y)" 
    proof-
      have bb: "Z ∈ objC" and cc: "Y ∈ objC" using aa a by (simp add: Category.MapsToObj)+
      have dd: "domC f = Z" and ee: "codC f = Y" and ff: "f ∈ morC" using aa by auto
      have "(HomPC[X,\<emdash>]) ## f = HomC[X,f]" by (simp add: HomFtor'_def)
      moreover have "(HomPC[X,\<emdash>]) @@ Z = HomC X Z" 
        and "(HomPC[X,\<emdash>]) @@ Y = HomC X Y" using assms bb cc PF by (simp add: HomFtorObj')+
      moreover have "HomC[X,f] mapsSET (HomC X (domC f)) to (HomC X (codC f))" 
        using assms ff by (simp add: HomFtorMapsTo)
      ultimately show ?thesis using dd ee by simp
    qed
  }
  thus "FunctorM_axioms (HomPC[X,\<emdash>])" using PF by (auto simp add: FunctorM_axioms_def HomFtor'_def)
qed

lemma HomFtorFtor: 
  assumes a: "LSCategory C"
  and     b: "X ∈ objC"
  shows   "Functor (HomC[X,\<emdash>])"
proof-
  have "FunctorM (HomPC[X,\<emdash>])" using assms by (rule HomFtorFtor')
  thus ?thesis by (simp add: HomFtor_def MakeFtor)
qed 

lemma HomFtorObj:
  assumes "LSCategory C"
  and     "X ∈ objC" and "Y ∈ objC"
  shows   "(HomC[X,\<emdash>]) @@ Y = HomC X Y"
proof-
  have "FunctorM (HomPC[X,\<emdash>])" using assms by (simp add: HomFtorFtor')
  hence 1: "PreFunctor (HomPC[X,\<emdash>])" by (simp add: FunctorM_def)
  moreover have "CatDom (HomPC[X,\<emdash>]) = C" by (simp add: HomFtor'_def)
  ultimately have "(HomC[X,\<emdash>]) @@ Y = (HomPC[X,\<emdash>]) @@ Y" using assms by (simp add: MakeFtorObj HomFtor_def)
  thus ?thesis using assms 1 by (simp add: HomFtorObj')
qed

definition
  HomFtorMapContra :: "('o,'m,'a) LSCategory_scheme => 'm => 'o => ZF" ("HomC\<index>[_,_]" [65,65] 65) where
  "HomFtorMapContra C g X ≡ ZFfun (HomC (codC g) X) (HomC (domC g) X) (λ f . m2zC (g ;;C (z2mC f)))"

definition 
  HomFtorContra' :: "('o,'m,'a) LSCategory_scheme => 'o => 
      ('o,ZF,'m,ZF,(|mor2ZF :: 'm => ZF, … :: 'a|)),,unit) Functor" ("HomP\<index>[\<emdash>,_]" [65] 65) where
  "HomFtorContra' C X ≡ (|
        CatDom = (Op C), 
        CatCod = SET ,
        MapM   = λ g . HomCC[g,X]
  |)),"

definition HomFtorContra ("Hom\<index>[\<emdash>,_]" [65] 65) where "HomFtorContra C X ≡ MakeFtor(HomFtorContra' C X)"

lemma HomContraAt: "x |∈| (HomC (codC f) X) ==> (HomCC[f,X]) |@| x = m2zC (f ;;C (z2mC x))"
  by (simp add: HomFtorMapContra_def ZFfunApp)

lemma mor2ZF_Op: "mor2ZF (Op C) = mor2ZF C"  
apply (cases C)
apply (simp add: OppositeCategory_def)
done

lemma mor_Op: "morOp C = morC" by (simp add: OppositeCategory_def)
lemma obj_Op: "objOp C = objC" by (simp add: OppositeCategory_def)

lemma ZF2mor_Op: "ZF2mor (Op C) f = ZF2mor C f"
by (simp add: ZF2mor_def mor2ZF_Op mor_Op)

lemma mapsTo_Op: "f mapsOp C Y to X = f mapsC X to Y"
by (auto simp add: OppositeCategory_def mor_Op MapsTo_def)

lemma HOMCollection_Op: "HOMCollection (Op C) X Y = HOMCollection C Y X"
by (simp add: HOMCollection_def mapsTo_Op mor2ZF_Op)

lemma Hom_Op: "HomOp C X Y = HomC Y X"
by (simp add: HomSet_def HOMCollection_Op)

lemma HomFtorContra': "HomPC[\<emdash>,X] = HomPOp C[X,\<emdash>]"
apply (simp add:  HomFtorContra'_def 
                      HomFtor'_def HomFtorMapContra_def HomFtorMap_def mor2ZF_Op ZF2mor_Op Hom_Op)
by (simp add: OppositeCategory_def)

lemma HomFtorContra: "HomC[\<emdash>,X] = HomOp C[X,\<emdash>]"
by (auto simp add: HomFtorContra' HomFtorContra_def HomFtor_def)

lemma HomFtorContraDom: "CatDom (HomC[\<emdash>,X]) = Op C"
by(simp add: HomFtorContra_def HomFtorContra'_def MakeFtor_def)

lemma HomFtorContraCod: "CatCod (HomC[\<emdash>,X]) = SET"
by(simp add: HomFtorContra_def HomFtorContra'_def MakeFtor_def)

lemma LSCategory_Op: assumes "LSCategory C" shows "LSCategory (Op C)"
proof(auto simp only: LSCategory_def)
  show "Category (Op C)" using assms by (simp add: OpCatCat)
  show "LSCategory_axioms (Op C)" using assms
    by (simp add: LSCategory_axioms_def mor_Op obj_Op mor2ZF_Op HOMCollection_Op 
                     LSCategory.mor2ZFInj LSCategory.HOMSetIsSet LSCategory.m2zExt)
qed

lemma HomFtorContraFtor:
  assumes "LSCategory C"
  and     "X ∈ objC"
  shows   "Ftor (HomC[\<emdash>,X]) : (Op C) --> SET"
proof(auto simp only: functor_abbrev_def)
  show "Functor (HomC[\<emdash>,X])"
  proof-
    have "HomC[\<emdash>,X] = HomOp C[X,\<emdash>]" by (simp add: HomFtorContra)
    moreover have "LSCategory (Op C)" using assms by (simp add: LSCategory_Op)
    moreover have "X ∈ objOp C" using assms by (simp add: OppositeCategory_def)
    ultimately show ?thesis using assms by (simp add: HomFtorFtor)
  qed
  show "CatDom (HomC[\<emdash>,X]) = Op C" by(simp add: HomFtorContra_def HomFtorContra'_def MakeFtor_def)
  show "CatCod (HomC[\<emdash>,X]) = SET" by(simp add: HomFtorContra_def HomFtorContra'_def MakeFtor_def)
qed

lemma HomFtorOpObj:
  assumes "LSCategory C"
  and     "X ∈ objC" and "Y ∈ objC"
  shows   "(HomC[\<emdash>,X]) @@ Y = HomC Y X"
proof-
  have 1: "X ∈ Obj (Op C)" and 2: "Y ∈ Obj (Op C)" using assms by (simp add: OppositeCategory_def)+
  have "(HomC[\<emdash>,X]) @@ Y = (HomOp C[X,\<emdash>]) @@ Y" by (simp add: HomFtorContra)
  also have "... = (HomOp C X Y)" using assms(1) 1 2 by (simp add: LSCategory_Op HomFtorObj)
  also have "... = (HomC Y X)" by (simp add: Hom_Op)
  finally show ?thesis .
qed
  

lemma HomCHomOp: "HomCC[g,X] = HomOp C[X,g]"
apply (simp add:  HomFtorContra'_def 
                      HomFtor'_def HomFtorMapContra_def HomFtorMap_def mor2ZF_Op ZF2mor_Op Hom_Op)
by (simp add: OppositeCategory_def)

lemma HomFtorContraMapsTo:
  assumes "LSCategory C" and "X ∈ objC" and "f ∈ morC" 
  shows "HomCC[f,X] mapsSET HomC (codC f) X  to HomC (domC f) X"
proof-
  have "LSCategory (Op C)" using assms by(simp add: LSCategory_Op)
  moreover have "X ∈ Obj (Op C)" using assms by (simp add: OppositeCategory_def)
  moreover have "f ∈ Mor (Op C)" using assms by (simp add: OppositeCategory_def)
  ultimately have "HomOp C[X,f] mapsSET HomOp C X (domOp C f) to HomOp C X (codOp C f)" using assms
    by (simp add: HomFtorMapsTo)
  moreover have "HomCC[f,X] = HomOp C[X,f]" by (simp add: HomCHomOp)
  moreover have "HomOp C X (domOp C f) = HomC (codC f) X" 
  proof-
    have "HomOp C X (domOp C f) = HomC (domOp C f) X" by (simp add: Hom_Op)
    thus ?thesis by (simp add:  OppositeCategory_def)
  qed
  moreover have "HomOp C X (codOp C f) = HomC (domC f) X"
  proof-
    have "HomOp C X (codOp C f) = HomC (codOp C f) X" by (simp add: Hom_Op)
    thus ?thesis by (simp add:  OppositeCategory_def)
  qed
  ultimately show ?thesis by simp
qed

lemma HomFtorContraMor:
  assumes "LSCategory C" and "X ∈ objC" and "f ∈ morC" 
  shows "HomCC[f,X] ∈ Mor SET" and "domSET (HomCC[f,X]) = HomC (codC f) X" 
  and "codSET (HomCC[f,X]) = HomC (domC f) X"
proof-
  have "HomCC[f,X] mapsSET HomC (codC f) X  to HomC (domC f) X" using assms by (simp add: HomFtorContraMapsTo)
  thus "HomCC[f,X] ∈ Mor SET" and "domSET (HomCC[f,X]) = HomC (codC f) X" 
  and "codSET (HomCC[f,X]) = HomC (domC f) X"
    by auto
qed

lemma HomContraMor:
  assumes "LSCategory C" and "f ∈ Mor C" 
  shows "(HomC[\<emdash>,X]) ## f = HomCC[f,X]"
by(simp add: HomFtorContra_def HomFtorContra'_def MakeFtor_def assms OppositeCategory_def) 



(*This is used in the proof of the naturality of the Yoneda trans*)
lemma HomCHom:
  assumes "LSCategory C" and "f ∈ Mor C" and "g ∈ Mor C"
  shows "(HomCC[g,domC f]) ;;SET (HomC[domC g,f]) = (HomC[codC g,f]) ;;SET (HomCC[g,codC f])"
proof-
  have ObjDf: "domC f ∈ objC" and ObjDg: "domC g ∈ objC" using assms by (simp add: Category.Cdom)+
  have ObjCg: "codC g ∈ objC" and ObjCf: "codC f ∈ objC" using assms by (simp add: Category.Ccod)+
  have "(HomCC[g,domC f]) ;;SET (HomC[domC g,f]) = (HomCC[g,domC f]) |o| (HomC[domC g,f])" 
  proof-
    have "(HomCC[g,domC f]) ≈>SET (HomC[domC g,f])" 
    proof(rule CompDefinedI)
      show "HomC[domC g,f] ∈ Mor SET" using assms ObjDg by (simp add: HomFtorMor)
      show "HomCC[g,domC f] ∈ Mor SET" using assms ObjDf by (simp add: HomFtorContraMor)
      show "codSET (HomCC[g,domC f]) = domSET (HomC[domC g,f])" using assms ObjDg ObjDf
        by (simp add: HomFtorMor HomFtorContraMor)
    qed
    thus ?thesis by(simp add: SET_def SET'_def MakeCatComp2)
  qed
  also have "... = ZFfun (HomC (codC g) (domC f)) (HomC (domC g) (codC f)) 
              ((λ h . m2zC ((z2mC h) ;;C f)) o (λ h . m2zC (g ;;C (z2mC h))))" 
  proof(simp add: HomFtorMapContra_def HomFtorMap_def, rule ZFfunComp, rule allI, rule impI)
    {
      fix x assume aa: "x |∈| (HomC (codC g) (domC f))"
      show "(m2zC (g ;;C (z2mC x))) |∈| (HomC (domC g) (domC f))"
      proof(rule LSCategory.m2zz2m, simp_all add: assms(1) ObjDg ObjDf)
        have "g mapsC (domC g) to (codC g)" using assms by auto
        moreover have "(z2mC x) mapsC (codC g) to (domC f)" using aa ObjCg ObjDf assms(1) 
          by (simp add: LSCategory.z2mm2z)
        ultimately show "g ;;C (z2mC x) mapsC (domC g) to (domC f)" using assms(1)
          by (simp add: Category.Ccompt)
      qed
    }
  qed
  also have "... = ZFfun (HomC (codC g) (domC f)) (HomC (domC g) (codC f)) 
              ((λ h . m2zC (g ;;C (z2mC h))) o (λ h . m2zC ((z2mC h) ;;C f)))" 
  proof(rule ZFfun_ext, rule allI, rule impI)
    {
      fix h assume aa: "h |∈| (HomC (codC g) (domC f))"
      show "((λ h . m2zC ((z2mC h) ;;C f)) o (λ h . m2zC (g ;;C (z2mC h)))) h = 
        ((λ h . m2zC (g ;;C (z2mC h))) o (λ h . m2zC ((z2mC h) ;;C f))) h"
      proof-
        have MapsTo1: "(z2mC h) mapsC (codC g) to (domC f)" using assms(1) ObjCg ObjDf aa by (simp add: LSCategory.z2mm2z)
        have CompDef1: "(z2mC h) ≈>C f"
        proof(rule CompDefinedI)
          show "f ∈ morC" using assms by simp
          show "(z2mC h) ∈ morC" and "codC (z2mC h) = domC f" using MapsTo1 by auto
        qed
        have CompDef2: "g ≈>C (z2mC h)"
        proof(rule CompDefinedI)
          show "g ∈ morC" using assms by simp
          thus "(z2mC h) ∈ morC" and "codC g = domC (z2mC h)" using MapsTo1 by auto
        qed
        have c1: "(z2mC h) ;;C f ∈ Mor C" using assms CompDef1 by (simp add: Category.MapsToMorDomCod)
        have c2: "g ;;C (z2mC h) ∈ Mor C" using assms CompDef2 by (simp add: Category.MapsToMorDomCod)
        have "g ;;C (z2mC (m2zC ((z2mC h) ;;C f))) = g ;;C ((z2mC h) ;;C f)" using assms(1) c1
          by (simp add: LSCategory.m2zz2mInv)
        also have "... = (g ;;C (z2mC h)) ;;C f" using CompDef1 CompDef2 assms by (simp add: Category.Cassoc)
        also have "... = (z2mC (m2zC (g ;;C (z2mC h)))) ;;C f" using assms(1) c2
          by (simp add: LSCategory.m2zz2mInv)
        finally have "g ;;C (z2mC (m2zC ((z2mC h) ;;C f))) = (z2mC (m2zC (g ;;C (z2mC h)))) ;;C f" .
        thus ?thesis by simp
      qed
    }
  qed
  also have "... = (HomC[codC g,f]) |o| (HomCC[g,codC f])"
  proof(simp add: HomFtorMapContra_def HomFtorMap_def, rule ZFfunComp[THEN sym], rule allI, rule impI)
    {
      fix x assume aa: "x |∈| (HomC codC g domC f)"
      show "m2zC ((z2mC x) ;;C f) |∈| (HomC codC g codC f)" 
      proof(rule LSCategory.m2zz2m, simp_all add: assms(1) ObjCg ObjCf)
        have "f mapsC (domC f) to (codC f)" using assms by auto
        moreover have "(z2mC x) mapsC (codC g) to (domC f)" using aa ObjCg ObjDf assms(1) 
          by (simp add: LSCategory.z2mm2z)
        ultimately show "(z2mC x) ;;C f mapsC codC g to codC f" using assms(1)
          by (simp add: Category.Ccompt)
      qed
    }
  qed
  also have "... = (HomC[codC g,f]) ;;SET (HomCC[g,codC f])"
  proof-
    have "(HomC[codC g,f]) ≈>SET (HomCC[g,codC f])"
    proof(rule CompDefinedI)
      show "HomC[codC g,f] ∈ Mor SET" using assms ObjCg by (simp add: HomFtorMor)
      show "HomCC[g,codC f] ∈ Mor SET" using assms ObjCf by (simp add: HomFtorContraMor)
      show "codSET (HomC[codC g,f]) = domSET (HomCC[g,codC f])" using assms ObjCg ObjCf
        by (simp add: HomFtorMor HomFtorContraMor)
    qed
    thus ?thesis by(simp add: SET_def SET'_def MakeCatComp2)
  qed
  finally show ?thesis .
qed

end