Ayberk Tosun.

Formulations of some alternative definitions of the notion of continuity from
`MFPSAndVariations.Continuity` and proofs of their equivalences with the
original definitions.

First equivalence, for continuity, proved on 2023-06-13.

\begin{code}

{-# OPTIONS --safe --without-K --exact-split #-}

open import UF.FunExt

module EffectfulForcing.MFPSAndVariations.ContinuityProperties (fe : Fun-Ext) where

open import EffectfulForcing.MFPSAndVariations.Continuity
open import MGS.hlevels using (ℕ-is-set)
open import MLTT.Athenian
open import MLTT.Spartan
open import MLTT.Two-Properties
open import Naturals.Order
open import Naturals.Properties using (succ-no-fp; zero-not-positive)
open import UF.Embeddings
open import UF.Equiv
open import UF.Subsingletons
open import UF.Subsingletons-FunExt

\end{code}

We first formulate the `α =⦅ n ⦆ β` relation expressing that two sequences `α`,
`β` of natural numbers are equal up to (not inclusive) some bound `n`. These
have been adapted from the `CantorSearch` module authored by Martín Escardó
(including the proofs `agreement→` and `agreement←`).

\begin{code}

hd : {X : 𝓤₀  ̇}  (  X)  X
hd α = α 0

tl : {X : 𝓤₀  ̇}  (  X)    X
tl α = α  succ

_=⦅_⦆_ : {X : 𝓤₀  ̇}  (  X)    (  X)  𝓤₀  ̇
α =⦅ 0       β = 𝟙
α =⦅ succ n  β = (hd α  hd β) × tl α =⦅ n  tl β

\end{code}

A small lemma characterizing this relation.

\begin{code}

agreement→ : {X : 𝓤₀  ̇} (α α′ :   X) (n : )
            α =⦅ n  α′
            (i : )  (i <ℕ n)  α i  α′ i
agreement→ α α′ zero     p         zero     ()
agreement→ α α′ (succ n) (p₁ , p₂) zero     q = p₁
agreement→ α α′ (succ n) (p₁ , p₂) (succ i) q = IH i q
 where
  IH : (j : )  j <ℕ n  α (succ j)  α′ (succ j)
  IH = agreement→ (tl α) (tl α′) n p₂

agreement← : (α α′ : Baire) (n : )
            ((i : )  (i <ℕ n)  α i  α′ i)
            α =⦅ n  α′
agreement← α α′ zero     φ = 
agreement← α α′ (succ n) φ = φ 0  , (agreement← (tl α) (tl α′) n ψ)
 where
  ψ : (j : )  j <ℕ n  tl α j  tl α′ j
  ψ j p = φ (succ j) (succ-monotone (succ j) n p)

\end{code}

\section{Continuity}

Using the `_=⦅_⦆_` relation, we express the “usual” notion of continuity
mentioned in the TODO. We call this `is-continuous₀` and prove at the end of the
module that it is logically equivalent to `is-continuous`.

\begin{code}

is-continuous₀ : (Baire  )  𝓤₀  ̇
is-continuous₀ f =
 (α : Baire)  Σ n   , ((α′ : Baire)  α =⦅ n  α′  f α  f α′)

\end{code}

We also define the following operation `modulus-at₀` that projects out the
modulus of continuity computed by a proof of `is-continuous₀`:

\begin{code}

modulus-at₀ : (f : Baire  )  is-continuous₀ f  Baire  
modulus-at₀ f c α = pr₁ (c α)

\end{code}

We now formulate an alternative non-inductive version of the `_=⟪_⟫_` relation
that we call `_=⟪_⟫₀_` and prove its logical equivalence with `_=⟪_⟫_`. The
motivation for the non-inductive formulation is to use it as an intermediate
step to simplify our proofs.

\begin{code}

_=⟪_⟫₀_ : {X : 𝓤₀  ̇}  (  X)  List   (  X)  𝓤₀  ̇
_=⟪_⟫₀_ α₁ s α₂ = (i : )  member i s  α₁ i  α₂ i

\end{code}

It is an obvious fact that equality up to `i ∷ is` (with `_=⟪_⟫₀_`) entails
equality up to `is`. We record this fact as `=⟪⟫₀-cons`.

\begin{code}

=⟪⟫₀-cons : {X : 𝓤₀  ̇} (α α′ :   X) (i : ) (is : List )
            α =⟪ i  is ⟫₀ α′  α =⟪ is ⟫₀ α′
=⟪⟫₀-cons α α′ i is t j p = t j (in-tail p)

\end{code}

We now generalize this fact. Equality up to `ms ++ ns` entails both equality up
to `ms` and up to `ns`. In other words, `α₁ =⟪_⟫₀ α₂` is a semigroup
homomorphism from semigroup `(List ℕ, _++_)` into semigroup `(𝓤₀, _×_)`.

\begin{code}

=⟪⟫-++-lemma₁ : {X : 𝓤₀  ̇} (α₁ α₂ :   X) (ms ns : List )
                α₁ =⟪ ms ++ ns ⟫₀ α₂
                (α₁ =⟪ ms ⟫₀ α₂) × (α₁ =⟪ ns ⟫₀ α₂)
=⟪⟫-++-lemma₁ α₁ α₂ ms ns p =  , 
 where
   : α₁ =⟪ ms ⟫₀ α₂
   n q = p n (right-concatenation-preserves-membership n ms ns q)

   : α₁ =⟪ ns ⟫₀ α₂
   n q = p n (left-concatenation-preserves-membership n ns ms q)

=⟪⟫-++-lemma₂ : {X : 𝓤₀  ̇} (α₁ α₂ :   X) (ms ns : List )
                (α₁ =⟪ ms ⟫₀ α₂) × (α₁ =⟪ ns ⟫₀ α₂)
                α₁ =⟪ ms ++ ns ⟫₀ α₂
=⟪⟫-++-lemma₂ α₁ α₂ ms ns (p , q) i r =
 cases (p i) (q i) (++-membership₁ i ms ns r)

=⟪⟫-respects-list-concatenation : {X : 𝓤₀  ̇} (α₁ α₂ :   X) (ms ns : List )
                                  α₁ =⟪ ms ++ ns ⟫₀ α₂
                                  (α₁ =⟪ ms ⟫₀ α₂) × (α₁ =⟪ ns ⟫₀ α₂)
=⟪⟫-respects-list-concatenation α₁ α₂ ms ns =
 =⟪⟫-++-lemma₁ α₁ α₂ ms ns , =⟪⟫-++-lemma₂ α₁ α₂ ms ns

\end{code}

We now record the fact that the alternative version of `_=⟪_⟫_` is logically
equivalent to the original version.

\begin{code}

=⟪⟫₀-implies-=⟪⟫ : {X : 𝓤₀  ̇} (α α′ :   X) (s : List )
                    α =⟪ s ⟫₀ α′  α =⟪ s   α′
=⟪⟫₀-implies-=⟪⟫ α α′ []       t = []
=⟪⟫₀-implies-=⟪⟫ α α′ (i  is) t = t i in-head  IH
 where
  IH = =⟪⟫₀-implies-=⟪⟫ α α′ is (=⟪⟫₀-cons α α′ i is t)

=⟪⟫-implies-=⟪⟫₀ : {X : 𝓤₀  ̇} (α β :   X) (s : List )
                    α =⟪ s  β  α =⟪ s ⟫₀ β
=⟪⟫-implies-=⟪⟫₀ α α′ []       []       i ()
=⟪⟫-implies-=⟪⟫₀ α α′ (i  is) (p  ps) i in-head     = p
=⟪⟫-implies-=⟪⟫₀ α α′ (_  is) (p  ps) j (in-tail q) = IH
 where
  IH = =⟪⟫-implies-=⟪⟫₀ α α′ is ps j q

\end{code}

We now define the `maximum` function computing the maximum of a given list of
natural numbers.

\begin{code}

maximum : List   
maximum = foldr max 0

\end{code}

Recall that the first (logical) equivalence we would like to prove is that
between `is-continuous` and `is-continuous₀`. We tackle this in the next
section, and the converse direction in the section after that.

\section{`is-continuous` implies `is-continuous₀`}

The fact that `is-continuous` implies `is-continuous₀` is the easy direction of
the equivalence in consideration. We need only two minor lemmas to conclude
this.

\begin{code}

member-implies-below-max : (s : List ) (i : )  member i s  i ≤ℕ maximum s
member-implies-below-max (m  ns) m in-head     = max-≤-upper-bound m (maximum ns)
member-implies-below-max (n  ns) m (in-tail p) =
 ≤-trans m _ _ IH (max-≤-upper-bound' (maximum ns) n)
  where
   IH =(member-implies-below-max ns m p)

=⦅⦆-implies-=⟪⟫ : {X : 𝓤₀  ̇} (α α′ :   X) (s : List )
                   α =⦅ succ (maximum s)  α′
                   α =⟪ s  α′
=⦅⦆-implies-=⟪⟫ α α′ s t = =⟪⟫₀-implies-=⟪⟫ α α′ s 
 where
  m : 
  m = succ (maximum s)

   : α =⟪ s ⟫₀ α′
   i p = agreement→ α α′ m t i (member-implies-below-max s i p)

continuity-implies-continuity₀ : (f : Baire  )
                                is-continuous f  is-continuous₀ f
continuity-implies-continuity₀ f c = 
 where
   : is-continuous₀ f
   α = m , γ
   where
    s = pr₁ (c α)
    m = succ (maximum s)

    γ : (α′ : Baire)  α =⦅ m  α′  f α  f α′
    γ α′ p = pr₂ (c α) α′ (=⦅⦆-implies-=⟪⟫ α α′ s p)

\end{code}

\section{`is-continuous₀` implies `is-continuous`}

We now address the converse direction which is harder.

We first define a `range` function such that `range n` is the list `[0..n]` and
prove its completeness.

\begin{code}

range :   List 
range zero     = [ 0 ]
range (succ n) = succ n  range n

range-succ : (i n : )  member i (range n)  member (succ i) (range (succ n))
range-succ zero     zero     p            = in-head
range-succ (succ i) zero     (in-tail ())
range-succ zero     (succ n) (in-tail p)  = in-tail (range-succ zero n p)
range-succ (succ i) (succ i) in-head      = in-head
range-succ (succ i) (succ n) (in-tail p)  = in-tail (range-succ (succ i) n p)

range-is-complete : (i n : )  i ≤ℕ n  member i (range n)
range-is-complete zero     zero     p = in-head
range-is-complete zero     (succ n) p = in-tail (range-is-complete zero n p)
range-is-complete (succ i) (succ n) p = range-succ i n (range-is-complete i n p)

\end{code}

We combine all these into a final lemma that we need:

\begin{code}

=⟪⟫-range-implies-=⦅⦆ : (α α′ : Baire) (n : )
                         α =⟪ range n  α′
                         α =⦅ n  α′
=⟪⟫-range-implies-=⦅⦆ α α′ n p = agreement← α α′ n 
 where
   : (j : )  j <ℕ n  α j  α′ j
   j q = =⟪⟫-implies-=⟪⟫₀ α α′ (range n) p j 
   where
     : member j (range n)
     = range-is-complete j n (<-coarser-than-≤ j n q)

\end{code}

The result we want now follows easily:

\begin{code}

continuity₀-implies-continuity : (f : Baire  )
                                is-continuous₀ f  is-continuous f
continuity₀-implies-continuity f c α = range m , γ
 where
  m = modulus-at₀ f c α

  γ : (α′ : Baire)  α =⟪ range m  α′  f α  f α′
  γ α′ p = pr₂ (c α) α′ (=⟪⟫-range-implies-=⦅⦆ α α′ m p)

\end{code}

Finally, we record the logical equivalence as a fact in itself.

\begin{code}

continuous₀-iff-continuous : (f : Baire  )
                            is-continuous₀ f  is-continuous f
continuous₀-iff-continuous f =  , 
 where
   = continuity₀-implies-continuity f
   = continuity-implies-continuity₀ f

\end{code}

\section{Uniform continuity}

We start by defining the notion of being “Boolean-valued”: a point `α : Baire`
of the Baire space is called Boolean if its range is a subset of `{0, 1}`.

\begin{code}

is-boolean-valued :   𝓤₀  ̇
is-boolean-valued n = (n  0) + (n  1)

embedding-𝟚-ℕ-gives-boolean : (b : 𝟚)  is-boolean-valued (embedding-𝟚-ℕ b)
embedding-𝟚-ℕ-gives-boolean  = inl refl
embedding-𝟚-ℕ-gives-boolean  = inr refl

\end{code}

The following is the inverse of `embedding-𝟚-ℕ`: it takes us back to `𝟚` from a
Boolean-valued natural number.

\begin{code}

to-bool : (n : )  is-boolean-valued n  𝟚
to-bool _ (inl p) = 
to-bool _ (inr q) = 

\end{code}

A point `α : Baire` of the Baire space is called a _Boolean point_ if its range
is a subset of {`₀`, `₁`}.

\begin{code}

is-boolean-point : Baire  𝓤₀  ̇
is-boolean-point α = (n : )  is-boolean-valued (α n)

\end{code}

Being Boolean-valued is a proposition, from which it follows that being
a Boolean point is also a proposition.

\begin{code}

being-boolean-is-prop : (α : Baire) (i : )  is-prop (is-boolean-valued (α i))
being-boolean-is-prop α i (inl p) (inl q) = ap inl (ℕ-is-set (α i) 0 p q)
being-boolean-is-prop α i (inr p) (inr q) = ap inr (ℕ-is-set (α i) 1 p q)
being-boolean-is-prop α i (inl p) (inr q) = 𝟘-elim (succ-no-fp 0 )
                                             where
                                               : 0  1
                                               = 0 =⟨ p ⁻¹  α i =⟨ q  1 
being-boolean-is-prop α i (inr p) (inl q) = 𝟘-elim (succ-no-fp 0 )
                                             where
                                               : 0  1
                                               = 0 =⟨ q ⁻¹  α i =⟨ p  1 

being-boolean-point-is-prop : (α : Baire)  is-prop (is-boolean-point α)
being-boolean-point-is-prop α = Π-is-prop fe (being-boolean-is-prop α)

\end{code}

Using this, we can give an alternative definition of the Cantor space as the
subtype of Baire space consisting of the Boolean points,

\begin{code}

Cantor₀ : 𝓤₀  ̇
Cantor₀ = Σ α  Baire , is-boolean-point α

point-of : Cantor₀  Baire
point-of (α , _) = α

\end{code}

This is clearly equivalent to the usual definition.

\begin{code}

to-baire-gives-boolean-point : (α : Cantor)  is-boolean-point (embedding-C-B α)
to-baire-gives-boolean-point α = embedding-𝟚-ℕ-gives-boolean  α

\end{code}

We now prove the equivalence between `Cantor` and `Cantor₀`.

\begin{code}

to-cantor₀ : Cantor  Cantor₀
to-cantor₀ α = embedding-C-B α , to-baire-gives-boolean-point α

to-cantor : Cantor₀  Cantor
to-cantor (α , p) = λ n  to-bool (α n) (p n)

\end{code}

\begin{code}

embedding-𝟚-ℕ-0-implies-is-₀ : (b : 𝟚)  embedding-𝟚-ℕ b  0  b  
embedding-𝟚-ℕ-0-implies-is-₀  p = refl

embedding-𝟚-ℕ-1-implies-is-₁ : (b : 𝟚)  embedding-𝟚-ℕ b  1  b  
embedding-𝟚-ℕ-1-implies-is-₁  p = refl

embedding-𝟚-ℕ-is-embedding : is-embedding embedding-𝟚-ℕ
embedding-𝟚-ℕ-is-embedding m (b , p) (c , q) = to-subtype-=  
 where
   : (b : 𝟚)  is-prop (embedding-𝟚-ℕ b  m)
   b = ℕ-is-set (embedding-𝟚-ℕ b) m

  φ : embedding-𝟚-ℕ b  embedding-𝟚-ℕ c
  φ = embedding-𝟚-ℕ b =⟨ p  m =⟨ q ⁻¹  embedding-𝟚-ℕ c 

  ϑ₁ : b    c    b  c
  ϑ₁ p q = b =⟨ p   =⟨ q ⁻¹  c 

  ϑ₂ : b    c    b  c
  ϑ₂ p q = 𝟘-elim (zero-not-positive (embedding-𝟚-ℕ ) ϟ)
   where
    ϟ : 0  1
    ϟ = 0               =⟨ refl                  
        embedding-𝟚-ℕ  =⟨ ap embedding-𝟚-ℕ p ⁻¹ 
        embedding-𝟚-ℕ b =⟨ φ                     
        embedding-𝟚-ℕ c =⟨ ap embedding-𝟚-ℕ q    
        embedding-𝟚-ℕ  =⟨ refl                  
        1               

  ϑ₃ : b    c    b  c
  ϑ₃ p q = 𝟘-elim (zero-not-positive (embedding-𝟚-ℕ ) ϟ)
   where
    ϟ : 0  1
    ϟ = 0                  =⟨ refl                 
        embedding-𝟚-ℕ    =⟨ ap embedding-𝟚-ℕ q ⁻¹ 
        embedding-𝟚-ℕ c   =⟨ φ ⁻¹                  
        embedding-𝟚-ℕ b   =⟨ ap embedding-𝟚-ℕ p    
        1                  

  ϑ₄ : b    c    b  c
  ϑ₄ p q = b =⟨ p   =⟨ q ⁻¹  c 

  ξ : b    b  c
  ξ r = cases (ϑ₁ r) (ϑ₂ r) (𝟚-possibilities c)

  ζ : b    b  c
  ζ r = cases (ϑ₃ r) (ϑ₄ r) (𝟚-possibilities c)

   : b  c
   = cases ξ ζ (𝟚-possibilities b)

\end{code}

The map `to-cantor₀` is a section whose retraction is the map `to-cantor`

\begin{code}

to-cantor-cancels-to-cantor₀ : (α : Cantor)  to-cantor (to-cantor₀ α)  α
to-cantor-cancels-to-cantor₀ α = dfunext fe 
 where
   : (n : )
     to-bool (embedding-𝟚-ℕ (α n)) (to-baire-gives-boolean-point α n)  α n
   n = cases †₁ †₂ (to-baire-gives-boolean-point α n)
   where
    †₁ : embedding-𝟚-ℕ (α n)  0
        to-bool (embedding-𝟚-ℕ (α n)) (to-baire-gives-boolean-point α n)  α n
    †₁ p =
     to-bool (embedding-𝟚-ℕ (α n)) (embedding-𝟚-ℕ-gives-boolean (α n)) =⟨  
     to-bool 0 (inl refl)                                              =⟨  
     α n                                                               
      where
        = ap
             -  to-bool (embedding-𝟚-ℕ -) (embedding-𝟚-ℕ-gives-boolean -))
            (embedding-𝟚-ℕ-0-implies-is-₀ (α n) p)
        = embedding-𝟚-ℕ-0-implies-is-₀ (α n) p ⁻¹

    †₂ : embedding-𝟚-ℕ (α n)  1
        to-bool (embedding-𝟚-ℕ (α n)) (to-baire-gives-boolean-point α n)  α n
    †₂ p =
     to-bool (embedding-𝟚-ℕ (α n)) (embedding-𝟚-ℕ-gives-boolean (α n)) =⟨  
     to-bool 1 (inr refl)                                              =⟨  
     α n                                                               
      where
        = ap
             -  to-bool (embedding-𝟚-ℕ -) (embedding-𝟚-ℕ-gives-boolean -))
            (embedding-𝟚-ℕ-1-implies-is-₁ (α n) p)
        = embedding-𝟚-ℕ-1-implies-is-₁ (α n) p ⁻¹

