Tom de Jong, 27 May 2019.
Refactored December 2021.

* Continuous K and S functions. These will interpret the K and S combinators of
  PCF in ScottModelOfPCF.lagda.
* Continuous ifZero function specific to the lifting of the natural numbers.
  This will then be used to interpret the ifZero combinator of PCF in
  ScottModelOfPCF.lagda.

\begin{code}

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

open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc

module PCF.Combinatory.PCFCombinators
        (pt : propositional-truncations-exist)
        (fe : Fun-Ext)
        (π“₯ : Universe)
       where

open PropositionalTruncation pt

open import UF.Subsingletons

open import DomainTheory.Basics.Dcpo pt fe π“₯
open import DomainTheory.Basics.Exponential pt fe π“₯
open import DomainTheory.Basics.Miscelanea pt fe π“₯
open import DomainTheory.Basics.Pointed pt fe π“₯

\end{code}

We start by defining continuous K and S functions. These will interpret the K
and S combinators of PCF in ScottModelOfPCF.lagda.

This requires a little (straightforward) work, because S must be continuous in
all of its arguments.
Therefore, it is not enough to have S of type
  DCPO[ 𝓓 , 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ] β†’ DCPO[ 𝓓 , 𝓔 ] β†’ DCPO[ 𝓓 , 𝓕 ].
Rather we should have S of type
  DCPO[𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 , (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔) βŸΉα΅ˆαΆœα΅–α΅’ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) ].

\begin{code}

