open import Cat.Instances.Product
open import Cat.Univalent using (is-category)
open import Cat.Prelude

import Cat.Reasoning

open Precategory
open Functor
open _=>_

module Cat.Instances.Functor where

private variable
  o h o₁ h₁ oβ‚‚ hβ‚‚ : Level
  C D E : Precategory o h
  F G : Functor C D

Functor (pre)categoriesπŸ”—

By assigning the identity morphism to every object in CC, we get a natural transformation between F:C→DF : C \to D and itself.

idnt : {F : Functor C D} β†’ F => F
idnt {C = C} {D = D} .Ξ· x = D .id
idnt {C = C} {D = D} .is-natural x y f = D .idl _ βˆ™ sym (D .idr _)

Given two natural transformations Ξ·:Fβ‡’G\eta : F \To G and ΞΈ:Gβ‡’H\theta : G \To H, we can show that the assignment x↦ηx∘θxx \mapsto \eta_x \circ \theta_x of β€œcomponentwise compositions” defines a natural transformation Fβ‡’HF \To H, which serves as the composite of Ξ·\eta and ΞΈ\theta.

_∘nt_ : {F G H : Functor C D} β†’ G => H β†’ F => G β†’ F => H
_∘nt_ {C = C} {D = D} {F} {G} {H} f g = nat where
  module D = Precategory D

  nat : F => H
  nat .η x = f .η _ D.∘ g .η _

We can then show that these definitions assemble into a category where the objects are functors F,G:C→DF, G : C \to D, and the morphisms are natural transformations F⇒GF \To G. This is because natural transformations inherit the identity and associativity laws from the codomain category DD, and since hom-sets are sets, is-natural does not matter.

module _ {o₁ h₁ oβ‚‚ hβ‚‚} (C : Precategory o₁ h₁) (D : Precategory oβ‚‚ hβ‚‚) where
  open Precategory

  Cat[_,_] : Precategory (o₁ βŠ” oβ‚‚ βŠ” h₁ βŠ” hβ‚‚) (o₁ βŠ” h₁ βŠ” hβ‚‚)
  Cat[_,_] .Ob = Functor C D
  Cat[_,_] .Hom F G = F => G
  Cat[_,_] .id = idnt
  Cat[_,_] ._∘_ = _∘nt_

All of the properties that make up a Precategory follow from the characterisation of equalities in natural transformations: They are a set, and equality of the components determines equality of the transformation.

  Cat[_,_] .Hom-set F G = Nat-is-set
  Cat[_,_] .idr f = Nat-path Ξ» x β†’ D .idr _
  Cat[_,_] .idl f = Nat-path Ξ» x β†’ D .idl _
  Cat[_,_] .assoc f g h = Nat-path Ξ» x β†’ D .assoc _ _ _

Before moving on, we prove the following lemma which characterises equality in Functor (between definitionally equal categories). Given an identification p:F0(x)≑G0(x)p : F_0(x) \equiv G_0(x) between the object mappings, and an identification of morphism parts that lies over pp, we can identify the functors F≑GF \equiv G.

Functor-path : {F G : Functor C D}
         β†’ (p0 : βˆ€ x β†’ Fβ‚€ F x ≑ Fβ‚€ G x)
         β†’ (p1 : βˆ€ {x y} (f : C .Hom x y)
               β†’ PathP (Ξ» i β†’ D .Hom (p0 x i) (p0 y i)) (F₁ F f) (F₁ G f))
         β†’ F ≑ G
Functor-path p0 p1 i .Fβ‚€ x = p0 x i
Functor-path p0 p1 i .F₁ f = p1 f i

Functor categoriesπŸ”—

When the codomain category DD is univalent, then so is the category of functors [C,D][C,D]. Essentially, this can be read as saying that β€œnaturally isomorphic functors are identified”. We begin by proving that the components of a natural isomorphism (a natural transformation with natural inverse) are themselves isomorphisms in DD.

  Nat-isoβ†’Iso : F [C,D].β‰… G β†’ βˆ€ x β†’ Fβ‚€ F x D.β‰… Fβ‚€ G x
  Nat-iso→Iso natiso x =
    D.make-iso (to .Ξ· x) (from .Ξ· x)
      (Ξ» i β†’ invl i .Ξ· x) (Ξ» i β†’ invr i .Ξ· x)
    where open [C,D]._β‰…_ natiso

