{-# OPTIONS --safe #-}
module Multiset.Functor where
open import Multiset.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Function
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Univalence using (ua)
record Functor {ℓ} (F : Type ℓ → Type ℓ) : Type (ℓ-suc ℓ) where
field
map : ∀ {X Y : Type ℓ} → (X → Y) → (F X → F Y)
map-id : ∀ {X} x → map (idfun X) x ≡ x
map-comp : ∀ {X Y Z}
→ (g : Y → Z)
→ (f : X → Y)
→ ∀ x → map (g ∘ f) x ≡ map g (map f x)
map-id-ext : ∀ {X} → map (idfun X) ≡ idfun (F X)
map-id-ext = funExt map-id
map-comp-ext : ∀ {X Y Z}
→ (g : Y → Z) → (f : X → Y)
→ map (g ∘ f) ≡ map g ∘ map f
map-comp-ext g f = funExt (map-comp g f)
cong-map-ext : ∀ {X Y} → {f g : X → Y}
→ f ≡ g → ∀ x → map f x ≡ map g x
cong-map-ext p x = cong (λ h → map h x) p
cong-map : ∀ {X Y} → {f g : X → Y}
→ (∀ x → f x ≡ g x) → ∀ x → map f x ≡ map g x
cong-map p x = cong (λ h → map h x) (funExt p)
module _ where
open Functor
_∙F_ : ∀ {ℓ} (F G : Type ℓ → Type ℓ)
→ ⦃ Functor F ⦄
→ ⦃ Functor G ⦄
→ Functor (G ∘ F)
_∙F_ _ _ ⦃ FF ⦄ ⦃ FG ⦄ .Functor.map = FG .map ∘ FF .map
_∙F_ _ _ ⦃ FF ⦄ ⦃ FG ⦄ .Functor.map-id = funExt⁻ (cong (FG .map) (map-id-ext FF) ∙ map-id-ext FG)
_∙F_ _ _ ⦃ FF ⦄ ⦃ FG ⦄ .Functor.map-comp g f = funExt⁻ (cong (FG .map) (map-comp-ext FF g f) ∙ map-comp-ext FG (map FF g) (map FF f))
module _ {ℓ} (F : Type ℓ → Type ℓ) {{F' : Functor F}} where
open Iso
open Functor F' renaming (map to F[_])
isoLift : {X Y : Type ℓ} (isom : Iso X Y) → Iso (F X) (F Y)
isoLift isom .fun = F[ isom .fun ]
isoLift isom .inv = F[ isom .inv ]
isoLift isom .rightInv y = sym (map-comp (isom .fun) (isom .inv) y) ∙∙ cong-map (isom .rightInv) y ∙∙ map-id y
isoLift isom .leftInv x = sym (map-comp (isom .inv) (isom .fun) x) ∙∙ cong-map (isom .leftInv) x ∙∙ map-id x
equivLift : {X Y : Type ℓ} → X ≃ Y → F X ≃ F Y
equivLift e = isoToEquiv (isoLift (equivToIso e))
isEquivFunctorAction : {X Y : Type ℓ} {f : X → Y} → isEquiv f → isEquiv F[ f ]
isEquivFunctorAction {f = f} is-equiv = equivIsEquiv (equivLift (f , is-equiv))
module _ {ℓ} (F G : Type ℓ → Type ℓ) {{F' : Functor F}} {{G' : Functor G}} where
open Functor F' using () renaming (map to F[_])
open Functor G' using () renaming (map to G[_])
isNatTrans : (∀ {X : Type ℓ} → F X → G X) → Type (ℓ-suc ℓ)
isNatTrans η = ∀ {X Y : Type ℓ} (f : X → Y) → η {Y} ∘ F[ f ] ≡ G[ f ] ∘ η {X}
record NatTrans : Type (ℓ-suc ℓ) where
constructor nattrans
field
mor : ∀ {X} → F X → G X
is-nat : isNatTrans mor
component : ∀ X → F X → G X
component _ = mor
_⇒_ : Type _
_⇒_ = NatTrans
open NatTrans public
NatEquiv : Type (ℓ-suc ℓ)
NatEquiv = Σ[ η ∈ NatTrans ] (∀ {X} → isEquiv (component η X))
NatEquiv→Equiv : NatEquiv → ∀ {X} → F X ≃ G X
NatEquiv→Equiv (η , is-equiv) {X} = component η X , is-equiv {X}
Equiv→NatEquiv : (η : ∀ {X} → F X ≃ G X) → isNatTrans (equivFun η) → NatEquiv
Equiv→NatEquiv η is-nat = nattrans (equivFun η) is-nat , equivIsEquiv η
FunctorSIP₀ : ∀ {ℓ} {F G : Type ℓ → Type ℓ} {{FunctorF : Functor F}} {{FunctorG : Functor G}}
→ ({X : Type ℓ} → F X ≃ G X) → F ≡ G
FunctorSIP₀ equivs = funExt λ X → ua (equivs {X})
idNatTrans : ∀ {ℓ} (F : Type ℓ → Type ℓ) {{F' : Functor F}} → F ⇒ F
idNatTrans F .mor = idfun _
idNatTrans F .is-nat = λ _ → refl
private
variable
ℓ : Level
F G H : Type ℓ → Type ℓ
invNatEquiv : ∀ ⦃ F' : Functor F ⦄ ⦃ G' : Functor G ⦄ → NatEquiv F G → NatEquiv G F
invNatEquiv {ℓ} {F} {G} η@(nattrans η⁺ is-nat , is-equiv) = nattrans η⁻ is-nat-η⁻ , is-equiv-η⁻ where
open Functor ⦃...⦄
η⁻ : ∀ {X} → G X → F X
η⁻ = invIsEq is-equiv
is-nat-η⁻ : ∀ {X Y} → (f : X → Y) → η⁻ ∘ map f ≡ map f ∘ η⁻
is-nat-η⁻ {X} {Y} f =
η⁻ ∘ map f ≡⟨ cong ((η⁻ ∘ map f) ∘_) (sym (funExt (secIsEq is-equiv))) ⟩
η⁻ ∘ map f ∘ η⁺ ∘ η⁻ ≡⟨ cong (λ · → η⁻ ∘ · ∘ η⁻) (sym (is-nat f)) ⟩
η⁻ ∘ η⁺ ∘ map f ∘ η⁻ ≡⟨ cong (λ g → g ∘ (map f ∘ η⁻)) (funExt (retIsEq is-equiv)) ⟩
map f ∘ η⁻ ∎
is-equiv-η⁻ : ∀ {X} → isEquiv (η⁻ {X})
is-equiv-η⁻ {X} = isoToIsEquiv (invIso (equivToIso (NatEquiv→Equiv F G η)))
compNatTrans : ∀ ⦃ F' : Functor F ⦄ ⦃ G' : Functor G ⦄ ⦃ H' : Functor H ⦄
→ NatTrans F G
→ NatTrans G H
→ NatTrans F H
compNatTrans {ℓ} {F} {G} {H} (nattrans η η-nat) (nattrans φ φ-nat) = nattrans (φ ∘ η) isNatTransComp where
open Functor ⦃...⦄
isNatTransComp : isNatTrans F H (φ ∘ η)
isNatTransComp f =
φ ∘ η ∘ map f ≡⟨ cong (φ ∘_) (η-nat f) ⟩
φ ∘ map f ∘ η ≡⟨ cong (_∘ η) (φ-nat f) ⟩
map f ∘ φ ∘ η ∎
_∙ₙₜ_ = compNatTrans
compNatEquiv : ∀ ⦃ F' : Functor F ⦄ ⦃ G' : Functor G ⦄ ⦃ H' : Functor H ⦄
→ NatEquiv F G
→ NatEquiv G H
→ NatEquiv F H
compNatEquiv (η , η-equiv) (φ , φ-equiv) = η ∙ₙₜ φ , equivIsEquiv ((_ , η-equiv) ∙ₑ (_ , φ-equiv))
_∙ₙₑ_ = compNatEquiv
infixr 30 _∙ₙₜ_ _∙ₙₑ_
module SetTruncation where
open import Cubical.HITs.SetTruncation as ST using (∥_∥₂ ; ∣_∣₂)
open import Multiset.Util.SetTruncation
open Functor ⦃...⦄
instance
setTruncFunctor : Functor {ℓ} ∥_∥₂
setTruncFunctor .Functor.map = ST.map
setTruncFunctor .Functor.map-id = ST.elim (λ _ → ST.isSetPathImplicit) (λ _ → refl)
setTruncFunctor .Functor.map-comp g f = ST.elim (λ _ → ST.isSetPathImplicit) (λ _ → refl)
setTruncPostFunctor : ⦃ Functor F ⦄ → Functor (∥_∥₂ ∘ F)
setTruncPostFunctor {F = F} ⦃ F' ⦄ .Functor.map = ST.map ∘ map
setTruncPostFunctor {F = F} ⦃ F' ⦄ .Functor.map-id = ST.elim (λ _ → ST.isSetPathImplicit) (cong ∣_∣₂ ∘ map-id)
setTruncPostFunctor {F = F} ⦃ F' ⦄ .Functor.map-comp g f = ST.elim (λ _ → ST.isSetPathImplicit) (cong ∣_∣₂ ∘ map-comp g f)
setTruncPostNatTrans : ⦃ F' : Functor F ⦄ → ⦃ G' : Functor G ⦄ → F ⇒ G → (∥_∥₂ ∘ F) ⇒ (∥_∥₂ ∘ G)
setTruncPostNatTrans η .mor = ST.map (η .mor)
setTruncPostNatTrans η .is-nat f = funExt $ ST.elim (λ _ → ST.isSetPathImplicit) λ x → cong ∣_∣₂ (funExt⁻ (η .is-nat f) x)
setTruncPostNatEquiv : ⦃ F' : Functor F ⦄ → ⦃ G' : Functor G ⦄ → NatEquiv F G → NatEquiv (∥_∥₂ ∘ F) (∥_∥₂ ∘ G)
setTruncPostNatEquiv (α , α-equiv) = setTruncPostNatTrans α , equivIsEquiv (setTruncEquiv (_ , α-equiv))