open import Cat.Functor.Base
open import Cat.Functor.Hom
open import Cat.Prelude

import Cat.Functor.Reasoning.Presheaf as PSh

open Functor
open _=>_
module Cat.Functor.Hom.Yoneda where

The Yoneda lemma🔗

module _ {o ℓ} {C : Precategory o ℓ} (A : Functor (C ^op) (Sets ℓ)) where
  private module A = PSh A using (expand ; elim)
  open Precategory C

The Yoneda lemma says that the set of sections of a presheaf is isomorphic to the set of natural transformations into with domain a and that this isomorphism is natural. This result is actually extremely easy to prove, as long as we expand what a natural transformation consists of: a dependent function

There’s no secret in choosing the components of the isomorphism:

  • Given a we define a natural transformation by sending a map to the restriction
  yo :  {U}  A ʻ U  Hom-into C U => A
  yo a .η i h = A ⟪ h ⟫ a
  yo a .is-natural x y f = ext λ h  A.expand refl
  • Given an we obtain a value
  unyo :  {U}  Hom-into C U => A  A ʻ U
  unyo h = h .η _ id

This inverse explains why the Yoneda lemma is sometimes stated as “natural transformations (from a representable) are determined by their component at the identity”. These inverse equivalences compose to give expressions which are easy to cancel using naturality and functoriality:

  yo-is-equiv :  {U}  is-equiv (yo {U})
  yo-is-equiv = is-iso→is-equiv record where
    from = unyo
    rinv x = ext λ i h 
      yo (unyo x) .η i h ≡˘⟨ x .is-natural _ _ _ · _
      x .η i (id ∘ h)    ≡⟨ ap (x .η i) (idl h)
      x .η i h           ∎
    linv x =
      A ⟪ id ⟫ x ≡⟨ A.elim refl ⟩
      x          ∎
module _ {o ℓ} {C : Precategory o ℓ} {A : Functor (C ^op) (Sets ℓ)} where
  private module A = PSh A
  open Precategory C

Naturality🔗

The only part of the Yoneda lemma which is slightly tricky is working out the naturality statements. Since the isomorphism is natural in both and there are two statements. We implement the proofs of naturality for the isomorphism as combinators, so that they can slot into bigger proofs more easily. Calling these combinators with gives back the familiar naturality results.

For naturality “on the right”, i.e. in the coordinate, naturality says that given we have for all

  yo-natr
    :  {U V} {x : A ʻ U} {h : Hom V U} {y}
     A ⟪ h ⟫ x ≡ y
     yo A x ∘nt よ₁ C h ≡ yo A y
  yo-natr p = ext λ i f  A.expand refl ∙ A.ap p

  yo-naturalr
    :  {U V} {x : A ʻ U} {h : Hom V U}
     yo A x ∘nt よ₁ C h ≡ yo A (A ⟪ h ⟫ x)
  yo-naturalr = yo-natr refl

On “the left”, i.e. in the variable naturality says that, given a natural transformation we have as natural transformations for any

  yo-natl
    :  {B : Functor (C ^op) (Sets ℓ)} {U} {x : A ʻ U} {y : B ʻ U} {h : A => B}
     h .η U x ≡ y  h ∘nt yo {C = C} A x ≡ yo B y
  yo-natl {B = B} {h = h} p = ext λ i f  h .is-natural _ _ _ · _ ∙ PSh.ap B p

  yo-naturall
    :  {B : Functor (C ^op) (Sets ℓ)} {U} {x : A ʻ U} {h : A => B}
     h ∘nt yo {C = C} A x ≡ yo B (h .η U x)
  yo-naturall = yo-natl refl
  unyo-path :  {U : ⌞ C ⌟} {x y : A ʻ U}  yo {C = C} A x ≡ yo A y  x ≡ y
  unyo-path {x = x} {y} p =
    x          ≡⟨ A.intro refl ⟩
    A ⟪ id ⟫ x ≡⟨ unext p _ id ⟩
    A ⟪ id ⟫ y ≡⟨ A.elim refl ⟩
    y          ∎