open import Cat.CartesianClosed.Locally
open import Cat.Instances.Sets.Complete
open import Cat.Functor.Pullback
open import Cat.Functor.Adjoint
open import Cat.Instances.Slice
open import Cat.Prelude

module Cat.Instances.Sets.CartesianClosed {} where

Sets is (locally) cartesian closed🔗

We show that the category of Sets is locally cartesian closed, i.e. that every map f:ABf : A \to B of Sets induces a functor f:Sets/ASets/B\prod_f : \sets/A \to \sets/B, which is right adjoint to the base change functor f:Sets/BSets/Af^* : \sets/B \to \sets/A.

⚠️⚠️⚠️

module _ {A B : Set } (func :  A    B ) where
  Sets-Π : Functor (Slice (Sets ) A) (Slice (Sets ) B)
  Sets-Π .F₀ ob .domain =
      (Σ[ y   B  ] ((f : fibre func y)  fibre (ob .map) (f .fst)))
    , Σ-is-hlevel 2 (B .is-tr) λ _ 
      Π-is-hlevel 2 λ _ 
      Σ-is-hlevel 2 (ob .domain .is-tr) λ _  is-prop→is-set (A .is-tr _ _)

  Sets-Π .F₀ ob .map g = g .fst

  Sets-Π .F₁ hom .map (i , fibs) = i , go where
    go :  _  _
    go (x , fx=i) = hom .map (fibs (x , fx=i) .fst) ,
      happly (hom .commutes) _  (fibs (x , fx=i) .snd)
  Sets-Π .F₁ hom .commutes = refl
open is-lcc
Sets-lcc : is-lcc (Sets )
Sets-lcc .finitely-complete = Sets-finitely-complete
Sets-lcc .Πf = Sets-Π
Sets-lcc .f*⊣Πf f .unit .η x .map y = x .map y , λ f  (_ , _ , sym (f .snd)) , refl
Sets-lcc .f*⊣Πf f .counit .η x .map ((a , g) , b , p) = g (b , sym p) .fst