point-of-lemma : (α : Cantor)
                point-of (to-cantor₀ α)  embedding-𝟚-ℕ  α
point-of-lemma α = λ _  refl

to-bool-lemma₁ : (α : Baire) (bv : is-boolean-point α) (i : )
               α i  0  to-bool (α i) (bv i)  
to-bool-lemma₁ α bv i p = ap (to-bool (α i)) 
  where
    : bv i  inl p
    = being-boolean-is-prop α i (bv i) (inl p)

to-bool-lemma₂ : (α : Baire) (bv : is-boolean-point α) (i : )
                α i  1  to-bool (α i) (bv i)  
to-bool-lemma₂ α bv i p = ap (to-bool (α i)) 
  where
    : bv i  inr p
    = being-boolean-is-prop α i (bv i) (inr p)

to-cantor₀-cancels-to-cantor : to-cantor₀  to-cantor  id
to-cantor₀-cancels-to-cantor (α , bv) = to-subtype-= being-boolean-point-is-prop 
  where
   ‡₁ : (i : )  α i  0  embedding-C-B (to-cantor (α , bv)) i  α i
   ‡₁ i p = embedding-𝟚-ℕ (to-bool (α i) (bv i)) =⟨  
            0                                    =⟨ p ⁻¹ 
            α i                                  
             where
               = ap embedding-𝟚-ℕ (to-bool-lemma₁ α bv i p)

   ‡₂ : (i : )  α i  1  embedding-C-B (to-cantor (α , bv)) i  α i
   ‡₂ i p = embedding-C-B (to-cantor (α , bv)) i =⟨ refl 
            embedding-𝟚-ℕ (to-bool (α i) (bv i)) =⟨  
            embedding-𝟚-ℕ                       =⟨ refl 
            1                                    =⟨ p ⁻¹ 
            α i                                  
             where
               = ap embedding-𝟚-ℕ (to-bool-lemma₂ α bv i p)

    : embedding-C-B (to-cantor (α , bv))  α
    i = embedding-C-B (to-cantor (α , bv)) i =⟨ refl 
         embedding-𝟚-ℕ (to-bool (α i) (bv i)) =⟨     
         α i                                  
          where
            : embedding-𝟚-ℕ (to-bool (α i) (bv i))  α i
            = cases (‡₁ i) (‡₂ i) (bv i)


    : embedding-C-B (to-cantor (α , bv))  α
    = dfunext fe 

