# Precomposition of functions ```agda module foundation.precomposition-functions where open import foundation-core.precomposition-functions public ``` <details><summary>Imports</summary> ```agda open import foundation.action-on-identifications-functions open import foundation.dependent-pair-types open import foundation.function-extensionality open import foundation.precomposition-dependent-functions open import foundation.sections open import foundation.universe-levels open import foundation.whiskering-homotopies-composition open import foundation-core.commuting-squares-of-maps open import foundation-core.commuting-triangles-of-maps open import foundation-core.equivalences open import foundation-core.fibers-of-maps open import foundation-core.function-types open import foundation-core.functoriality-dependent-pair-types open import foundation-core.homotopies open import foundation-core.identity-types open import foundation-core.retractions ``` </details> ## Idea Given a function `f : A → B` and a type `X`, the **precomposition function** by `f` ```text - ∘ f : (B → X) → (A → X) ``` is defined by `λ h x → h (f x)`. The precomposition function was already defined in [`foundation-core.precomposition-functions`](foundation-core.precomposition-functions.md). In this file we derive some further properties of the precomposition function. ## Properties ### Precomposition preserves homotopies ```agda htpy-precomp : {l1 l2 l3 : Level} {A : UU l1} {B : UU l2} {f g : A → B} (H : f ~ g) (C : UU l3) → precomp f C ~ precomp g C htpy-precomp H C h = eq-htpy (h ·l H) compute-htpy-precomp-refl-htpy : {l1 l2 l3 : Level} {A : UU l1} {B : UU l2} (f : A → B) (C : UU l3) → htpy-precomp (refl-htpy' f) C ~ refl-htpy compute-htpy-precomp-refl-htpy f C h = eq-htpy-refl-htpy (h ∘ f) ``` ### Precomposition preserves concatenation of homotopies ```agda compute-concat-htpy-precomp : { l1 l2 l3 : Level} {A : UU l1} {B : UU l2} { f g h : A → B} (H : f ~ g) (K : g ~ h) (C : UU l3) → htpy-precomp (H ∙h K) C ~ htpy-precomp H C ∙h htpy-precomp K C compute-concat-htpy-precomp H K C k = ( ap ( eq-htpy) ( eq-htpy (distributive-left-whisker-comp-concat k H K))) ∙ ( eq-htpy-concat-htpy (k ·l H) (k ·l K)) ``` ### If precomposition `- ∘ f : (Y → X) → (X → X)` has a section, then `f` has a retraction ```agda module _ {l1 l2 : Level} {X : UU l1} {Y : UU l2} (f : X → Y) where retraction-section-precomp-domain : section (precomp f X) → retraction f pr1 (retraction-section-precomp-domain s) = map-section (precomp f X) s id pr2 (retraction-section-precomp-domain s) = htpy-eq (is-section-map-section (precomp f X) s id) ``` ### Equivalences induce an equivalence from the type of homotopies between two maps to the type of homotopies between their precomposites ```agda module _ { l1 l2 l3 : Level} {A : UU l1} {B : UU l2} {C : UU l3} where equiv-htpy-precomp-htpy : (f g : B → C) (e : A ≃ B) → (f ~ g) ≃ (f ∘ map-equiv e ~ g ∘ map-equiv e) equiv-htpy-precomp-htpy f g e = equiv-htpy-precomp-htpy-Π f g e ``` ### Computations of the fibers of `precomp` The fiber of `- ∘ f : (B → X) → (A → X)` at `g ∘ f : B → X` is equivalent to the type of maps `h : B → X` equipped with a homotopy witnessing that the square ```text f A -----> B | | f | | h ∨ ∨ B -----> X g ``` commutes. ```agda module _ {l1 l2 l3 : Level} {A : UU l1} {B : UU l2} (f : A → B) (X : UU l3) where compute-coherence-triangle-fiber-precomp' : (g : A → X) → fiber (precomp f X) g ≃ Σ (B → X) (λ h → coherence-triangle-maps' g h f) compute-coherence-triangle-fiber-precomp' g = equiv-tot (λ _ → equiv-funext) compute-coherence-triangle-fiber-precomp : (g : A → X) → fiber (precomp f X) g ≃ Σ (B → X) (λ h → coherence-triangle-maps g h f) compute-coherence-triangle-fiber-precomp g = equiv-tot (λ _ → equiv-funext) ∘e equiv-fiber (precomp f X) g compute-fiber-precomp : (g : B → X) → fiber (precomp f X) (g ∘ f) ≃ Σ (B → X) (λ h → coherence-square-maps f f h g) compute-fiber-precomp g = compute-coherence-triangle-fiber-precomp (g ∘ f) compute-total-fiber-precomp : Σ (B → X) (λ g → fiber (precomp f X) (g ∘ f)) ≃ Σ (B → X) (λ u → Σ (B → X) (λ v → u ∘ f ~ v ∘ f)) compute-total-fiber-precomp = equiv-tot compute-fiber-precomp diagonal-into-fibers-precomp : (B → X) → Σ (B → X) (λ g → fiber (precomp f X) (g ∘ f)) diagonal-into-fibers-precomp = map-section-family (λ g → g , refl) ``` ### The action on identifications of precomposition by a map Consider a map `f : A → B` and two functions `g h : B → C`. Then the [action on identifications](foundation.action-on-identifications-functions.md) of `precomp f C` fits in a [commuting square](foundation-core.commuting-squares-of-maps.md) ```text ap (precomp f C) (g = h) --------------------------> (g ∘ f = h ∘ f) | | htpy-eq | | htpy-eq ∨ ∨ (g ~ h) --------------------------> (g ∘ f ~ h ∘ f). precomp f (eq-value g h) ``` Similarly, the action on identifications of `precomp f C` also fits in a commuting square ```text precomp f (eq-value g h) (g ~ h) --------------------------> (g ∘ f ~ h ∘ f) | | eq-htpy | | eq-htpy ∨ ∨ (g = h) --------------------------> (g ∘ f = h ∘ f). ap (precomp f C) ``` commutes. ```agda module _ { l1 l2 l3 : Level} {A : UU l1} {B : UU l2} {C : UU l3} (f : A → B) {g h : B → C} where compute-htpy-eq-ap-precomp : coherence-square-maps ( ap (precomp f C)) ( htpy-eq) ( htpy-eq) ( precomp-Π f (eq-value g h)) compute-htpy-eq-ap-precomp = compute-htpy-eq-ap-precomp-Π f compute-eq-htpy-ap-precomp : coherence-square-maps ( precomp-Π f (eq-value g h)) ( eq-htpy) ( eq-htpy) ( ap (precomp f C)) compute-eq-htpy-ap-precomp = vertical-inv-equiv-coherence-square-maps ( ap (precomp f C)) ( equiv-funext) ( equiv-funext) ( precomp-Π f (eq-value g h)) ( compute-htpy-eq-ap-precomp) ```