\begin{code}
{-# OPTIONS --without-K --exact-split --safe --auto-inline #-}
module UF.Retracts where
open import MLTT.Spartan
open import MLTT.AlternativePlus
open import UF.Base
open import UF.Subsingletons
has-section : {X : π€ Μ } {Y : π₯ Μ } β (X β Y) β π€ β π₯ Μ
has-section r = Ξ£ s κ (codomain r β domain r), r β s βΌ id
is-section : {X : π€ Μ } {Y : π₯ Μ } β (X β Y) β π€ β π₯ Μ
is-section s = Ξ£ r κ (codomain s β domain s), r β s βΌ id
sections-are-lc : {X : π€ Μ } {Y : π₯ Μ } (s : X β Y)
                β is-section s β left-cancellable s
sections-are-lc s (r , rs) {x} {x'} p = (rs x)β»ΒΉ β ap r p β rs x'
retract_of_ : π€ Μ β π₯ Μ β π€ β π₯ Μ
retract Y of X = Ξ£ r κ (X β Y) , has-section r
retraction : {X : π€ Μ } {Y : π₯ Μ } β retract X of Y β (Y β X)
retraction (r , s , rs) = r
section : {X : π€ Μ } {Y : π₯ Μ } β retract X of Y β (X β Y)
section (r , s , rs) = s
retract-condition : {X : π€ Μ } {Y : π₯ Μ } (Ο : retract X of Y)
                  β retraction Ο β section Ο βΌ id
retract-condition (r , s , rs) = rs
retraction-has-section : {X : π€ Μ } {Y : π₯ Μ } (Ο : retract X of Y)
                       β has-section (retraction Ο)
retraction-has-section (r , h) = h
retract-of-singleton : {X : π€ Μ } {Y : π₯ Μ }
                     β retract Y of X
                     β is-singleton X
                     β is-singleton Y
retract-of-singleton (r , s , rs) (c , Ο) = r c , (Ξ» y β ap r (Ο (s y)) β rs y)
retract-of-prop : {X : π€ Μ } {Y : π₯ Μ }
                β retract Y of X
                β is-prop X
                β is-prop Y
retract-of-prop (r , s , rs) = subtype-of-prop-is-prop s (sections-are-lc s (r , rs))
Ξ£-is-set : {X : π€ Μ } {A : X β π₯ Μ }
         β is-set X
         β ((x : X) β is-set (A x))
         β is-set (Ξ£ A)
Ξ£-is-set {π€} {π₯} {X} {A} i j {Ο} {Ο} = Ξ³
 where
  S = Ξ£ p κ prβ Ο οΌ prβ Ο , transport A p (prβ Ο) οΌ prβ Ο
  a : is-prop S
  a = Ξ£-is-prop i (Ξ» p β j (prβ Ο))
  b : retract (Ο οΌ Ο) of S
  b = to-Ξ£-οΌ , from-Ξ£-οΌ , tofrom-Ξ£-οΌ
  Ξ³ : is-prop (Ο οΌ Ο)
  Ξ³ = retract-of-prop b a
identity-retraction : {X : π€ Μ } β retract X of X
identity-retraction = id , id , Ξ» x β refl
has-section-closed-under-βΌ : {X : π€ Μ } {Y : π₯ Μ } (f g : X β Y)
                           β has-section f
                           β g βΌ f
                           β has-section g
has-section-closed-under-βΌ {π€} {π₯} {X} {Y} f g (s , fs) h =
 (s , Ξ» y β g (s y) οΌβ¨ h (s y) β© f (s y) οΌβ¨ fs y β© y β)
has-section-closed-under-βΌ' : {X : π€ Μ } {Y : π₯ Μ } {f g : X β Y}
                            β has-section f
                            β f βΌ g
                            β has-section g
has-section-closed-under-βΌ' ise h = has-section-closed-under-βΌ _ _ ise (Ξ» x β (h x)β»ΒΉ)
is-section-closed-under-βΌ : {X : π€ Μ } {Y : π₯ Μ } (f g : X β Y)
                          β is-section f
                          β  g βΌ f
                          β is-section g
is-section-closed-under-βΌ {π€} {π₯} {X} {Y} f g (r , rf) h =
  (r , Ξ» x β r (g x) οΌβ¨ ap r (h x) β©
             r (f x) οΌβ¨ rf x β©
             x       β)
is-section-closed-under-βΌ' : {X : π€ Μ } {Y : π₯ Μ } {f g : X β Y}
                           β is-section f
                           β f βΌ g
                           β is-section g
is-section-closed-under-βΌ' ise h = is-section-closed-under-βΌ _ _ ise (Ξ» x β (h x)β»ΒΉ)
\end{code}
Surjection expressed in Curry-Howard logic amounts to retraction.
\begin{code}
has-section' : {X : π€ Μ } {Y : π₯ Μ } (f : X β Y) β π€ β π₯ Μ
has-section' f = (y : codomain f) β Ξ£ x κ domain f , f x οΌ y
retract_Of_ : π€ Μ β π₯ Μ β π€ β π₯ Μ
retract Y Of X = Ξ£ f κ (X β Y) , has-section' f
retract-of-gives-retract-Of : {X : π€ Μ } {Y : π₯ Μ } β retract Y of X β retract Y Of X
retract-of-gives-retract-Of {π€} {π₯} {X} {Y} Ο = (retraction Ο , hass)
 where
  hass : (y : Y) β Ξ£ x κ X , retraction Ο x οΌ y
  hass y = section Ο y , retract-condition Ο y
retract-Of-gives-retract-of : {X : π€ Μ } {Y : π₯ Μ } β retract Y Of X β retract Y of X
retract-Of-gives-retract-of {π€} {π₯} {X} {Y} (f , hass) = (f , Ο)
 where
  Ο : Ξ£ s κ (Y β X) , f β s βΌ id
  Ο = (Ξ» y β prβ (hass y)) , (Ξ» y β prβ (hass y))
retracts-compose : {X : π€ Μ } {Y : π₯ Μ } {Z : π¦ Μ }
                 β retract Y of X
                 β retract Z of Y
                 β retract Z of X
retracts-compose (r , s , rs) (r' , s' , rs') =
  r' β r , s β s' , Ξ» z β r' (r (s (s' z))) οΌβ¨ ap r' (rs (s' z)) β©
                          r' (s' z)         οΌβ¨ rs' z β©
                          z                 β