cantor-equiv-cantor₀ : Cantor  Cantor₀
cantor-equiv-cantor₀ = to-cantor₀ , (to-cantor , φ) , to-cantor , ψ
 where
  φ : to-cantor₀  to-cantor  id
  φ = to-cantor₀-cancels-to-cantor

  ψ : to-cantor  to-cantor₀  id
  ψ = to-cantor-cancels-to-cantor₀

\end{code}

Now, we start working towards showing the equivalence of the alternative notion
of uniform continuity with the original one. We define the following function
`sequentialize` that flattens a binary tree into a list.

\begin{code}

sequentialize : {X : 𝓤₀  ̇}  BT X  List X
sequentialize []      = []
sequentialize (x  φ) = x  sequentialize (φ ) ++ sequentialize (φ )

\end{code}

Recall the `maximum` operation that we used in the proof of
`continuous₀-iff-continuous`. We now define an analogue of this operation for
uniform continuity, on binary trees instead of lists.

\begin{code}

maximumᵤ : BT   
maximumᵤ []      = 0
maximumᵤ (n  φ) = max n (max (maximumᵤ (φ )) (maximumᵤ (φ )))

\end{code}

Alternatively, this operation could also be defined as:

\begin{code}

maximumᵤ′ : BT   
maximumᵤ′ = maximum  sequentialize