module _ (𝓓 : DCPO {𝓀} {𝓣})
         (𝓔 : DCPO {𝓀'} {𝓣'})
       where

 Kα΅ˆαΆœα΅–α΅’ : DCPO[ 𝓓 , 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓓 ]
 Kα΅ˆαΆœα΅–α΅’ = k , c where
  k : ⟨ 𝓓 ⟩ β†’ DCPO[ 𝓔 , 𝓓 ]
  k x = ((Ξ» _ β†’ x) , constant-functions-are-continuous 𝓔 𝓓)
  c : (I : π“₯ Μ‡ ) (Ξ± : I β†’ ⟨ 𝓓 ⟩) (Ξ΄ : is-Directed 𝓓 Ξ±)
    β†’ is-sup (underlying-order (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓓)) (k (∐ 𝓓 Ξ΄)) (Ξ» (i : I) β†’ k (Ξ± i))
  c I Ξ± Ξ΄ = u , v where
   u : (i : I) (e : ⟨ 𝓔 ⟩) β†’ Ξ± i βŠ‘βŸ¨ 𝓓 ⟩ (∐ 𝓓 Ξ΄)
   u i e = ∐-is-upperbound 𝓓 Ξ΄ i
   v : (f : DCPO[ 𝓔 , 𝓓 ])
     β†’ ((i : I) β†’ k (Ξ± i) βŠ‘βŸ¨ 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓓 ⟩ f)
     β†’ (e : ⟨ 𝓔 ⟩) β†’ ∐ 𝓓 Ξ΄ βŠ‘βŸ¨ 𝓓 ⟩ [ 𝓔 , 𝓓 ]⟨ f ⟩ e
   v (f , _) l e = ∐-is-lowerbound-of-upperbounds 𝓓 Ξ΄ (f e)
                   (Ξ» (i : I) β†’ (l i) e)

 module _ (𝓕 : DCPO {𝓦} {𝓦'}) where

  Sβ‚€α΅ˆαΆœα΅–α΅’ : DCPO[ 𝓓 , 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ]
         β†’ DCPO[ 𝓓 , 𝓔 ]
         β†’ DCPO[ 𝓓 , 𝓕 ]
  Sβ‚€α΅ˆαΆœα΅–α΅’ (f , cf) (g , cg) = (Ξ» x β†’ [ 𝓔 , 𝓕 ]⟨ f x ⟩ (g x)) , c
   where

    c : is-continuous 𝓓 𝓕 (Ξ» x β†’ [ 𝓔 , 𝓕 ]⟨ f x ⟩ (g x))
    c I Ξ± Ξ΄ = u , v
     where
      u : (i : I) β†’ [ 𝓔 , 𝓕 ]⟨ f (Ξ± i) ⟩   (g (Ξ± i)) βŠ‘βŸ¨ 𝓕 ⟩
                    [ 𝓔 , 𝓕 ]⟨ f (∐ 𝓓 Ξ΄) ⟩ (g (∐ 𝓓 Ξ΄))
      u i = [ 𝓔 , 𝓕 ]⟨ f (Ξ± i)   ⟩ (g (Ξ± i))   βŠ‘βŸ¨ 𝓕 ⟩[ β¦…1⦆ ]
            [ 𝓔 , 𝓕 ]⟨ f (∐ 𝓓 Ξ΄) ⟩ (g (Ξ± i))   βŠ‘βŸ¨ 𝓕 ⟩[ β¦…2⦆ ]
            [ 𝓔 , 𝓕 ]⟨ f (∐ 𝓓 Ξ΄) ⟩ (g (∐ 𝓓 Ξ΄)) ∎⟨ 𝓕 ⟩
       where
        β¦…1⦆ = monotone-if-continuous 𝓓 (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) (f , cf) (Ξ± i)
               (∐ 𝓓 Ξ΄) (∐-is-upperbound 𝓓 Ξ΄ i) (g (Ξ± i))
        β¦…2⦆ = monotone-if-continuous 𝓔 𝓕 (f (∐ 𝓓 Ξ΄)) (g (Ξ± i)) (g (∐ 𝓓 Ξ΄))
               (monotone-if-continuous 𝓓 𝓔 (g , cg) (Ξ± i) (∐ 𝓓 Ξ΄)
                 (∐-is-upperbound 𝓓 Ξ΄ i))
      v : (y : ⟨ 𝓕 ⟩)
        β†’ ((i : I) β†’ ([ 𝓔 , 𝓕 ]⟨ f (Ξ± i) ⟩ (g (Ξ± i))) βŠ‘βŸ¨ 𝓕 ⟩ y)
        β†’ ([ 𝓔 , 𝓕 ]⟨ f (∐ 𝓓 Ξ΄) ⟩ (g (∐ 𝓓 Ξ΄))) βŠ‘βŸ¨ 𝓕 ⟩ y
      v y ineqs = Ξ³
       where
        Ξ³ : [ 𝓔 , 𝓕 ]⟨ f (∐ 𝓓 Ξ΄) ⟩ (g (∐ 𝓓 Ξ΄)) βŠ‘βŸ¨ 𝓕 ⟩ y
        Ξ³ = transport (Ξ» - β†’ [ 𝓔 , 𝓕  ]⟨ f (∐ 𝓓 Ξ΄) ⟩ - βŠ‘βŸ¨ 𝓕 ⟩ y)
            eβ‚€ Ξ³β‚€
         where
          eβ‚€ : ∐ 𝓔 (image-is-directed' 𝓓 𝓔 (g , cg) Ξ΄) = g (∐ 𝓓 Ξ΄)
          eβ‚€ = (continuous-∐-= 𝓓 𝓔 (g , cg) Ξ΄) ⁻¹
          Ξ΅β‚€ : is-Directed 𝓔 (g ∘ Ξ±)
          Ξ΅β‚€ = image-is-directed' 𝓓 𝓔 (g , cg) Ξ΄
          Ξ³β‚€ : [ 𝓔 , 𝓕 ]⟨ f (∐ 𝓓 Ξ΄) ⟩ (∐ 𝓔 Ξ΅β‚€) βŠ‘βŸ¨ 𝓕 ⟩ y
          Ξ³β‚€ = transport (Ξ» - β†’ - βŠ‘βŸ¨ 𝓕 ⟩ y) e₁ γ₁
           where
            e₁ : ∐ 𝓕 (image-is-directed' 𝓔 𝓕 (f (∐ 𝓓 Ξ΄)) Ξ΅β‚€) =
                 [ 𝓔 , 𝓕 ]⟨ f (∐ 𝓓 Ξ΄) ⟩ (∐ 𝓔 Ξ΅β‚€)
            e₁ = (continuous-∐-= 𝓔 𝓕 (f (∐ 𝓓 Ξ΄)) Ξ΅β‚€) ⁻¹
            Ρ₁ : is-Directed 𝓕 ([ 𝓔 , 𝓕 ]⟨ f (∐ 𝓓 Ξ΄) ⟩ ∘ (g ∘ Ξ±))
            Ρ₁ = image-is-directed' 𝓔 𝓕 (f (∐ 𝓓 Ξ΄)) Ξ΅β‚€
            γ₁ : (∐ 𝓕 Ρ₁) βŠ‘βŸ¨ 𝓕 ⟩ y
            γ₁ = ∐-is-lowerbound-of-upperbounds 𝓕 Ρ₁ y Ξ³β‚‚
             where
              Ξ³β‚‚ : (i : I) β†’ [ 𝓔 , 𝓕 ]⟨ f (∐ 𝓓 Ξ΄) ⟩ (g (Ξ± i)) βŠ‘βŸ¨ 𝓕 ⟩ y
              Ξ³β‚‚ i = transport (Ξ» - β†’ [ 𝓔 , 𝓕 ]⟨ - ⟩ (g (Ξ± i)) βŠ‘βŸ¨ 𝓕 ⟩ y) eβ‚‚ γ₃
               where
                Ξ΅β‚‚ : is-Directed (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) (f ∘ Ξ±)
                Ξ΅β‚‚ = image-is-directed' 𝓓 (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) (f , cf) Ξ΄
                eβ‚‚ : ∐ (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) {I} {f ∘ Ξ±} Ξ΅β‚‚ = f (∐ 𝓓 Ξ΄)
                eβ‚‚ = (continuous-∐-= 𝓓 (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) (f , cf) Ξ΄) ⁻¹
                γ₃ : [ 𝓔 , 𝓕 ]⟨ ∐ (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) {I} {f ∘ Ξ±} Ξ΅β‚‚ ⟩ (g (Ξ± i)) βŠ‘βŸ¨ 𝓕 ⟩ y
                γ₃ = ∐-is-lowerbound-of-upperbounds 𝓕
                      (pointwise-family-is-directed 𝓔 𝓕 (f ∘ Ξ±) Ξ΅β‚‚ (g (Ξ± i)))
                      y h
                 where
                  h : (j : I) β†’ [ 𝓔 , 𝓕 ]⟨ f (Ξ± j) ⟩ (g (Ξ± i)) βŠ‘βŸ¨ 𝓕 ⟩ y
                  h j = βˆ₯βˆ₯-rec (prop-valuedness 𝓕
                         ([ 𝓔 , 𝓕 ]⟨ f (Ξ± j) ⟩ (g (Ξ± i))) y)
                         r (semidirected-if-Directed 𝓓 Ξ± Ξ΄ i j)
                   where
                    r : (Ξ£ k κž‰ I , Ξ± i βŠ‘βŸ¨ 𝓓 ⟩ Ξ± k Γ— Ξ± j βŠ‘βŸ¨ 𝓓 ⟩ Ξ± k)
                      β†’ [ 𝓔 , 𝓕 ]⟨ f (Ξ± j) ⟩ (g (Ξ± i)) βŠ‘βŸ¨ 𝓕 ⟩ y
                    r (k , l , m ) = [ 𝓔 , 𝓕 ]⟨ f (Ξ± j) ⟩ (g (Ξ± i)) βŠ‘βŸ¨ 𝓕 ⟩[ β¦…1⦆ ]
                                     [ 𝓔 , 𝓕 ]⟨ f (Ξ± k) ⟩ (g (Ξ± i)) βŠ‘βŸ¨ 𝓕 ⟩[ β¦…2⦆ ]
                                     [ 𝓔 , 𝓕 ]⟨ f (Ξ± k) ⟩ (g (Ξ± k)) βŠ‘βŸ¨ 𝓕 ⟩[ β¦…3⦆ ]
                                     y                              ∎⟨ 𝓕 ⟩
                     where
                      β¦…1⦆ = monotone-if-continuous 𝓓 (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) (f , cf)
                             (Ξ± j) (Ξ± k) m (g (Ξ± i))
                      β¦…2⦆ = monotone-if-continuous 𝓔 𝓕 (f (Ξ± k))
                             (g (Ξ± i)) (g (Ξ± k))
                             (monotone-if-continuous 𝓓 𝓔 (g , cg) (Ξ± i) (Ξ± k) l)
                      β¦…3⦆ = ineqs k

  Sβ‚α΅ˆαΆœα΅–α΅’ : DCPO[ 𝓓 , 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ]
         β†’ DCPO[ 𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔 , 𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ]
  Sβ‚α΅ˆαΆœα΅–α΅’ (f , cf) = h , c
   where
    h : DCPO[ 𝓓 , 𝓔 ] β†’ DCPO[ 𝓓 , 𝓕 ]
    h = (Sβ‚€α΅ˆαΆœα΅–α΅’ (f , cf))
    c : is-continuous (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔) (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) h
    c I Ξ± Ξ΄ = u , v
     where
      u : (i : I) (d : ⟨ 𝓓 ⟩)
        β†’ [ 𝓓 , 𝓕 ]⟨ h (Ξ± i) ⟩ d βŠ‘βŸ¨ 𝓕 ⟩
          [ 𝓓 , 𝓕 ]⟨ h (∐ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔) {I} {Ξ±} Ξ΄ )⟩ d
      u i d = monotone-if-continuous 𝓔 𝓕 (f d)
              ([ 𝓓 , 𝓔 ]⟨ Ξ± i ⟩ d)
              ([ 𝓓 , 𝓔 ]⟨ ∐ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔) {I} {Ξ±} Ξ΄ ⟩ d)
              (∐-is-upperbound 𝓔 (pointwise-family-is-directed 𝓓 𝓔 Ξ± Ξ΄ d) i)
      v : (g : DCPO[ 𝓓 , 𝓕 ])
        β†’ ((i : I) β†’ h (Ξ± i) βŠ‘βŸ¨ 𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ⟩ g)
        β†’ (d : ⟨ 𝓓 ⟩)
        β†’ [ 𝓓 , 𝓕 ]⟨ h (∐ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔) {I} {Ξ±} Ξ΄) ⟩ d βŠ‘βŸ¨ 𝓕 ⟩ [ 𝓓 , 𝓕 ]⟨ g ⟩ d
      v g l d = transport (Ξ» - β†’ - βŠ‘βŸ¨ 𝓕 ⟩ [ 𝓓 , 𝓕 ]⟨ g ⟩ d) e s
       where
        Ξ΅ : is-Directed 𝓔 (pointwise-family 𝓓 𝓔 Ξ± d)
        Ξ΅ = pointwise-family-is-directed 𝓓 𝓔 Ξ± Ξ΄ d
        e : ∐ 𝓕 (image-is-directed' 𝓔 𝓕 (f d) Ξ΅)
            = [ 𝓓 , 𝓕 ]⟨ h (∐ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔) {I} {Ξ±} Ξ΄) ⟩ d
        e = (continuous-∐-= 𝓔 𝓕 (f d) Ξ΅) ⁻¹
        Ο† : is-Directed 𝓕
            ([ 𝓔 , 𝓕 ]⟨ f d ⟩ ∘ (pointwise-family 𝓓 𝓔 Ξ± d))
        Ο† = image-is-directed' 𝓔 𝓕 (f d) Ξ΅
        s : ∐ 𝓕 Ο† βŠ‘βŸ¨ 𝓕 ⟩ [ 𝓓 , 𝓕 ]⟨ g ⟩ d
        s = ∐-is-lowerbound-of-upperbounds 𝓕 Ο† ([ 𝓓 , 𝓕 ]⟨ g ⟩ d)
            (Ξ» (i : I) β†’ l i d)

  Sα΅ˆαΆœα΅–α΅’ : DCPO[ 𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 , (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔) βŸΉα΅ˆαΆœα΅–α΅’ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) ]
  Sα΅ˆαΆœα΅–α΅’ = Sβ‚α΅ˆαΆœα΅–α΅’ , c
   where
    c : is-continuous (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕)
                      ((𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔) βŸΉα΅ˆαΆœα΅–α΅’ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕))
                      Sβ‚α΅ˆαΆœα΅–α΅’
    c I Ξ± Ξ΄ = u , v
     where
      u : (i : I) ((g , _) : DCPO[ 𝓓 , 𝓔 ]) (d : ⟨ 𝓓 ⟩)
        β†’ [ 𝓔 , 𝓕 ]⟨ [ 𝓓 , 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ]⟨ Ξ± i ⟩ d ⟩ (g d) βŠ‘βŸ¨ 𝓕 ⟩
          [ 𝓔 , 𝓕 ]⟨ [ 𝓓 , 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ]⟨ ∐ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕)) {I} {Ξ±} Ξ΄ ⟩ d ⟩
           (g d)
      u i (g , _) d = ∐-is-upperbound 𝓕
                       (pointwise-family-is-directed 𝓔 𝓕 Ξ² Ξ΅ (g d)) i
       where
        Ξ² : I β†’ DCPO[ 𝓔 , 𝓕 ]
        Ξ² = pointwise-family 𝓓 (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) Ξ± d
        Ξ΅ : is-Directed (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) Ξ²
        Ξ΅ = pointwise-family-is-directed 𝓓 (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) Ξ± Ξ΄ d
      v : (f : DCPO[ 𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔 , 𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ])
        β†’ ((i : I) β†’ Sβ‚α΅ˆαΆœα΅–α΅’ (Ξ± i) βŠ‘βŸ¨ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔) βŸΉα΅ˆαΆœα΅–α΅’ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) ⟩ f)
        β†’ (g : DCPO[ 𝓓 , 𝓔 ]) (d : ⟨ 𝓓 ⟩)
        β†’ [ 𝓔 , 𝓕 ]⟨ [ 𝓓 , 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ]⟨ ∐ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’ (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕)) {I} {Ξ±} Ξ΄ ⟩ d ⟩
           ([ 𝓓 , 𝓔 ]⟨ g ⟩ d)
        βŠ‘βŸ¨ 𝓕 ⟩
          [ 𝓓 , 𝓕 ]⟨ [ 𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔 , 𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ]⟨ f ⟩ g ⟩ d
      v (f , _) l g d = ∐-is-lowerbound-of-upperbounds 𝓕 Ξ΅ ([ 𝓓 , 𝓕 ]⟨ f g ⟩ d)
                         (Ξ» (i : I) β†’ l i g d)
       where
        Ξ΅ : is-Directed 𝓕
             (Ξ» i β†’ [ 𝓓 , 𝓕 ]⟨ [ 𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓔 , 𝓓 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ]⟨ Sβ‚α΅ˆαΆœα΅–α΅’ (Ξ± i) ⟩ g ⟩ d)
        Ξ΅ = pointwise-family-is-directed 𝓔 𝓕 Ξ² Ο† ([ 𝓓 , 𝓔 ]⟨ g ⟩ d)
         where
          Ξ² : I β†’ DCPO[ 𝓔 , 𝓕 ]
          Ξ² i = [ 𝓓 , 𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕 ]⟨ Ξ± i ⟩ d
          Ο† : is-Directed (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) Ξ²
          Ο† = pointwise-family-is-directed 𝓓 (𝓔 βŸΉα΅ˆαΆœα΅–α΅’ 𝓕) Ξ± Ξ΄ d