Γ-retract : {X : π€ Μ } {Y : π₯ Μ } {A : π¦ Μ } {B : π£ Μ }
          β retract X of A
          β retract Y of B
          β retract (X Γ Y) of (A Γ B)
Γ-retract {π€} {π₯} {π¦} {π£} {X} {Y} {A} {B} (r , s , rs) (t , u , tu) = f , g , fg
 where
  f : A Γ B β X Γ Y
  f (a , b) = (r a , t b)
  g : X Γ Y β A Γ B
  g (x , y) = s x , u y
  fg : (z : X Γ Y) β f (g z) οΌ z
  fg (x , y) = to-Γ-οΌ (rs x) (tu y)
+-retract : {X : π€ Μ } {Y : π¦ Μ } {A : π₯ Μ } {B : π£ Μ }
          β retract X of A
          β retract Y of B
          β retract (X + Y) of (A + B)
+-retract {π€} {π₯} {π¦} {π£} {X} {Y} {A} {B} (r , s , rs) (t , u , tu) = f , g , fg
 where
  f : A + B β X + Y
  f (inl a) = inl (r a)
  f (inr b) = inr (t b)
  g : X + Y β A + B
  g (inl x) = inl (s x)
  g (inr y) = inr (u y)
  fg : (p : X + Y) β f (g p) οΌ p
  fg (inl x) = ap inl (rs x)
  fg (inr y) = ap inr (tu y)