\end{code}

We now prove a lemma that we need about `maximum`: it map `ms ++ ns` to the
binary maximum of the maxima of `ms` and `ns`.

\begin{code}

maximum-maps-++-to-max-of-maximum
 : (ms ns : List )
  maximum (ms ++ ns)  max (maximum ms) (maximum ns)
maximum-maps-++-to-max-of-maximum []       ns = refl
maximum-maps-++-to-max-of-maximum (m  ms) ns = 
 where
  IH : maximum (ms ++ ns)  max (maximum ms) (maximum ns)
  IH = maximum-maps-++-to-max-of-maximum ms ns

   = ap (max m) IH
   = max-assoc m (maximum ms) (maximum ns) ⁻¹

   : max m (maximum (ms ++ ns))  max (max m (maximum (ms))) (maximum ns)
   = max m (maximum (ms ++ ns))              =⟨  
      max m (max (maximum ms) (maximum ns))   =⟨  
      max (max m (maximum ms)) (maximum ns)   

\end{code}

It is an easy corollary of this that `maximumᵤ′` and `maximumᵤ` are equal.

\begin{code}

maximumᵤ′-equivalent-to-maximumᵤ : (t : BT )  maximumᵤ t  maximumᵤ′ t
maximumᵤ′-equivalent-to-maximumᵤ []      = refl
maximumᵤ′-equivalent-to-maximumᵤ (n  φ) = 
 where
  IH₁ = maximumᵤ′-equivalent-to-maximumᵤ (φ )
  IH₂ = maximumᵤ′-equivalent-to-maximumᵤ (φ )

   = ap  -  max - (maximumᵤ (φ ))) IH₁
   = ap (max (maximumᵤ′ (φ ))) IH₂
   = maximum-maps-++-to-max-of-maximum
       (sequentialize (φ ))
       (sequentialize (φ )) ⁻¹

   : max (maximumᵤ (φ )) (maximumᵤ (φ ))
       maximum (sequentialize (φ ) ++ sequentialize (φ ))
   =
   max (maximumᵤ (φ )) (maximumᵤ (φ ))                               =⟨     
   max (maximumᵤ′ (φ )) (maximumᵤ (φ ))                              =⟨     
   max (maximumᵤ′ (φ )) (maximumᵤ′ (φ ))                             =⟨ refl 
   max (maximum (sequentialize (φ ))) (maximum (sequentialize (φ ))) =⟨     
   maximum (sequentialize (φ ) ++ sequentialize (φ ))                

   : max n (max (maximumᵤ (φ )) (maximumᵤ (φ )))
       max n (maximum (sequentialize (φ ) ++ sequentialize (φ )))
   = ap (max n) 