module _ (𝓓 : DCPOβŠ₯ {𝓀} {𝓣})
         (𝓔 : DCPOβŠ₯ {𝓀'} {𝓣'})
       where

 Kα΅ˆαΆœα΅–α΅’βŠ₯ : DCPOβŠ₯[ 𝓓 , 𝓔 βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ 𝓓 ]
 Kα΅ˆαΆœα΅–α΅’βŠ₯ = Kα΅ˆαΆœα΅–α΅’ (𝓓 ⁻) (𝓔 ⁻)

 Sα΅ˆαΆœα΅–α΅’βŠ₯ : (𝓕 : DCPOβŠ₯ {𝓦} {𝓦'})
        β†’ DCPOβŠ₯[ 𝓓 βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ 𝓔 βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ 𝓕 , (𝓓 βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ 𝓔) βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ (𝓓 βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ 𝓕) ]
 Sα΅ˆαΆœα΅–α΅’βŠ₯ 𝓕 = Sα΅ˆαΆœα΅–α΅’ (𝓓 ⁻) (𝓔 ⁻) (𝓕 ⁻)

\end{code}

Finally, we construct the continuous ifZero function, specific to the lifting
of β„•. This will then be used to interpret the ifZero combinator of PCF in
ScottModelOfPCF.lagda.

\begin{code}

module IfZeroDenotationalSemantics
        (pe : propext π“₯)
       where

 open import Lifting.Construction π“₯
 open import Lifting.Miscelanea π“₯
 open import Lifting.Miscelanea-PropExt-FunExt π“₯ pe fe
 open import Lifting.Monad π“₯

 open import DomainTheory.Lifting.LiftingSet pt fe π“₯ pe
 open import UF.DiscreteAndSeparated
 open import Naturals.Properties

 π“›α΅ˆβ„• : DCPOβŠ₯ {π“₯ ⁺} {π“₯ ⁺}
 π“›α΅ˆβ„• = 𝓛-DCPOβŠ₯ β„•-is-set

 β¦…ifZero⦆₀ : 𝓛 β„• β†’ 𝓛 β„• β†’ β„• β†’ 𝓛 β„•
 β¦…ifZero⦆₀ a b zero     = a
 β¦…ifZero⦆₀ a b (succ n) = b

 β¦…ifZero⦆₁ : 𝓛 β„• β†’ 𝓛 β„• β†’ DCPOβŠ₯[ π“›α΅ˆβ„• , π“›α΅ˆβ„• ]
 β¦…ifZero⦆₁ a b =
  (β¦…ifZero⦆₀ a b) β™― , β™―-is-continuous β„•-is-set β„•-is-set (β¦…ifZero⦆₀ a b)

 β¦…ifZero⦆₂ : 𝓛 β„• β†’ DCPOβŠ₯[ π“›α΅ˆβ„• , π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„• ]
 β¦…ifZero⦆₂ a = β¦…ifZero⦆₁ a , c
  where
   c : is-continuous (π“›α΅ˆβ„• ⁻) ((π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„•) ⁻) (β¦…ifZero⦆₁ a)
   c I Ξ± Ξ΄ = u , v
    where
     u : (i : I) (l : 𝓛 β„•) (d : is-defined (((β¦…ifZero⦆₀ a (Ξ± i)) β™―) l))
       β†’ ((β¦…ifZero⦆₀ a (Ξ± i)) β™―) l = ((β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) β™―) l
     u i l d = ((β¦…ifZero⦆₀ a (Ξ± i)) β™―) l             =⟨ q₁ ⟩
               β¦…ifZero⦆₀ a (Ξ± i) (value l e)         =⟨ qβ‚‚ ⟩
               β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e) =⟨ q₃ ⟩
               ((β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) β™―) l     ∎
      where
       e : is-defined l
       e = β™―-is-defined (β¦…ifZero⦆₀ a (Ξ± i)) l d
       q₁ = β™―-on-total-element (β¦…ifZero⦆₀ a (Ξ± i)) e
       q₃ = (β™―-on-total-element (β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) {l} e) ⁻¹
       qβ‚‚ = β„•-cases {π“₯ ⁺} {Ξ» (n : β„•) β†’ β¦…ifZero⦆₀ a (Ξ± i) n
                                     = β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) n} (value l e) pβ‚€ pβ‚›
        where
         pβ‚€ : value l e = zero
            β†’ β¦…ifZero⦆₀ a (Ξ± i) (value l e) = β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e)
         pβ‚€ q = β¦…ifZero⦆₀ a (Ξ± i) (value l e)         =⟨ ap (β¦…ifZero⦆₀ a (Ξ± i)) q  ⟩
                β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) zero        =⟨ ap (β¦…ifZero⦆₀ a _) (q ⁻¹) ⟩
                β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e) ∎
         pβ‚› : (n : β„•) β†’ value l e = succ n
            β†’ β¦…ifZero⦆₀ a (Ξ± i) (value l e) = β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e)
         pβ‚› n q = β¦…ifZero⦆₀ a (Ξ± i) (value l e)         =⟨ β¦…1⦆  ⟩
                  β¦…ifZero⦆₀ a (Ξ± i) (succ n)            =⟨ refl ⟩
                  Ξ± i                                   =⟨ β¦…2⦆  ⟩
                  ∐ (π“›α΅ˆβ„• ⁻) Ξ΄                           =⟨ refl ⟩
                  β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (succ n)    =⟨ β¦…3⦆  ⟩
                  β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e) ∎
          where
           β¦…1⦆ = ap (β¦…ifZero⦆₀ a (Ξ± i)) q
           β¦…3⦆ = ap (β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) (q ⁻¹)
           β¦…2⦆ = family-defined-somewhere-sup-= β„•-is-set Ξ΄ i eα΅’
            where
             eα΅’ : is-defined (Ξ± i)
             eα΅’ = =-to-is-defined (ap (β¦…ifZero⦆₀ a (Ξ± i)) q)
                   (=-to-is-defined
                     (β™―-on-total-element (β¦…ifZero⦆₀ a (Ξ± i)) {l} e) d)

     v : (f : DCPOβŠ₯[ π“›α΅ˆβ„• , π“›α΅ˆβ„• ])
       β†’ ((i : I) β†’ β¦…ifZero⦆₁ a (Ξ± i) βŠ‘βŸͺ π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„• ⟫ f)
       β†’ (l : 𝓛 β„•) (d : is-defined (((β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) β™―) l))
       β†’ ((β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) β™―) l = [ π“›α΅ˆβ„• ⁻ , π“›α΅ˆβ„• ⁻ ]⟨ f ⟩ l
     v (f , _) ineqs l d = ((β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) β™―) l     =⟨ q₁ ⟩
                           β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e) =⟨ qβ‚‚ ⟩
                           f l                                  ∎
      where
       e : is-defined l
       e = β™―-is-defined (β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) l d
       q₁ = β™―-on-total-element (β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) {l} e
       qβ‚‚ = β„•-cases {π“₯ ⁺} {Ξ» (n : β„•) β†’ β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) n = f l}
             (value l e) pβ‚€ pβ‚›
        where
         pβ‚€ : value l e = zero
            β†’ β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e) = f l
         pβ‚€ q = β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e) =⟨ β¦…1⦆  ⟩
                β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) zero        =⟨ refl ⟩
                a                                     =⟨ β¦…2⦆  ⟩
                f l                                   ∎
          where
           β¦…1⦆ = ap (β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) q
           β¦…2⦆ = βˆ₯βˆ₯-rec (lifting-of-set-is-set β„•-is-set)
                  h (inhabited-if-Directed (π“›α΅ˆβ„• ⁻) Ξ± Ξ΄)
            where
             h : (i : I) β†’ a = f l
             h i = a                             =⟨ β¦…1'⦆ ⟩
                   β¦…ifZero⦆₀ a (Ξ± i) (value l e) =⟨ β¦…2'⦆ ⟩
                   ((β¦…ifZero⦆₀ a (Ξ± i)) β™―) l     =⟨ β¦…3'⦆ ⟩
                   f l                           ∎
              where
               β¦…1'⦆ = ap (β¦…ifZero⦆₀ a (Ξ± i)) (q ⁻¹)
               β¦…2'⦆ = (β™―-on-total-element (β¦…ifZero⦆₀ a (Ξ± i)) e) ⁻¹
               β¦…3'⦆ = ineqs i l (=-to-is-defined r d)
                where
                 r : ((β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) β™―) l
                   = ((β¦…ifZero⦆₀ a (Ξ± i)) β™―) l
                 r = q₁ βˆ™ β¦…1⦆ βˆ™ β¦…1'⦆ βˆ™ β¦…2'⦆

         pβ‚› : (m : β„•) β†’ value l e = succ m
            β†’ β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e) = f l
         pβ‚› m q = βˆ₯βˆ₯-rec (lifting-of-set-is-set β„•-is-set) h e'
          where
           β¦…1⦆ : (β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) β™―) l
               = β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e)
           β¦…1⦆ = β™―-on-total-element (β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) {l} e
           β¦…2⦆ : β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e) = ∐ (π“›α΅ˆβ„• ⁻) Ξ΄
           β¦…2⦆ = ap (β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) q
           e' : is-defined (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)
           e' = =-to-is-defined (β¦…1⦆ βˆ™ β¦…2⦆) d
           h : (Ξ£ i κž‰ I , is-defined (Ξ± i))
             β†’ β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e) = f l
           h (i , dα΅’) = β¦…ifZero⦆₀ a (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) (value l e) =⟨ β¦…1'⦆ ⟩
                        ∐ (π“›α΅ˆβ„• ⁻) Ξ΄                           =⟨ β¦…2'⦆ ⟩
                        Ξ± i                                   =⟨ β¦…3'⦆ ⟩
                        ((β¦…ifZero⦆₀ a (Ξ± i)) β™―) l             =⟨ β¦…4'⦆ ⟩
                        f l                                   ∎
            where
             β¦…1'⦆ = β¦…2⦆
             β¦…2'⦆ = (family-defined-somewhere-sup-= β„•-is-set Ξ΄ i dα΅’) ⁻¹
             β¦…3'⦆ = (β™―-on-total-element (β¦…ifZero⦆₀ a (Ξ± i)) e
                     βˆ™ ap (β¦…ifZero⦆₀ a (Ξ± i)) q) ⁻¹
             β¦…4'⦆ = ineqs i l (=-to-is-defined β¦…3'⦆ dα΅’)

