1-- Natural transformations between functors2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.Category.Natural8import Functor9import Set.Function.Space1011-- η : F ⟹ G, for functors F G : C ⥤ D: a function η : obj(C) → mor(D) whose12-- component at a is a morphism η(a) : F(a) ⟶ G(a) and which commutes with13-- every morphism, η(b) ∘ F(f) = G(f) ∘ η(a). The categories are those of14-- the functors, so the predicate names only the three maps.15predicate NaturalTransformation (η F G : Set) :=16∀ C, ∀ D, F : C ⥤ D → G : C ⥤ D →17 (η : obj(C) → mor(D)) ∧ (∀ a ∈ obj(C), η(a) : F(a) ⟶ G(a)) ∧18 (∀ (a b ∈ obj(C)) (f : a ⟶ b), η(b) ∘ F(f) = G(f) ∘ η(a))1920notationmixfix"_ : _ ⟹ _"=> NaturalTransformation2122-- The set of natural transformations from F to G.23def NatTrans (F G : Set) : Set:=24 { η ∈ functionSpace(Category.obj(src(F)), mor(tgt(F))) | η : F ⟹ G }2526predicate NaturalIsomorphism (η F G : Set) :=27 η : F ⟹ G ∧∀ a ∈ Category.obj(src(F)), Isomorphism(tgt(F), η(a))2829-- The constructor: a transformation is given by its components and the30-- naturality squares.31theorem NaturalTransformation.mk (η F G C D : Set)32requires functorF : F : C ⥤ D33requires functorG : G : C ⥤ D34requires function : η : obj(C) → mor(D)35requires components : ∀ a ∈ obj(C), η(a) : F(a) ⟶ G(a)36requires naturality : ∀ (a b ∈ obj(C)) (f : a ⟶ b), η(b) ∘ F(f) = G(f) ∘ η(a)37shows η : F ⟹ G38proof39unfold NaturalTransformation40intros C2 D2 functorF2 functorG241obtain⟨srcF, tgtF, rest⟩:= functorF42obtain⟨srcF2, tgtF2, rest2⟩:= functorF243have sameSource : C2 = C bycc44have sameTarget : D2 = D bycc45rwunder sameSource46rwunder sameTarget47refine⟨function, components, naturality⟩4849section TransformationLaws50variable (η F G C D : Set)51hypothesis functorF : F : C ⥤ D52hypothesis functorG : G : C ⥤ D53hypothesis natural : η : F ⟹ G5455theorem NaturalTransformation.function56shows η : obj(C) → mor(D)57proof58obtain⟨function, components, naturality⟩:= natural with C, D, functorF, functorG59exact function6061instance NaturalTransformation.component_hom (a : Set)62requires aInO : a ∈ obj(C)63shows η(a) : F(a) ⟶ G(a)64proof65obtain⟨function, components, naturality⟩:= natural with C, D, functorF, functorG66exact components with a, aInO6768theorem NaturalTransformation.naturality (a b ∈ obj(C)) (f : a ⟶ b)69shows η(b) ∘ F(f) = G(f) ∘ η(a)70proof71obtain⟨function, components, naturality⟩:= natural with C, D, functorF, functorG72exact naturality with a, assumption, b, assumption, f, assumption7374theorem NaturalTransformation.component (a : Set)75requires aInO : a ∈ obj(C)76shows η(a) ∈ hom(D, F(a), G(a))77proof78have component := NaturalTransformation.component_hom with*79exact Morphism.hom with component8081theorem NaturalTransformation.component_closed (a : Set)82requires aInO : a ∈ obj(C)83shows η(a) ∈ mor(D)84proof85have component := NaturalTransformation.component_hom with*86exact Morphism.in_morphisms with component8788theorem NaturalTransformation.component_dom (a : Set)89requires aInO : a ∈ obj(C)90shows dom(D)(η(a)) = F(a)91proof92have component := NaturalTransformation.component_hom with*93exact Morphism.dom with component9495theorem NaturalTransformation.component_cod (a : Set)96requires aInO : a ∈ obj(C)97shows cod(D)(η(a)) = G(a)98proof99have component := NaturalTransformation.component_hom with*100exact Morphism.cod with component101102-- Naturality in hom-set form.103theorem NaturalTransformation.square (a b f : Set)104requires fHom : f ∈ hom(C, a, b)105shows η(b) ∘ F(f) = G(f) ∘ η(a)106proof107have typed : f : a ⟶ b := Morphism.of_hom with fHom108exact NaturalTransformation.naturality with*109110theorem NatTrans.of_transformation111shows η ∈ NatTrans(F, G)112proof113have srcF := Functor.source with functorF114have tgtF := Functor.target with functorF115have function := NaturalTransformation.function with*116have bounded := functionSpace.mem_iff.backward with function117rw [← srcF, ← tgtF] at bounded118simp [NatTrans]119120end TransformationLaws121122theorem NatTrans.natural (η F G : Set)123requires member : η ∈ NatTrans(F, G)124shows η : F ⟹ G125proof126simp [NatTrans] at member127exact member.right128129-- The categorical rewrite set extended by the functor and transformation130-- laws: functoriality and naturality goals close by functor_simp when the131-- hom guards of the morphisms involved are in scope.132tactic functor_simp :=simp [Category.id_left, Category.id_right, Category.assoc, Functor.map_id, Functor.map_comp, NaturalTransformation.naturality]133134-- Two transformations with the same components are equal.135theorem NaturalTransformation.ext (η θ F G C D : Set)136requires functorF : F : C ⥤ D137requires functorG : G : C ⥤ D138requires etaNatural : η : F ⟹ G139requires thetaNatural : θ : F ⟹ G140requires same : ∀ a ∈ obj(C), η(a) = θ(a)141shows η = θ142proof143have etaFunction := NaturalTransformation.function with functorF, functorG, etaNatural144have thetaFunction := NaturalTransformation.function with functorF, functorG, thetaNatural145exact FunctionBetween.ext with etaFunction, thetaFunction, same146147-- The identity transformation of a functor.148defgraph identityTransformation (F : Set) (a ∈ Category.obj(src(F))) : mor(tgt(F)) :=149 id(tgt(F))(obj(F)(a))150requires functor : Functor(F, src(F), tgt(F))151proof152have image := Functor.object_closed with functor, member153have target := Functor.target_category with functor154exact Category.id_closed with target, image155156section IdentityTransformation157variable (F C D : Set)158hypothesis functor : F : C ⥤ D159160theorem identityTransformation.component (a : Set)161requires aInO : a ∈ obj(C)162shows identityTransformation(F)(a) = id(D)(F(a))163proof164haveself:= Functor.self with functor165have srcF := Functor.source with functor166have tgtF := Functor.target with functor167have aInSrc : a ∈ obj(src(F)) by rwa srcF168have value := identityTransformation.value withself, aInSrc169 rwa tgtF at value170171theorem identityTransformation.function_hom172shows identityTransformation(F) : obj(C) → mor(D)173proof174haveself:= Functor.self with functor175have srcF := Functor.source with functor176have tgtF := Functor.target with functor177have function := identityTransformation.function withself178 rwa [srcF, tgtF] at function179180theorem identityTransformation.natural181shows identityTransformation(F) : F ⟹ F182proof183have function := identityTransformation.function_hom with functor184apply NaturalTransformation.mk with functor, functor, function185 . intros a aIn186rw identityTransformation.component187synthesize188 . intros a aIn b bIn f fHom189rw [identityTransformation.component, identityTransformation.component]190 category_simp191192end IdentityTransformation193194-- Vertical composition of transformations η : F ⟹ G and θ : G ⟹ H.195defgraph verticalComposition (η θ F G H : Set) (a ∈ Category.obj(src(F))) : mor(tgt(F)) :=196 comp(tgt(F))(θ(a), η(a))197requires functorF : Functor(F, src(F), tgt(F))198requires functorG : Functor(G, src(F), tgt(F))199requires functorH : Functor(H, src(F), tgt(F))200requires etaNatural : η : F ⟹ G201requires thetaNatural : θ : G ⟹ H202proof203have etaHom := NaturalTransformation.component_hom with functorF, functorG, etaNatural, member204have thetaHom := NaturalTransformation.component_hom with functorG, functorH, thetaNatural, member205have composite : comp(tgt(F))(θ(a), η(a)) : F(a) ⟶ H(a) := Morphism.comp with*206exact Morphism.in_morphisms with composite207208section VerticalComposition209variable (η θ F G H C D : Set)210hypothesis functorF : F : C ⥤ D211hypothesis functorG : G : C ⥤ D212hypothesis functorH : H : C ⥤ D213hypothesis etaNatural : η : F ⟹ G214hypothesis thetaNatural : θ : G ⟹ H215216theorem verticalComposition.component (a : Set)217requires aInO : a ∈ obj(C)218shows verticalComposition(η, θ, F, G, H)(a) = θ(a) ∘ η(a)219proof220have srcF := Functor.source with functorF221have tgtF := Functor.target with functorF222have selfF := Functor.self with functorF223have selfG : Functor(G, src(F), tgt(F)) by rwa [srcF, tgtF]224have selfH : Functor(H, src(F), tgt(F)) by rwa [srcF, tgtF]225have aInSrc : a ∈ obj(src(F)) by rwa srcF226have value := verticalComposition.value with227 selfF, selfG, selfH, etaNatural, thetaNatural, aInSrc228 rwa tgtF at value229230theorem verticalComposition.function_hom231shows verticalComposition(η, θ, F, G, H) : obj(C) → mor(D)232proof233have srcF := Functor.source with functorF234have tgtF := Functor.target with functorF235have selfF := Functor.self with functorF236have selfG : Functor(G, src(F), tgt(F)) by rwa [srcF, tgtF]237have selfH : Functor(H, src(F), tgt(F)) by rwa [srcF, tgtF]238have function := verticalComposition.function with selfF, selfG, selfH, etaNatural, thetaNatural239 rwa [srcF, tgtF] at function240241theorem verticalComposition.natural242shows verticalComposition(η, θ, F, G, H) : F ⟹ H243proof244have function : verticalComposition(η, θ, F, G, H) : obj(C) → mor(D) := verticalComposition.function_hom with*245apply NaturalTransformation.mk with functorF, functorH, function246 . intros a aIn247rw verticalComposition.component248synthesize249 . intros a aIn b bIn f fHom250rw [verticalComposition.component, verticalComposition.component]251rw [Category.assoc, NaturalTransformation.naturality, ← Category.assoc, NaturalTransformation.naturality, Category.assoc]252rfl253254end VerticalComposition255256-- Natural isomorphisms and their inverses.257section NaturalIsomorphismLaws258variable (η F G C D : Set)259hypothesis functorF : F : C ⥤ D260hypothesis functorG : G : C ⥤ D261262theorem NaturalIsomorphism.natural263requires iso : NaturalIsomorphism(η, F, G)264shows η : F ⟹ G265proof266obtain⟨natural, components⟩:= iso267exact natural268269theorem NaturalIsomorphism.component (a : Set)270requires iso : NaturalIsomorphism(η, F, G)271requires aInO : a ∈ obj(C)272shows Isomorphism(D, η(a))273proof274obtain⟨natural, components⟩:= iso275have srcF := Functor.source with functorF276have tgtF := Functor.target with functorF277have aInSrc : a ∈ obj(src(F)) by rwa srcF278have component := components with a, aInSrc279 rwa tgtF at component280281theorem NaturalIsomorphism.isomorphic (a : Set)282requires iso : NaturalIsomorphism(η, F, G)283requires aInO : a ∈ obj(C)284shows Isomorphic(D, F(a), G(a))285proof286have natural := NaturalIsomorphism.natural with functorF, functorG, iso287have component := NaturalTransformation.component with functorF, functorG, natural, aInO288have componentIso := NaturalIsomorphism.component with functorF, functorG, iso, aInO289exact Isomorphic.of_hom with component, componentIso290291theorem NaturalIsomorphism.mk292requires natural : η : F ⟹ G293requires components : ∀ a ∈ obj(C), Isomorphism(D, η(a))294shows NaturalIsomorphism(η, F, G)295proof296have srcF := Functor.source with functorF297have tgtF := Functor.target with functorF298unfold NaturalIsomorphism299rwunder srcF300rwunder tgtF301refine⟨natural, components⟩302303end NaturalIsomorphismLaws304305-- The inverse of a natural isomorphism, componentwise.306defgraph inverseTransformation (η F G : Set) (a ∈ Category.obj(src(F))) : mor(tgt(F)) :=307 inverseMorphism(tgt(F), η(a))308requires functorF : Functor(F, src(F), tgt(F))309requires iso : NaturalIsomorphism(η, F, G)310proof311have target := Functor.target_category with functorF312obtain⟨natural, components⟩:= iso313have componentIso := components with a, member314exact inverseMorphism.morphism with target, componentIso315316section InverseTransformation317variable (η F G C D : Set)318hypothesis functorF : F : C ⥤ D319hypothesis functorG : G : C ⥤ D320hypothesis iso : NaturalIsomorphism(η, F, G)321322theorem inverseTransformation.component (a : Set)323requires aInO : a ∈ obj(C)324shows inverseTransformation(η, F, G)(a) = inverseMorphism(D, η(a))325proof326have srcF := Functor.source with functorF327have tgtF := Functor.target with functorF328have selfF := Functor.self with functorF329have aInSrc : a ∈ obj(src(F)) by rwa srcF330have value := inverseTransformation.value with selfF, iso, aInSrc331 rwa tgtF at value332333theorem inverseTransformation.function_hom334shows inverseTransformation(η, F, G) : obj(C) → mor(D)335proof336have srcF := Functor.source with functorF337have tgtF := Functor.target with functorF338have selfF := Functor.self with functorF339have function := inverseTransformation.function with selfF, iso340 rwa [srcF, tgtF] at function341342theorem inverseTransformation.component_hom (a : Set)343requires aInO : a ∈ obj(C)344shows inverseTransformation(η, F, G)(a) : G(a) ⟶ F(a)345proof346have target := Functor.target_category with functorF347have natural := NaturalIsomorphism.natural with functorF, functorG, iso348have component : η(a) : F(a) ⟶ G(a) :=349 NaturalTransformation.component_hom with functorF, functorG, natural, aInO350have componentIso := NaturalIsomorphism.component with functorF, functorG, iso, aInO351have pair := inverseMorphism.pair with target, componentIso352rw inverseTransformation.component353exact InversePair.inverse_of_hom with*354355theorem inverseTransformation.natural356shows inverseTransformation(η, F, G) : G ⟹ F357proof358have target := Functor.target_category with functorF359have natural := NaturalIsomorphism.natural with functorF, functorG, iso360have function := inverseTransformation.function_hom with functorF, functorG, iso361apply NaturalTransformation.mk with functorG, functorF, function362 . intros a aIn363exact inverseTransformation.component_hom with functorF, functorG, iso, aIn364 . intros a aIn b bIn f fHom365have fHomSet : f ∈ hom(C, a, b) := Morphism.hom with fHom366have etaA := NaturalTransformation.component with functorF, functorG, natural, aIn367have etaB := NaturalTransformation.component with functorF, functorG, natural, bIn368have isoA := NaturalIsomorphism.component with functorF, functorG, iso, aIn369have isoB := NaturalIsomorphism.component with functorF, functorG, iso, bIn370have pairA := inverseMorphism.pair with target, isoA371have pairB := inverseMorphism.pair with target, isoB372have imageF := Functor.hom with functorF, fHomSet373have imageG := Functor.hom with functorG, fHomSet374have square : η(b) ∘ F(f) = G(f) ∘ η(a) :=375 NaturalTransformation.naturality with functorF, functorG, natural, aIn, bIn, fHom376rw [inverseTransformation.component, inverseTransformation.component]377exact InversePair.transpose with target, pairA, pairB, etaA, etaB, imageF, imageG, square378379theorem inverseTransformation.natural_iso380shows NaturalIsomorphism(inverseTransformation(η, F, G), G, F)381proof382have target := Functor.target_category with functorF383have natural := inverseTransformation.natural with functorF, functorG, iso384apply NaturalIsomorphism.mk with functorG, functorF, natural385intros a aIn386have componentIso := NaturalIsomorphism.component with functorF, functorG, iso, aIn387rw inverseTransformation.component388exact inverseMorphism.isomorphism with target, componentIso389390theorem inverseTransformation.vertical_left391shows verticalComposition(η, inverseTransformation(η, F, G), F, G, F) =392 identityTransformation(F)393proof394have target := Functor.target_category with functorF395have natural := NaturalIsomorphism.natural with functorF, functorG, iso396have inverseNatural := inverseTransformation.natural with functorF, functorG, iso397have composite := verticalComposition.natural with398 functorF, functorG, functorF, natural, inverseNatural399have identityNatural := identityTransformation.natural with functorF400apply NaturalTransformation.ext with functorF, functorF, composite, identityNatural401intros a aIn402have component : η(a) : F(a) ⟶ G(a) :=403 NaturalTransformation.component_hom with functorF, functorG, natural, aIn404have componentIso := NaturalIsomorphism.component with functorF, functorG, iso, aIn405have pair := inverseMorphism.pair with target, componentIso406haveleft : inverseMorphism(D, η(a)) ∘ η(a) = id(D)(F(a)) := InversePair.left_hom with*407rw [verticalComposition.component, inverseTransformation.component, identityTransformation.component]408exactleft409410theorem inverseTransformation.vertical_right411shows verticalComposition(inverseTransformation(η, F, G), η, G, F, G) =412 identityTransformation(G)413proof414have target := Functor.target_category with functorF415have natural := NaturalIsomorphism.natural with functorF, functorG, iso416have inverseNatural := inverseTransformation.natural with functorF, functorG, iso417have composite := verticalComposition.natural with418 functorG, functorF, functorG, inverseNatural, natural419have identityNatural := identityTransformation.natural with functorG420apply NaturalTransformation.ext with functorG, functorG, composite, identityNatural421intros a aIn422have component : η(a) : F(a) ⟶ G(a) :=423 NaturalTransformation.component_hom with functorF, functorG, natural, aIn424have componentIso := NaturalIsomorphism.component with functorF, functorG, iso, aIn425have pair := inverseMorphism.pair with target, componentIso426haveright : η(a) ∘ inverseMorphism(D, η(a)) = id(D)(G(a)) := InversePair.right_hom with*427rw [verticalComposition.component, inverseTransformation.component, identityTransformation.component]428exactright429430end InverseTransformation431432-- The identity transformation is a natural isomorphism, and it is a unit433-- for vertical composition.434section IdentityLaws435variable (η F G C D : Set)436hypothesis functorF : F : C ⥤ D437hypothesis functorG : G : C ⥤ D438hypothesis natural : η : F ⟹ G439440theorem identityTransformation.natural_iso441shows NaturalIsomorphism(identityTransformation(F), F, F)442proof443have target := Functor.target_category with functorF444have identityNatural := identityTransformation.natural with functorF445apply NaturalIsomorphism.mk with functorF, functorF, identityNatural446intros a aIn447have image := Functor.object_closed with functorF, aIn448rw identityTransformation.component449exact Isomorphism.id with target, image450451theorem verticalComposition.identity_left452shows verticalComposition(η, identityTransformation(G), F, G, G) = η453proof454have identityNatural := identityTransformation.natural with functorG455have composite := verticalComposition.natural with456 functorF, functorG, functorG, natural, identityNatural457apply NaturalTransformation.ext with functorF, functorG, composite, natural458intros a aIn459have component : η(a) : F(a) ⟶ G(a) :=460 NaturalTransformation.component_hom with functorF, functorG, natural, aIn461rw [verticalComposition.component, identityTransformation.component]462 category_simp463464theorem verticalComposition.identity_right465shows verticalComposition(identityTransformation(F), η, F, F, G) = η466proof467have identityNatural := identityTransformation.natural with functorF468have composite := verticalComposition.natural with469 functorF, functorF, functorG, identityNatural, natural470apply NaturalTransformation.ext with functorF, functorG, composite, natural471intros a aIn472have component : η(a) : F(a) ⟶ G(a) :=473 NaturalTransformation.component_hom with functorF, functorG, natural, aIn474rw [verticalComposition.component, identityTransformation.component]475 category_simp476477end IdentityLaws478