\end{code}

We define the following function `to-cantor₀-map`, that extends `to-cantor₀`
from points of the Cantor space to maps `Cantor → ℕ`, and prove some small
lemmas about it.

\begin{code}

to-cantor₀-map : (Cantor  )  Cantor₀  
to-cantor₀-map f = f  to-cantor

to-cantor₀-map-lemma : (f : Cantor  ) (α β : Cantor)
                      let f₀ = to-cantor₀-map f in
                       f₀ (to-cantor₀ α)  f₀ (to-cantor₀ β)
                      f α  f β
to-cantor₀-map-lemma f α β p = f α                          =⟨  
                               f (to-cantor (to-cantor₀ α)) =⟨  
                               f (to-cantor (to-cantor₀ β)) =⟨  
                               f β                          
                                where
                                  = ap f (to-cantor-cancels-to-cantor₀ α ⁻¹ )
                                  = p
                                  = ap f (to-cantor-cancels-to-cantor₀ β)

\end{code}

We now define the alternative notion of uniform continuity, analogous to
`is-continuous₀`.

\begin{code}

is-uniformly-continuous₀ : (Cantor  )  𝓤₀  ̇
is-uniformly-continuous₀ f =
 Σ n   , ((ξ₁@(α₁ , _) ξ₂@(α₂ , _) : Cantor₀)  α₁ =⦅ n  α₂  f₀ ξ₁  f₀ ξ₂)
  where
   f₀ : Cantor₀  
   f₀ = to-cantor₀-map f