\end{code}

We can exploit the fact that ifZero a b 0 = ifZero b a 1, to reduce the proof
that ifZero is continuous in its first argument to continuity in its second
argument. The "flip"-code below prepares for this.

\begin{code}

 β„•-flip : β„• β†’ β„•
 β„•-flip zero     = succ zero
 β„•-flip (succ n) = zero

 ifZero-flip-equation : (a b : 𝓛 β„•) (n : β„•)
                      β†’ β¦…ifZero⦆₀ a b n = β¦…ifZero⦆₀ b a (β„•-flip n)
 ifZero-flip-equation a b zero     = refl
 ifZero-flip-equation a b (succ n) = refl

 𝓛ℕ-flip : 𝓛 β„• β†’ 𝓛 β„•
 𝓛ℕ-flip (P , Ο• , ρ) = (P , β„•-flip ∘ Ο• , ρ)

 ifZeroβ™―-flip-equation : (a b : 𝓛 β„•) (l : 𝓛 β„•)
                      β†’ ((β¦…ifZero⦆₀ a b) β™―) l = ((β¦…ifZero⦆₀ b a) β™―) (𝓛ℕ-flip l)
 ifZeroβ™―-flip-equation a b l = βŠ‘'-is-antisymmetric u v
  where
   l' : 𝓛 β„•
   l' = 𝓛ℕ-flip l
   lemma : (p : is-defined l)
         β†’ (β¦…ifZero⦆₀ a b β™―) l = (β¦…ifZero⦆₀ b a β™―) l'
   lemma p = (β¦…ifZero⦆₀ a b β™―) l        =⟨ β¦…1⦆ ⟩
             β¦…ifZero⦆₀ a b (value l  p) =⟨ β¦…2⦆ ⟩
             β¦…ifZero⦆₀ b a (value l' p) =⟨ β¦…3⦆ ⟩
             (β¦…ifZero⦆₀ b a β™―) l'       ∎
    where
     β¦…1⦆ = β™―-on-total-element (β¦…ifZero⦆₀ a b) p
     β¦…2⦆ = ifZero-flip-equation a b (value l p)
     β¦…3⦆ = (β™―-on-total-element (β¦…ifZero⦆₀ b a) p) ⁻¹
   u : (β¦…ifZero⦆₀ a b β™―) l βŠ‘' (β¦…ifZero⦆₀ b a β™―) l'
   u q = lemma (β™―-is-defined (β¦…ifZero⦆₀ a b) l q)
   v : (β¦…ifZero⦆₀ b a β™―) l' βŠ‘' (β¦…ifZero⦆₀ a b β™―) l
   v q = (lemma (β™―-is-defined (β¦…ifZero⦆₀ b a) l' q)) ⁻¹

\end{code}

We are now ready to give the final continuity proof.

\begin{code}

 β¦…ifZero⦆ : DCPOβŠ₯[ π“›α΅ˆβ„• , π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„•  ]
 β¦…ifZero⦆ = β¦…ifZero⦆₂ , c
  where
   c : is-continuous (π“›α΅ˆβ„• ⁻) ((π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„•) ⁻) β¦…ifZero⦆₂
   c I Ξ± Ξ΄ = u , v
    where
     u : (i : I) (b : 𝓛 β„•) (l : 𝓛 β„•)
       β†’ ((β¦…ifZero⦆₀ (Ξ± i) b) β™―) l βŠ‘βŸͺ π“›α΅ˆβ„• ⟫ ((β¦…ifZero⦆₀ (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) b) β™―) l
     u i b l = ((β¦…ifZero⦆₀ (Ξ± i) b) β™―) l           βŠ‘βŸͺ π“›α΅ˆβ„• ⟫[ β¦…1⦆ ]
               ((β¦…ifZero⦆₀ b (Ξ± i)) β™―) l'          βŠ‘βŸͺ π“›α΅ˆβ„• ⟫[ β¦…2⦆ ]
               ((β¦…ifZero⦆₀ b (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) β™―) l'  βŠ‘βŸͺ π“›α΅ˆβ„• ⟫[ β¦…3⦆ ]
               ((β¦…ifZero⦆₀ (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) b) β™―) l   ∎βŸͺ π“›α΅ˆβ„• ⟫
      where
       l' : 𝓛 β„•
       l' = 𝓛ℕ-flip l
       β¦…1⦆ = =-to-βŠ‘ (π“›α΅ˆβ„• ⁻) (ifZeroβ™―-flip-equation (Ξ± i) b l)
       β¦…2⦆ = (monotone-if-continuous (π“›α΅ˆβ„• ⁻) ((π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„•) ⁻)
              (β¦…ifZero⦆₂ b) (Ξ± i) (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)
              (∐-is-upperbound (π“›α΅ˆβ„• ⁻) Ξ΄ i))
             l'
       β¦…3⦆ = =-to-βŠ’ (π“›α΅ˆβ„• ⁻) (ifZeroβ™―-flip-equation (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) b l)

     v : ((f , _) : DCPOβŠ₯[ π“›α΅ˆβ„• , π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„• ])
       β†’ ((i : I) (b : 𝓛 β„•) β†’ β¦…ifZero⦆₁ (Ξ± i) b βŠ‘βŸͺ π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„• ⟫ f b)
       β†’ (b : 𝓛 β„•) (l : 𝓛 β„•)
       β†’ ((β¦…ifZero⦆₀ (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) b) β™―) l βŠ‘βŸͺ π“›α΅ˆβ„• ⟫ [ π“›α΅ˆβ„• ⁻ , π“›α΅ˆβ„• ⁻ ]⟨ f b ⟩ l
     v (f , _) ineqs b l =
      ((β¦…ifZero⦆₀ (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) b) β™―) l                 βŠ‘βŸͺ π“›α΅ˆβ„• ⟫[ β¦…1⦆ ]
      ((β¦…ifZero⦆₀ b (∐ (π“›α΅ˆβ„• ⁻) Ξ΄)) β™―) l'                βŠ‘βŸͺ π“›α΅ˆβ„• ⟫[ β¦…2⦆ ]
      [ π“›α΅ˆβ„• ⁻ , π“›α΅ˆβ„• ⁻ ]⟨ β¦…ifZero⦆₁ b (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) ⟩ l' βŠ‘βŸͺ π“›α΅ˆβ„• ⟫[ β¦…3⦆ ]
      ∐ (π“›α΅ˆβ„• ⁻) {I} {Ξ±'} Ξ΄'                             βŠ‘βŸͺ π“›α΅ˆβ„• ⟫[ β¦…4⦆ ]
      ∐ (π“›α΅ˆβ„• ⁻) {I} {Ξ±''} Ξ΄''                           βŠ‘βŸͺ π“›α΅ˆβ„• ⟫[ β¦…5⦆ ]
      [ π“›α΅ˆβ„• ⁻ , π“›α΅ˆβ„• ⁻ ]⟨ f b ⟩ l                        ∎βŸͺ π“›α΅ˆβ„• ⟫
       where
        l' : 𝓛 β„•
        l' = 𝓛ℕ-flip l
        Ξ±' : (i : I) β†’ βŸͺ π“›α΅ˆβ„• ⟫
        Ξ±' i = ((β¦…ifZero⦆₀ b (Ξ± i)) β™―) l'
        Ξ΄' : is-Directed (π“›α΅ˆβ„• ⁻) Ξ±'
        Ξ΄' = pointwise-family-is-directed (π“›α΅ˆβ„• ⁻) (π“›α΅ˆβ„• ⁻) (β¦…ifZero⦆₁ b ∘ Ξ±) Ξ΅ l'
         where
          Ξ΅ : is-Directed ((π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„•) ⁻) (β¦…ifZero⦆₁ b ∘ Ξ±)
          Ξ΅ = image-is-directed' (π“›α΅ˆβ„• ⁻) ((π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„•) ⁻) (β¦…ifZero⦆₂ b) Ξ΄
        Ξ±'' : (i : I) β†’ βŸͺ π“›α΅ˆβ„• ⟫
        Ξ±'' i = ((β¦…ifZero⦆₀ (Ξ± i) b) β™―) l
        e : α' = α''
        e = dfunext fe (Ξ» i β†’ (ifZeroβ™―-flip-equation (Ξ± i) b l) ⁻¹)
        Ξ΄'' : is-Directed (π“›α΅ˆβ„• ⁻) Ξ±''
        Ξ΄'' = transport (is-Directed (π“›α΅ˆβ„• ⁻)) e Ξ΄'

        β¦…1⦆ = =-to-βŠ‘ (π“›α΅ˆβ„• ⁻) (ifZeroβ™―-flip-equation (∐ (π“›α΅ˆβ„• ⁻) Ξ΄) b l)
        β¦…2⦆ = reflexivity (π“›α΅ˆβ„• ⁻) _
        β¦…3⦆ = =-to-βŠ‘ (π“›α΅ˆβ„• ⁻)
              (ap (Ξ» - β†’ [ π“›α΅ˆβ„• ⁻ , π“›α΅ˆβ„• ⁻ ]⟨ - ⟩ l')
                  (continuous-∐-= (π“›α΅ˆβ„• ⁻) ((π“›α΅ˆβ„• βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ π“›α΅ˆβ„•) ⁻)
                    (β¦…ifZero⦆₂ b) {I} {Ξ±} Ξ΄))
        β¦…4⦆ = =-to-βŠ‘ (π“›α΅ˆβ„• ⁻) (∐-family-= (π“›α΅ˆβ„• ⁻) e Ξ΄')
        β¦…5⦆ = ∐-is-lowerbound-of-upperbounds (π“›α΅ˆβ„• ⁻) Ξ΄''
              ([ π“›α΅ˆβ„• ⁻ , π“›α΅ˆβ„• ⁻ ]⟨ f b ⟩ l) (Ξ» i β†’ ineqs i b l)

\end{code}