+'-retract-of-+ : {X Y : π€ Μ }
                β retract (X +' Y) of (X + Y)
+'-retract-of-+ {π€} {X} {Y} = f , g , fg
 where
  f : X + Y β X +' Y
  f (inl x) = β , x
  f (inr y) = β , y
  g : X +' Y β X + Y
  g (β , x) = inl x
  g (β , y) = inr y
  fg : (z : X +' Y) β f (g z) οΌ z
  fg (β , x) = refl
  fg (β , y) = refl
+-retract-of-+' : {X Y : π€ Μ }
                β retract (X + Y) of (X +' Y)
+-retract-of-+' {π€} {X} {Y} = g , f , gf
 where
  f : X + Y β X +' Y
  f (inl x) = β , x
  f (inr y) = β , y
  g : X +' Y β X + Y
  g (β , x) = inl x
  g (β , y) = inr y
  gf : (z : X + Y) β g (f z) οΌ z
  gf (inl x) = refl
  gf (inr y) = refl
+'-retract : {X Y : π€ Μ } {A B : π₯ Μ }
           β retract X of A
           β retract Y of B
           β retract (X +' Y) of (A +' B)
+'-retract {π€} {π₯} {X} {Y} {A} {B} (r , s , rs) (t , u , tu) = f , g , fg
 where
  f : A +' B β X +' Y
  f (β , a) = β , r a
  f (β , b) = β , t b
  g : X +' Y β A +' B
  g (β , x) = β , s x
  g (β , y) = β , u y
  fg : (p : X +' Y) β f (g p) οΌ p
  fg (β , x) = ap (Ξ» - β (β , -)) (rs x)
  fg (β , y) = ap (Ξ» - β (β , -)) (tu y)
Ξ£-reindex-retract : {X : π€ Μ } {Y : π₯ Μ } {A : X β π¦ Μ } (r : Y β X)
                  β has-section r β retract (Ξ£ A) of (Ξ£ (A β r))
Ξ£-reindex-retract {π€} {π₯} {π¦} {X} {Y} {A} r (s , rs) = Ξ³ , Ο , Ξ³Ο
 where
  Ξ³ : (Ξ£ y κ Y , A (r y)) β Ξ£ A
  Ξ³ (y , a) = (r y , a)
  Ο : Ξ£ A β Ξ£ y κ Y , A (r y)
  Ο (x , a) = (s x , transportβ»ΒΉ A (rs x) a)
  Ξ³Ο : (Ο : Ξ£ A) β Ξ³ (Ο Ο) οΌ Ο
  Ξ³Ο (x , a) = to-Ξ£-οΌ (rs x , p)
   where
    p : transport A (rs x) (transportβ»ΒΉ A (rs x) a) οΌ a
    p = back-and-forth-transport (rs x)
Ξ£-reindex-retract' : {X : π€ Μ } {Y : π₯ Μ } {A : X β π¦ Μ }
                   β (Ο : retract X of Y)
                   β retract (Ξ£ x κ X , A x) of (Ξ£ y κ Y , A (retraction Ο y))
Ξ£-reindex-retract' (r , s , rs) = Ξ£-reindex-retract r (s , rs)
Ξ£-retract : {X : π€ Μ } (A : X β π₯ Μ ) (B : X β π¦ Μ )
          β ((x : X) β retract (A x) of (B x))
          β retract (Ξ£ A) of (Ξ£ B)
Ξ£-retract {π€} {π₯} {π¦} {X} A B Ο = NatΞ£ R , NatΞ£ S , rs
 where
  R : (x : X) β B x β A x
  R x = retraction (Ο x)
  S : (x : X) β A x β B x
  S x = section (Ο x)
  RS : (x : X) (a : A x) β R x (S x a) οΌ a
  RS x = retract-condition (Ο x)
  rs : (Ο : Ξ£ A) β NatΞ£ R (NatΞ£ S Ο) οΌ Ο
  rs (x , a) = to-Ξ£-οΌ' (RS x a)
retract-π+π-of-π : retract π + π of π
retract-π+π-of-π = f , (g , fg)
 where
  f : π β π {π€β} + π {π€β}
  f = π-cases (inl β) (inr β)
  g : π + π β π
  g = cases (Ξ» x β β) (Ξ» x β β)
  fg : (x : π + π) β f (g x) οΌ x
  fg (inl β) = refl
  fg (inr β) = refl
\end{code}
TODO. Several retractions here are actually equivalences. So some code
should be generalized and moved to an equivalences module. Similarly,
some retracts proved here are also shown as equivalences in other
modules, and hence there is some amount of repetition that should be
removed. This is the result of (1) merging initially independent
developments, and (2) work over many years with uncontrolled growth.
\begin{code}
Ξ£-retractβ : {X : π€ Μ } {Y : X β π₯ Μ } {A : π¦ Μ } {B : π£ Μ }
           β retract X of A
           β ((x : X) β retract  (Y x) of B)
           β retract (Ξ£ Y) of (A Γ B)
Ξ£-retractβ {π€} {π₯} {π¦} {π£} {X} {Y} {A} {B} (r , s , rs) R = f , g , gf
 where
  Ο : (x : X) β B β Y x
  Ο x = retraction (R x)
  Ξ³ : (x : X) β Y x β B
  Ξ³ x = section (R x)
  ΟΞ³ : (x : X) β (y : Y x) β Ο x (Ξ³ x y) οΌ y
  ΟΞ³ x = retract-condition (R x)
  f : A Γ B β Ξ£ Y
  f (a , b) = r a , Ο (r a) b
  g : Ξ£ Y β A Γ B
  g (x , y) = s x , Ξ³ x y
  gf : (z : Ξ£ Y) β f (g z) οΌ z
  gf (x , y) = to-Ξ£-οΌ (rs x , l (rs x))
   where
    l : {x' : X} (p : x' οΌ x) β transport Y p (Ο x' (Ξ³ x y)) οΌ y
    l refl = ΟΞ³ x y
retract-π+π-of-β : retract π + π of β
retract-π+π-of-β = r , s , rs
 where
  r : β β π + π
  r zero = inl β
  r (succ _) = inr β
  s : π + π β β
  s (inl β) = zero
  s (inr β) = succ zero
  rs : (z : π {π€β} + π {π€β}) β r (s z) οΌ z
  rs (inl β) = refl
  rs (inr β) = refl
\end{code}
Added 5th March 2019. Notation for composing retracts. I should have
added this ages ago to make the above proofs more readable.
\begin{code}
_β_ : π€ Μ β π₯ Μ β π€ β π₯ Μ
Y β X = retract Y of X
_ββ¨_β©_ : (X : π€ Μ ) {Y : π₯ Μ } {Z : π¦ Μ } β X β Y β Y β Z β X β Z
_ ββ¨ d β© e = retracts-compose e d
β-refl : (X : π€ Μ ) β X β X
β-refl X = identity-retraction {universe-of X} {X}
_β : (X : π€ Μ ) β X β X
_β = β-refl
\end{code}
Fixities:
\begin{code}
infix  0 _β_
infix  1 _β
infixr 0 _ββ¨_β©_
\end{code}
Added 20 February 2020 by Tom de Jong.
\begin{code}
ap-of-section-is-section : {X : π€ Μ } {Y : π₯ Μ } (s : X β Y)
                         β is-section s
                         β (x x' : X) β is-section (ap s {x} {x'})
ap-of-section-is-section {π€} {π₯} {X} {Y} s (r , rs) x x' = Ο , Οap
 where
  Ο : s x οΌ s x' β x οΌ x'
  Ο q = x        οΌβ¨ (rs x) β»ΒΉ β©
        r (s x)  οΌβ¨ ap r q β©
        r (s x') οΌβ¨ rs x' β©
        x'       β
  Οap : (p : x οΌ x') β Ο (ap s p) οΌ p
  Οap p = Ο (ap s p)                          οΌβ¨ by-definition β©
          (rs x) β»ΒΉ β (ap r (ap s p) β rs x') οΌβ¨ i β©
          (rs x) β»ΒΉ β ap r (ap s p) β rs x'   οΌβ¨ ii β©
          (rs x) β»ΒΉ β ap (r β s) p β  rs x'   οΌβ¨ iii β©
          ap id p                             οΌβ¨ (ap-id-is-id' p)β»ΒΉ β©
          p                                   β
   where
    i   = βassoc ((rs x) β»ΒΉ) (ap r (ap s p)) (rs x') β»ΒΉ
    ii  = ap (Ξ» - β (rs x) β»ΒΉ β - β rs x') (ap-ap s r p)
    iii = homotopies-are-natural'' (r β s) id rs {x} {x'} {p}
\end{code}
I would phrase this in terms of fibers, but fiber is defined in UF.Equiv which
imports this file.
\begin{code}
Ξ£-section-retract : {X : π€ Μ } {Y : π₯ Μ } {Z : π¦ Μ } (Ο : Y β Z) (g : X β Y)
                  β (y : Y)
                  β (Ξ£ x κ X , g x οΌ y)
                  β (Ξ£ x κ X , section Ο (g x) οΌ section Ο y)
Ξ£-section-retract {π€} {π₯} {π¦} {X} {Y} {Z} (r , s , rs) g y =
 Ξ£-retract (Ξ» x β g x οΌ y) (Ξ» x β s (g x) οΌ s y) Ξ³
  where
   Ξ³ : (x : X) β (g x οΌ y) β (s (g x) οΌ s y)
   Ξ³ x = Ο , (Ο , ΟΟ)
    where
     Ο : g x οΌ y β s (g x) οΌ s y
     Ο = ap s
     Ο : s (g x) οΌ s y β g x οΌ y
     Ο = prβ (ap-of-section-is-section s (r , rs) (g x) y)
     ΟΟ : (p : g x οΌ y) β Ο (Ο p) οΌ p
     ΟΟ = prβ (ap-of-section-is-section s ((r , rs)) (g x) y)
\end{code}