modulus-atᵘ₀ : (f : Cantor  )  is-uniformly-continuous₀ f  
modulus-atᵘ₀ f (m , _) = m

\end{code}

The equality-up-to relation `_=⟪_⟫₀_` that we have defined above, implies the
`_=⟦_⟧_` relation that uses binary trees.

\begin{code}

=⟪⟫₀-implies-=⟦⟧ : {X : 𝓤₀  ̇} (α₁ α₂ :   X) (t : BT )
                    α₁ =⟪ sequentialize t ⟫₀ α₂  α₁ =⟦ t  α₂
=⟪⟫₀-implies-=⟦⟧ α₁ α₂ []      p = []
=⟪⟫₀-implies-=⟦⟧ α₁ α₂ (x  φ) p = p x in-head  
 where
  ϑ : α₁ =⟪ sequentialize (φ ) ++ sequentialize (φ ) ⟫₀ α₂
  ϑ = =⟪⟫₀-cons α₁ α₂ x (sequentialize (φ ) ++ sequentialize (φ )) p

  ς₀ : α₁ =⟪ sequentialize (φ ) ⟫₀ α₂
  ς₀ = pr₁ (=⟪⟫-++-lemma₁ α₁ α₂ (sequentialize (φ )) (sequentialize (φ )) ϑ)

  ς₁ : α₁ =⟪ sequentialize (φ ) ⟫₀ α₂
  ς₁ = pr₂ (=⟪⟫-++-lemma₁ α₁ α₂ (sequentialize (φ )) (sequentialize (φ )) ϑ)

   : (j : 𝟚)  α₁ =⟦ φ j  α₂
    = =⟪⟫₀-implies-=⟦⟧ α₁ α₂ (φ ) ς₀
    = =⟪⟫₀-implies-=⟦⟧ α₁ α₂ (φ ) ς₁

\end{code}

Conversely, the `_=⟦_⟧_` relation implies the `_=⟪_⟫₀` relation.

\begin{code}