We can now prove that [C,D][C,D] is a category, by showing that, for a fixed functor F:C→DF : C \to D, the space of functors GG equipped with natural isomorphisms F≅GF \cong G is contractible. The centre of contraction is the straightforward part: We have the canonical choice of (F,id)(F, id).

  Functor-is-category : is-category D β†’ is-category Cat[ C , D ]
  Functor-is-category _ F .centre = F , id-iso

The hard part is showing that, given some other functor G:Cβ†’DG : C \to D with a natural isomorphism Fβ‰…GF \cong G, we can give a continuous deformation p:G≑Fp : G \equiv F, such that, over this pp, the given isomorphism looks like the identity.

  Functor-is-category DisCat F .paths (G , Fβ‰…G) = Ξ£-pathp F≑G id≑Fβ‰…G where

The first thing we must note is that we can recover the components of a natural isomorphism while passing to/from paths in DD. Since DD is a category, path→iso is an equivalence; The lemmas we need then follow from equivalences having sections.

    ptoi-to
      : βˆ€ x β†’ pathβ†’iso (isoβ†’path DisCat (Nat-isoβ†’Iso Fβ‰…G _)) .D._β‰…_.to
            ≑ Fβ‰…G .to .Ξ· x
    ptoi-to x = ap (Ξ» e β†’ e .D._β‰…_.to)
      (equiv→section (path→iso-is-equiv DisCat) _)

    ptoi-from : βˆ€ x β†’ pathβ†’iso (isoβ†’path DisCat (Nat-isoβ†’Iso Fβ‰…G _)) .D._β‰…_.from
              ≑ Fβ‰…G .from .Ξ· x
    ptoi-from x = ap (Ξ» e β†’ e .D._β‰…_.from)
      (equiv→section (path→iso-is-equiv DisCat) _)

We can then show that the natural isomorphism F≅GF \cong G induces a homotopy between the object parts of FF and GG:

    F₀≑Gβ‚€ : βˆ€ x β†’ Fβ‚€ F x ≑ Fβ‚€ G x
    F₀≑Gβ‚€ x = isoβ†’path DisCat (Nat-isoβ†’Iso Fβ‰…G x)

A slightly annoying calculation tells us that pre/post composition with Fβ‰…GF \cong G does in fact turn F1(f)F_1(f) into G1(f)G_1(f); This is because Fβ‰…GF \cong G is natural, so we can push it β€œpast” the morphism part of FF so that the two halves of the isomorphism annihilate.

    abstract
      F₁≑G₁ : βˆ€ {x y} {f : C .Hom x y}
            β†’ PathP (Ξ» i β†’ D.Hom (F₀≑Gβ‚€ x i) (F₀≑Gβ‚€ y i)) (F₁ F f) (F₁ G f)
      F₁≑G₁ {x = x} {y} {f} = Hom-pathp (
        _ D.∘ F .F₁ f D.∘ _                           β‰‘βŸ¨ (Ξ» i β†’ ptoi-to _ i D.∘ F .F₁ f D.∘ ptoi-from _ i) βŸ©β‰‘
        Fβ‰…G .to .Ξ· y D.∘ F .F₁ f D.∘ Fβ‰…G .from .Ξ· x   β‰‘βŸ¨ apβ‚‚ D._∘_ refl (sym (Fβ‰…G .from .is-natural _ _ _)) βˆ™ D.assoc _ _ _ βŸ©β‰‘
        (Fβ‰…G .to .Ξ· y D.∘ Fβ‰…G .from .Ξ· y) D.∘ G .F₁ f β‰‘βŸ¨ apβ‚‚ D._∘_ (Ξ» i β†’ Fβ‰…G .invl i .Ξ· y) refl βŸ©β‰‘
        D.id D.∘ G .F₁ f                              β‰‘βŸ¨ solve D βŸ©β‰‘
        G .F₁ f                                       ∎)

    F≑G : F ≑ G
    F≑G = Functor-path F₀≑Gβ‚€ Ξ» f β†’ F₁≑G₁