=⟦⟧-implies-=⟪⟫₀ : (α β : Baire) (t : BT )
                    α =⟦ t  β  α =⟪ sequentialize t ⟫₀ β
=⟦⟧-implies-=⟪⟫₀ _ _ []      _       _ ()
=⟦⟧-implies-=⟪⟫₀ α β (n  φ) (p  _) _ in-head     = p
=⟦⟧-implies-=⟪⟫₀ α β (n  φ) (p  ψ) i (in-tail q) =  i q
 where
  ms = sequentialize (φ )
  ns = sequentialize (φ )

  IH₁ : α =⟪ ms ⟫₀ β
  IH₁ = =⟦⟧-implies-=⟪⟫₀ α β (φ ) (ψ )

  IH₂ : α =⟪ ns ⟫₀ β
  IH₂ = =⟦⟧-implies-=⟪⟫₀ α β (φ ) (ψ )

   : α =⟪ ms ++ ns ⟫₀ β
   = =⟪⟫-++-lemma₂ α β ms ns (IH₁ , IH₂)

\end{code}

\begin{code}

to-bool-congruence : (m n : )
                    (𝒷₁ : is-boolean-valued m)
                    (𝒷₂ : is-boolean-valued n)
                    m  n
                    to-bool m 𝒷₁  to-bool n 𝒷₂
to-bool-congruence zero            zero            (inl refl) (inl refl) _ = refl
to-bool-congruence (succ zero)     (succ zero)     (inr refl) (inr refl) _ = refl
to-bool-congruence (succ (succ _)) (succ (succ _)) (inl ())   (inl _)    _
to-bool-congruence (succ (succ _)) (succ (succ _)) (inl ())   (inr _)    _
to-bool-congruence (succ (succ _)) (succ (succ _)) (inr ())   (inl _)    _
to-bool-congruence (succ (succ _)) (succ (succ _)) (inr ())   (inr _)    _

\end{code}

\begin{code}

to-cantor-=⟦⟧ : {α₁ α₂ : Baire}
                 (ϑ₁ : is-boolean-point α₁) (ϑ₂ : is-boolean-point α₂)
                 (t : BT )
                α₁ =⟦ t  α₂
                to-cantor (α₁ , ϑ₁) =⟦ t  to-cantor (α₂ , ϑ₂)
to-cantor-=⟦⟧ {α₁} {α₂} ϑ₁ ϑ₂ []       _      = []
to-cantor-=⟦⟧ {α₁} {α₂} ϑ₁ ϑ₂ (n  φ) (p  ψ) = β  γ
 where
  β : to-bool (α₁ n) (ϑ₁ n)  to-bool (α₂ n) (ϑ₂ n)
  β = to-bool-congruence (α₁ n) (α₂ n) (ϑ₁ n) (ϑ₂ n) p

  γ : (b : 𝟚)  to-cantor (α₁ , ϑ₁) =⟦ φ b  to-cantor (α₂ , ϑ₂)
  γ  = to-cantor-=⟦⟧ ϑ₁ ϑ₂ (φ ) (ψ )
  γ  = to-cantor-=⟦⟧ ϑ₁ ϑ₂ (φ ) (ψ )

\end{code}

At this point, we are ready to prove one direction of the equivalence we are
interested in: `is-uniformly-continuous` implies `is-uniformly-continuous₀`.

\begin{code}

uni-continuity-implies-uni-continuity₀ : (f : Cantor  )
                                        is-uniformly-continuous  f
                                        is-uniformly-continuous₀ f
uni-continuity-implies-uni-continuity₀ f 𝔠 =
 n , λ (α₁ , ϑ₁) (α₂ , ϑ₂)   α₁ α₂ ϑ₁ ϑ₂
  where
   t : BT 
   t = pr₁ 𝔠

   n : 
   n = succ (maximumᵤ (pr₁ 𝔠))

   f₀ : Cantor₀  
   f₀ = to-cantor₀-map f

    : (α₁ α₂ : Baire) (ϑ₁ : is-boolean-point α₁) (ϑ₂ : is-boolean-point α₂)
      α₁ =⦅ n  α₂  f₀ (α₁ , ϑ₁)  f₀ (α₂ , ϑ₂)
    α₁ α₂ ϑ₁ ϑ₂ (p , q) = pr₂ 𝔠 (to-cantor (α₁ , ϑ₁)) (to-cantor (α₂ , ϑ₂)) η
    where
     ϝ : tl α₁ =⦅ maximumᵤ′ t  (tl α₂)
     ϝ = transport
           -  tl α₁ =⦅ -  tl α₂)
          (maximumᵤ′-equivalent-to-maximumᵤ t)
          q

     χ : α₁ =⦅ succ (maximum (sequentialize t))  α₂
     χ = p , ϝ

     υ : α₁ =⟪ sequentialize t  α₂
     υ = =⦅⦆-implies-=⟪⟫ α₁ α₂ (sequentialize t) χ

     ξ : α₁ =⟪ sequentialize t ⟫₀ α₂
     ξ = =⟪⟫-implies-=⟪⟫₀ α₁ α₂ (sequentialize t) υ

     ζ : α₁ =⟦ t  α₂
     ζ = =⟪⟫₀-implies-=⟦⟧ α₁ α₂ t ξ

     η : to-cantor (α₁ , ϑ₁) =⟦ t  to-cantor (α₂ , ϑ₂)
     η = to-cantor-=⟦⟧ ϑ₁ ϑ₂ t ζ

\end{code}

To prove the converse, we define an analogue of the range function for binary
trees that we call `rangeᵤ`. We also prove some small lemmas about this
function.

\begin{code}

singleton :   BT 
singleton n = n  λ {   [] ;   [] }

pred :   
pred zero     = zero
pred (succ n) = n

rangeᵤ : (n : )  BT 
rangeᵤ zero     = singleton 0
rangeᵤ (succ n) = succ n  λ {   [] ;   rangeᵤ n }

=⟦⟧-up-to-rangeᵤ-m-implies-=⟪⟫-up-to-range-m : {X : 𝓤₀  ̇} (α α′ :   X) (m : )
                                                α =⟦ rangeᵤ m  α′
                                                α =⟪ range m  α′
=⟦⟧-up-to-rangeᵤ-m-implies-=⟪⟫-up-to-range-m α α′ zero (p  _) = p  []
=⟦⟧-up-to-rangeᵤ-m-implies-=⟪⟫-up-to-range-m α α′ (succ m) (p  q) = p  IH
 where
  IH : α =⟪ range m  α′
  IH = =⟦⟧-up-to-rangeᵤ-m-implies-=⟪⟫-up-to-range-m α α′ m (q )

=⟦⟧-up-to-range-m-implies-=⦅⦆-up-to-m : (α β : Baire) (m : )
                                         α =⟦ rangeᵤ m  β
                                         α =⦅ m  β
=⟦⟧-up-to-range-m-implies-=⦅⦆-up-to-m α β m = φ  ψ
 where
  φ = =⟪⟫-range-implies-=⦅⦆ α β m
  ψ = =⟦⟧-up-to-rangeᵤ-m-implies-=⟪⟫-up-to-range-m α β m

\end{code}

We prove one final lemma about the `embedding-C-B` function.

\begin{code}

=⟦⟧-boolean-lemma : (α β : Cantor) (m : )
                    α =⟦ rangeᵤ m  β
                    embedding-C-B α =⟦ rangeᵤ m  embedding-C-B β
=⟦⟧-boolean-lemma α β zero (p  _) = ap embedding-𝟚-ℕ p   {   [] ;   [] })
=⟦⟧-boolean-lemma α β (succ m) (p  φ) =
 ap embedding-𝟚-ℕ p  λ {   [] ;   =⟦⟧-boolean-lemma α β m (φ ) }

\end{code}

We can now easily write down the proof that `is-uniformly-continuous` implies
`is-uniformly-continuous₀`.

\begin{code}

uni-continuity₀-implies-uni-continuity : (f : Cantor  )
                                        is-uniformly-continuous₀ f
                                        is-uniformly-continuous f
uni-continuity₀-implies-uni-continuity f ζ = rangeᵤ m , 
 where
  m : 
  m = modulus-atᵘ₀ f ζ

  f₀ : Cantor₀  
  f₀ = to-cantor₀-map f

   : (α β : Baire) (𝒷₁ : is-boolean-point α) (𝒷₂ : is-boolean-point β)
     α =⟦ rangeᵤ m  β  f₀ (α , 𝒷₁)  f₀ (β , 𝒷₂)
   α β 𝒷₁ 𝒷₂ =
   pr₂ ζ (α , 𝒷₁) (β , 𝒷₂)  =⟦⟧-up-to-range-m-implies-=⦅⦆-up-to-m α β m

   : (α β : Cantor)  α =⟦ rangeᵤ m  β  f α  f β
   α β p = to-cantor₀-map-lemma f α β ( α′ β′ 𝒷₁ 𝒷₂ p′)
   where
    α′ : Baire
    α′ = embedding-C-B α

    𝒷₁ : (n : )  is-boolean-valued (α′ n)
    𝒷₁ = to-baire-gives-boolean-point α

    β′ : Baire
    β′ = embedding-C-B β

    𝒷₂ : (n : )  is-boolean-valued (β′ n)
    𝒷₂ = to-baire-gives-boolean-point β

    p′ : α′ =⟦ rangeᵤ m  β′
    p′ = =⟦⟧-boolean-lemma α β m p

\end{code}

We finish by recording the equivalence of interest as a fact in itself.

\begin{code}

uni-continuity-equivalent-to-uni-continuity : (f : Cantor  )
                                             is-uniformly-continuous₀ f
                                               is-uniformly-continuous f
uni-continuity-equivalent-to-uni-continuity f = ⦅⇒⦆ , ⦅⇐⦆
 where
  ⦅⇒⦆ = uni-continuity₀-implies-uni-continuity f
  ⦅⇐⦆ = uni-continuity-implies-uni-continuity₀ f

\end{code}