Putting these homotopies together defines a path F≑G. It remains to show that, over this path, the natural isomorphism we started with is homotopic to the identity; Equality of isomorphisms and natural transformations are both tested componentwise, so we can β€œpush down” the relevant equalities to the level of families of morphisms; By computation, all we have to show is that Ξ·x∘id∘id=f\eta{}_x \circ \id{id} \circ \id{id} = f.

    id≑Fβ‰…G : PathP (Ξ» i β†’ F β‰… F≑G i) id-iso Fβ‰…G
    id≑Fβ‰…G = β‰…-pathp refl F≑G
      (Nat-pathp refl F≑G
        Ξ» x β†’ Hom-pathp
          (  apβ‚‚ D._∘_ (ptoi-to _) refl
          Β·Β· apβ‚‚ D._∘_ refl (apβ‚‚ D._∘_ refl (transport-refl _) βˆ™ D.idl _)
          Β·Β· D.idr _))

A useful lemma is that if you have a natural transformation where each component is an isomorphism, the evident inverse transformation is natural too, thus defining an inverse to Nat-iso→Iso defined above.

module _ {C : Precategory o h} {D : Precategory o₁ h₁} {F G : Functor C D} where
  import Cat.Reasoning D as D
  import Cat.Reasoning Cat[ C , D ] as [C,D]
  private
    module F = Functor F
    module G = Functor G

  open D.is-invertible

  componentwise-invertible→invertible
    : (eta : F => G)
    β†’ (βˆ€ x β†’ D.is-invertible (eta .Ξ· x))
    β†’ [C,D].is-invertible eta
  componentwise-invertible→invertible eta invs = are-invs where
    module eta = _=>_ eta

    eps : G => F
    eps .Ξ· x = invs x .inv
    eps .is-natural x y f =
      invs y .inv D.∘ G.₁ f                             β‰‘βŸ¨ apβ‚‚ D._∘_ refl (sym (D.idr _) βˆ™ ap (G.₁ f D.∘_) (sym (invs x .invl))) βŸ©β‰‘
      invs y .inv D.∘ G.₁ f D.∘ eta.Ξ· x D.∘ invs x .inv β‰‘βŸ¨ apβ‚‚ D._∘_ refl (D.extendl (sym (eta.is-natural _ _ _))) βŸ©β‰‘
      invs y .inv D.∘ eta.Ξ· y D.∘ F.₁ f D.∘ invs x .inv β‰‘βŸ¨ D.cancell (invs y .invr) βŸ©β‰‘
      F.₁ f D.∘ invs x .inv ∎

    are-invs : [C,D].is-invertible eta
    are-invs =
      record
        { inv      = eps
        ; inverses =
          record
            { invl = Nat-path Ξ» x β†’ invs x .invl
            ; invr = Nat-path Ξ» x β†’ invs x .invr
            }
        }

CurryingπŸ”—

There is an equivalence between the spaces of bifunctors CΓ—CatDβ†’E\ca{C} \times_\cat \ca{D} \to E and the space of functors Cβ†’[D,E]\ca{C} \to [\ca{D},E]. We refer to the image of a functor under this equivalence as its exponential transpose, and we refer to the map in the β€œforwards” direction (as in the text above) as currying:

Curry : Functor (C Γ—Cat D) E β†’ Functor C Cat[ D , E ]
Curry {C = C} {D = D} {E = E} F = curried where
  open import Cat.Functor.Bifunctor {C = C} {D = D} {E = E} F

  curried : Functor C Cat[ D , E ]
  curried .Fβ‚€ = Right
  curried .F₁ xβ†’y = NT (Ξ» f β†’ first xβ†’y) Ξ» x y f β†’
       sym (F-∘ F _ _)
    Β·Β· ap (F₁ F) (Ξ£-pathp (C .idr _ βˆ™ sym (C .idl _)) (D .idl _ βˆ™ sym (D .idr _)))
    ·· F-∘ F _ _
  curried .F-id = Nat-path Ξ» x β†’ F-id F
  curried .F-∘ f g = Nat-path Ξ» x β†’
    ap (Ξ» x β†’ F₁ F (_ , x)) (sym (D .idl _)) βˆ™ F-∘ F _ _

Uncurry : Functor C Cat[ D , E ] β†’ Functor (C Γ—Cat D) E
Uncurry {C = C} {D = D} {E = E} F = uncurried where
  import Cat.Reasoning C as C
  import Cat.Reasoning D as D
  import Cat.Reasoning E as E
  module F = Functor F

  uncurried : Functor (C Γ—Cat D) E
  uncurried .Fβ‚€ (c , d) = Fβ‚€ (F.β‚€ c) d
  uncurried .F₁ (f , g) = F.₁ f .Ξ· _ E.∘ F₁ (F.β‚€ _) g

  uncurried .F-id {x = x , y} = path where abstract
    path : E ._∘_ (F.₁ (C .id) .Ξ· y) (F₁ (F.β‚€ x) (D .id)) ≑ E .id
    path =
      F.₁ C.id .Ξ· y E.∘ F₁ (F.β‚€ x) D.id β‰‘βŸ¨ E.elimr (F-id (F.β‚€ x)) βŸ©β‰‘
      F.₁ C.id .Ξ· y                     β‰‘βŸ¨ (Ξ» i β†’ F.F-id i .Ξ· y) βŸ©β‰‘
      E.id                              ∎

  uncurried .F-∘ (f , g) (fβ€² , gβ€²) = path where abstract
    path : uncurried .F₁ (f C.∘ fβ€² , g D.∘ gβ€²)
         ≑ uncurried .F₁ (f , g) E.∘ uncurried .F₁ (fβ€² , gβ€²)
    path =
      F.₁ (f C.∘ fβ€²) .Ξ· _ E.∘ F₁ (F.β‚€ _) (g D.∘ gβ€²)                       β‰‘Λ˜βŸ¨ E.pulll (Ξ» i β†’ F.F-∘ f fβ€² (~ i) .Ξ· _) βŸ©β‰‘Λ˜
      F.₁ f .Ξ· _ E.∘ F.₁ fβ€² .Ξ· _ E.∘ F₁ (F.β‚€ _) (g D.∘ gβ€²)                β‰‘βŸ¨ (Ξ» i β†’ F.₁ f .Ξ· _ E.∘ F.₁ fβ€² .Ξ· _ E.∘ F-∘ (F.β‚€ _) g gβ€² i) βŸ©β‰‘
      F.₁ f .Ξ· _ E.∘ F.₁ fβ€² .Ξ· _ E.∘ F₁ (F.β‚€ _) g E.∘ F₁ (F.β‚€ _) gβ€²       β‰‘βŸ¨ solve E βŸ©β‰‘
      F.₁ f .Ξ· _ E.∘ (F.₁ fβ€² .Ξ· _ E.∘ F₁ (F.β‚€ _) g) E.∘ F₁ (F.β‚€ _) gβ€²     β‰‘βŸ¨ ap (Ξ» e β†’ _ E.∘ e E.∘ _) (F.₁ fβ€² .is-natural _ _ _) βŸ©β‰‘
      F.₁ f .Ξ· _ E.∘ (F₁ (F.β‚€ _) g E.∘ F.₁ fβ€² .Ξ· _) E.∘ F₁ (F.β‚€ _) gβ€²     β‰‘βŸ¨ solve E βŸ©β‰‘
      ((F.₁ f .Ξ· _ E.∘ F₁ (F.β‚€ _) g) E.∘ (F.₁ fβ€² .Ξ· _ E.∘ F₁ (F.β‚€ _) gβ€²)) ∎