The object language over the model

The readers were written about the hierarchy and the bridge carries them into the model. This chapter takes the bridge across, once, and states what a quoted reader means on the far side.

There is one wrinkle and it is small. A reader's meaning was stated in terms of the value of a variable in a hierarchy environment; on the far side the environment holds elements of the model, and the hierarchy environment is the one obtained by taking underlying sets. Looking up in the projected environment is projecting the lookup, which is a two-line induction, and after it the quoted reader says exactly what the original said about the underlying sets.

The first reader to cross is the one everything else is built from: the ordered pair. Nothing above it needs a new argument, because the bridge is generic and the readers' own characterizations were proved once already.

{-# OPTIONS --cubical --safe --guardedness #-}

open import Base.Prelude
open import Base.Truth

module L.Coding.Model { : Level} where

open import FOL.ZFStructure using ( module hPropStructure )
open import FOL.Syntax
  using ( Term; Formula; var; con; _∈̇_; _≐_; _∧̇_; _∨̇_; _⇒̇_; ¬̇_; ⊤̇; ⊥̇
        ; ∀̇_; ∀̇∈; ∃̇_; ∃̇∈ )
open import FOL.Manipulation.Relabelling using ( mapTm; mapFo )
import FOL.Absoluteness
import FOL.Coding
open import V.Hierarchy {} using ( 𝒮ᵥ )
open import V.Coding {} using ( pr; pr-inj; #-inj′; module VCode )
open import V.Model {} using ( pair-singleton )
open import L.Constructible {} using ( 𝒮ʟ; isL; isL-trans )
open import FOL.Manipulation.Bounding using ( BoundedFo )
open import L.Absoluteness {} using ( InL; liftFo; transferFo )
open import L.Coding.Base {}
  using ( prAt; Δ₀-prAt; prAt-adequate; sglConAt; pairConAt; tagAt )
open import L.Coding.Environment {}
  using ( sucAt; Δ₀-sucAt; sucAt-adequate; consAt; Δ₀-consAt; consAt-adequate
        ; env; cons; shiftPairAt )
open import L.Axioms.Numerals {}
  using ( numeralL; numeralL-fst; pairʟ; pairʟ-fst; sucʟ; sucʟ-fst )

open import Cubical.Data.Sigma using ( Σ≡Prop )
open import Cubical.Foundations.Prelude using ( subst2 )
open import Cubical.Data.Vec using ( map )
open import Cubical.Data.Nat using ( _+_ )
open import Cubical.Data.FinData using ( toℕ )
open import Cubical.Functions.Logic using ( ⇔toPath; ∃[∶]-syntax )
open import Cubical.Data.Sum using ( _⊎_; inl; inr )
import Cubical.HITs.PropositionalTruncation as PT
open PT using ( ∣_∣₁; ∥_∥₁; squash₁ )
open import Cubical.HITs.CumulativeHierarchy.Base using ( V; setIsSet; _∈_ )
open import Cubical.HITs.CumulativeHierarchy.Constructions using ( ⁅_,_⁆ )
open import Cubical.HITs.CumulativeHierarchy.Constructions using ( module InfinitySet )
open InfinitySet using ( #_; sucV )

open TruthAlgebra (hPropAlgebra (ℓ-suc ))
open hPropStructure 𝒮ʟ using ( S )

module AbsL = FOL.Absoluteness.Single 𝒮ᵥ isL isL-trans
open AbsL using ( _^_ ) renaming ( _⊨ᵐ_ to _⊨_ )

Looking up in a projected environment

Two lines, and the only bookkeeping the crossing costs.

lookup-fst :  {n} (i : Fin n) (γ : S ^ n)
            lookup i (map fst γ)  fst (lookup i γ)
lookup-fst zero    (x  γ) = refl
lookup-fst (suc i) (x  γ) = lookup-fst i γ

The ordered pair

The quoted reader is the original lifted along the bridge, and the lift asks for nothing: the reader names no constants, so there is nothing to be constructible and the admissibility witness is empty.

Its meaning is three steps. The bridge equates satisfaction in the model with satisfaction in the hierarchy at the projected environment; the reader's own characterization says what that is; and the lookups are projected. What comes out is the statement a consumer wants: the value of one variable is the Kuratowski pair of the values of the other two, as sets.

private
  PairIs : V   V   Ω
  PairIs a p = (a  p) , setIsSet a p

prAtL :  {n}  Fin n  Fin n  Fin n  Formula S n
prAtL q u v = liftFo (prAt q u v) _

prAtL-adequate :  {n} (q u v : Fin n) (γ : S ^ n)
   (γ  prAtL q u v)
   PairIs (fst (lookup q γ)) (pr (fst (lookup u γ)) (fst (lookup v γ)))
prAtL-adequate q u v γ =
    transferFo (prAt q u v) _ (Δ₀-prAt q u v) γ
   prAt-adequate q u v (map fst γ)
   cong₂ PairIs (lookup-fst q γ)
      (cong₂ pr (lookup-fst u γ) (lookup-fst v γ))

Application

A function in the object language is a set of ordered pairs, so the one thing every use of one asks is whether a given pair belongs to it. That is a bounded existential over the function, with the pair reader inside, and its meaning is membership of the Kuratowski pair.

The backward direction is where the model earns its keep, and it is worth noticing. To satisfy the existential one must produce an element of the model whose underlying set is the pair; the hypothesis only supplies a set. It is constructible because it belongs to something constructible, and the class is transitive. That is the whole argument, and the same step will recur wherever a witness has to be produced inside the model rather than merely in the hierarchy.

appAt :  {n}  Fin n  Fin n  Fin n  Formula S n
appAt f x y = ∃̇∈ (var f) (prAtL zero (suc x) (suc y))

appAt-adequate :  {n} (f x y : Fin n) (γ : S ^ n)
   (γ  appAt f x y)
   (pr (fst (lookup x γ)) (fst (lookup y γ))  fst (lookup f γ))
appAt-adequate f x y γ = ⇔toPath fwd bwd
  where
  a = fst (lookup x γ)
  b = fst (lookup y γ)
  F = lookup f γ

  read : (z : S)   (z  γ)  prAtL zero (suc x) (suc y)   fst z  pr a b
  read z h = subst ⟨_⟩ (prAtL-adequate zero (suc x) (suc y) (z  γ)) h

  fwd :  γ  appAt f x y    pr a b  fst F 
  fwd = PT.rec (snd (pr a b  fst F))
     { (z , (z∈F , h))  subst  w   w  fst F ) (read z h) z∈F })

  bwd :  pr a b  fst F    γ  appAt f x y 
  bwd h =  zS , (h , subst ⟨_⟩
      (sym (prAtL-adequate zero (suc x) (suc y) (zS  γ))) refl) ∣₁
    where
    zS : S
    zS = pr a b , isL-trans {x = fst F} {y = pr a b} h (F .snd)

Single-valuedness

The other half of being a function: a pair's first component determines its second. Three unbounded quantifiers, which cost nothing here, and two applications of the reader above.

Stated as two directions rather than a path, because that is how consumers use it and because building the right-hand side as a proposition would say the same thing at more length. Reading it out is the direction that matters: from the object-language claim, an actual proof that two values recorded against the same argument agree.

svAt :  {n}  Fin n  Formula S n
svAt f = ∀̇ (∀̇ (∀̇ (
      appAt (suc (suc (suc f))) (suc (suc zero)) (suc zero)
  ⇒̇ (appAt (suc (suc (suc f))) (suc (suc zero)) zero
  ⇒̇ (var (suc zero)  var zero)))))

module _ {n : } (f : Fin n) (γ : S ^ n) where
  private
    Holds : S  S  Type (ℓ-suc )
    Holds x y =  pr (fst x) (fst y)  fst (lookup f γ) 

    at : (x y y' : S)
        ((y'  y  x  γ)  appAt (suc (suc (suc f))) (suc (suc zero)) (suc zero))
        (pr (fst x) (fst y)  fst (lookup f γ))
    at x y y' = appAt-adequate (suc (suc (suc f))) (suc (suc zero)) (suc zero)
                  (y'  y  x  γ)

    at' : (x y y' : S)
         ((y'  y  x  γ)  appAt (suc (suc (suc f))) (suc (suc zero)) zero)
         (pr (fst x) (fst y')  fst (lookup f γ))
    at' x y y' = appAt-adequate (suc (suc (suc f))) (suc (suc zero)) zero
                   (y'  y  x  γ)

  svAt-out :  γ  svAt f 
            (x y y' : S)  Holds x y  Holds x y'  fst y  fst y'
  svAt-out h x y y' p q = h x y y'
    (subst ⟨_⟩ (sym (at x y y')) p) (subst ⟨_⟩ (sym (at' x y y')) q)

  svAt-in : ((x y y' : S)  Holds x y  Holds x y'  fst y  fst y')
            γ  svAt f 
  svAt-in h x y y' p q = h x y y'
    (subst ⟨_⟩ (at x y y') p) (subst ⟨_⟩ (at' x y y') q)

The domain

Being in the domain is having a value: one unbounded existential over the reader above. The domain itself is then the set with exactly those members, said as two implications, since the object language has no biconditional of its own and spelling it out is shorter than adding one.

Both are used in one direction each, and only those directions are extracted. A consumer holding a table asks either "this argument has an entry, so it is in the domain" or "this argument is in the domain, so it has an entry"; nothing wants the statement as a proposition.

inDomAt :  {n}  Fin n  Fin n  Formula S n
inDomAt f x = ∃̇ (appAt (suc f) (suc x) zero)

inDomAt-adequate :  {n} (f x : Fin n) (γ : S ^ n)
   (γ  inDomAt f x)
   (∃[ y  S ] (pr (fst (lookup x γ)) (fst y)  fst (lookup f γ)))
inDomAt-adequate f x γ =
  cong ( S) (funExt  y  appAt-adequate (suc f) (suc x) zero (y  γ)))

domAt :  {n}  Fin n  Fin n  Formula S n
domAt f d = ∀̇ ( (inDomAt (suc f) zero ⇒̇ (var zero ∈̇ var (suc d)))
             ∧̇ ((var zero ∈̇ var (suc d)) ⇒̇ inDomAt (suc f) zero) )

module _ {n : } (f d : Fin n) (γ : S ^ n) where
  private
    step : (x : S)
          ((x  γ)  inDomAt (suc f) zero)
          (∃[ y  S ] (pr (fst x) (fst y)  fst (lookup f γ)))
    step x = inDomAt-adequate (suc f) zero (x  γ)

  domAt-out :  γ  domAt f d   (x y : S)
              pr (fst x) (fst y)  fst (lookup f γ) 
              fst x  fst (lookup d γ) 
  domAt-out h x y p = h x .fst (subst ⟨_⟩ (sym (step x))  y , p ∣₁)

  domAt-in :  γ  domAt f d   (x : S)   fst x  fst (lookup d γ) 
             (Σ[ y  S ]  pr (fst x) (fst y)  fst (lookup f γ) ) ∥₁
  domAt-in h x m = subst ⟨_⟩ (step x) (h x .snd m)

  domAt-intro : ((x : S)
                  ( ∃[ y  S ] (pr (fst x) (fst y)  fst (lookup f γ)) 
                      fst x  fst (lookup d γ) )
                 × ( fst x  fst (lookup d γ) 
                      ∃[ y  S ] (pr (fst x) (fst y)  fst (lookup f γ)) ))
                γ  domAt f d 
  domAt-intro g x =  h  g x .fst (subst ⟨_⟩ (step x) h))
                  ,  m  subst ⟨_⟩ (sym (step x)) (g x .snd m))

The pair, inside the model

Every code is built by pairing, so every construction below needs the ordered pair of two elements of L to be one. It is, three applications of the model's own pairing, and the projection equations of the numeral chapter say that reading it through the underlying set gives the hierarchy's pair back. The singleton is the two-element pair with equal components, which is the one small identity the hierarchy supplies.

prʟ : S  S  S
prʟ a b = pairʟ (pairʟ a a) (pairʟ a b)

prʟ-fst : (a b : S)  fst (prʟ a b)  pr (fst a) (fst b)
prʟ-fst a b =
    pairʟ-fst (pairʟ a a) (pairʟ a b)
   cong₂ ⁅_,_⁆ (pairʟ-fst a a  pair-singleton (fst a)) (pairʟ-fst a b)

The coding, at the model

The pair and the numerals are injective, which is everything the coding chapter asks of a structure, so the object language codes into L itself. Two things follow and both are wanted. A code is an element of the model by construction, with no constructibility certificate to carry or to prove. And the code equation is injective at this arity, by the chapter's own theorem, which is what a table indexed by codes needs: two occurrences of different subformulas must not share a key, or the table is multi-valued and its existence fails.

The bridge says the two codings agree: reading a code of the model through the underlying set gives the hierarchy's code of the relabelled formula. Twelve clauses and two, each one tag equation over the clause below it. It is what lets the readers of this chapter, which are written on the hierarchy side, be applied to codes built on the model side.

prʟ-inj : {a b c d : S}  prʟ a b  prʟ c d  (a  c) × (b  d)
prʟ-inj {a} {b} {c} {d} e =
    Σ≡Prop  v  snd (isL v)) (pr-inj q .fst)
  , Σ≡Prop  v  snd (isL v)) (pr-inj q .snd)
  where
  q : pr (fst a) (fst b)  pr (fst c) (fst d)
  q = sym (prʟ-fst a b)  cong fst e  prʟ-fst c d

numeralL-inj : {j k : }  numeralL j  numeralL k  j  k
numeralL-inj {j} {k} e =
  #-inj′ (sym (numeralL-fst j)  cong fst e  numeralL-fst k)

module LCode = FOL.Coding {ℓ-suc } 𝒮ʟ prʟ prʟ-inj numeralL numeralL-inj

tagBridge : (k : ) (x : S)  fst (LCode.mkTag k x)  VCode.mkTag k (fst x)
tagBridge k x = prʟ-fst (numeralL k) x  cong₂ pr (numeralL-fst k) refl

codeBridgeTm :  {n} (t : Term S n)  fst LCode.⌜ t ⌝ᵗ  VCode.⌜ mapTm fst t ⌝ᵗ
codeBridgeTm (con c) = tagBridge 0 c
codeBridgeTm (var i) =
  tagBridge 1 (numeralL (toℕ i))  cong (VCode.mkTag 1) (numeralL-fst (toℕ i))

codeBridge :  {n} (φ : Formula S n)  fst LCode.⌜ φ   VCode.⌜ mapFo fst φ 
codeBridge (t ∈̇ u) = tagBridge 0 _  cong (VCode.mkTag 0)
  (prʟ-fst _ _  cong₂ pr (codeBridgeTm t) (codeBridgeTm u))
codeBridge (t  u) = tagBridge 1 _  cong (VCode.mkTag 1)
  (prʟ-fst _ _  cong₂ pr (codeBridgeTm t) (codeBridgeTm u))
codeBridge (a ∧̇ b) = tagBridge 2 _  cong (VCode.mkTag 2)
  (prʟ-fst _ _  cong₂ pr (codeBridge a) (codeBridge b))
codeBridge (a ∨̇ b) = tagBridge 3 _  cong (VCode.mkTag 3)
  (prʟ-fst _ _  cong₂ pr (codeBridge a) (codeBridge b))
codeBridge (a ⇒̇ b) = tagBridge 4 _  cong (VCode.mkTag 4)
  (prʟ-fst _ _  cong₂ pr (codeBridge a) (codeBridge b))
codeBridge (¬̇ a)   = tagBridge 5 _  cong (VCode.mkTag 5) (codeBridge a)
codeBridge ⊤̇       = tagBridge 6 _  cong (VCode.mkTag 6) (numeralL-fst 0)
codeBridge ⊥̇       = tagBridge 7 _  cong (VCode.mkTag 7) (numeralL-fst 0)
codeBridge (∃̇ a)   = tagBridge 8 _  cong (VCode.mkTag 8) (codeBridge a)
codeBridge (∀̇ a)   = tagBridge 9 _  cong (VCode.mkTag 9) (codeBridge a)
codeBridge (∀̇∈ t a) = tagBridge 10 _  cong (VCode.mkTag 10)
  (prʟ-fst _ _  cong₂ pr (codeBridgeTm t) (codeBridge a))
codeBridge (∃̇∈ t a) = tagBridge 11 _  cong (VCode.mkTag 11)
  (prʟ-fst _ _  cong₂ pr (codeBridgeTm t) (codeBridge a))



Environments

An environment is a function whose values lie in a given set, so an environment over a set is the conjunction of four things: single-valued, with the given domain, with values where they belong, and made of pairs.

The fourth is easy to leave out and fatal to leave out. The other three all speak about the pairs in a set and say nothing whatever about a member that is not one, so without it a set could carry any amount of junk and still qualify. That costs nothing where the predicate is only tested, but the frame that describes a set by its members asserts both directions, so a value satisfying it would have to contain every such junk-bearing set: a proper class, and a hypothesis no set can discharge. The conjunct pins each member to a pair of an index and a value, which makes an environment a subset of a product and the collection of them a set.

Only the four projections are given, because that is all a consumer wants. Whether a particular set is the set of all environments of a given length is a different question, and a harder one; this says only what it means for a single thing to be one.

valuesInAt :  {n}  Fin n  Fin n  Formula S n
valuesInAt f B = ∀̇ (∀̇ ( appAt (suc (suc f)) (suc zero) zero
                     ⇒̇ (var zero ∈̇ var (suc (suc B))) ))

valuesInAt-out :  {n} (f B : Fin n) (γ : S ^ n)
                 γ  valuesInAt f B   (x y : S)
                 pr (fst x) (fst y)  fst (lookup f γ) 
                 fst y  fst (lookup B γ) 
valuesInAt-out f B γ h x y p = h x y
  (subst ⟨_⟩ (sym (appAt-adequate (suc (suc f)) (suc zero) zero (y  x  γ))) p)

pairsInAt :  {n}  Fin n  Fin n  Fin n  Formula S n
pairsInAt e d B =
  ∀̇∈ (var e) (∃̇∈ (var (suc d)) (∃̇∈ (var (suc (suc B)))
    (prAtL (suc (suc zero)) (suc zero) zero)))

pairsIn-out :  {n} (e d B : Fin n) (γ : S ^ n)   γ  pairsInAt e d B 
             (s : S)   fst s  fst (lookup e γ) 
              (Σ[ u  S ] (Σ[ v  S ]
                  ( fst u  fst (lookup d γ) 
                   × ( fst v  fst (lookup B γ) 
                      × (fst s  pr (fst u) (fst v)))))) ∥₁
pairsIn-out e d B γ h s s∈ = PT.rec squash₁
   { (u , (u∈ , hv))  PT.map
     { (v , (v∈ , hp))  u , (v , (u∈ , (v∈ , subst ⟨_⟩
      (prAtL-adequate (suc (suc zero)) (suc zero) zero (v  u  s  γ)) hp))) })
    hv })
  (h s s∈)

pairsIn-in :  {n} (e d B : Fin n) (γ : S ^ n)
            ((s : S)   fst s  fst (lookup e γ) 
                (Σ[ u  S ] (Σ[ v  S ]
                    ( fst u  fst (lookup d γ) 
                     × ( fst v  fst (lookup B γ) 
                        × (fst s  pr (fst u) (fst v)))))) ∥₁)
             γ  pairsInAt e d B 
pairsIn-in e d B γ k s s∈ = PT.map
   { (u , (v , (u∈ , (v∈ , eq))))  u , (u∈ ,  v , (v∈ , subst ⟨_⟩
    (sym (prAtL-adequate (suc (suc zero)) (suc zero) zero (v  u  s  γ))) eq) ∣₁) })
  (k s s∈)

envOverAt :  {n}  Fin n  Fin n  Fin n  Formula S n
envOverAt e d B =
  svAt e ∧̇ (domAt e d ∧̇ (valuesInAt e B ∧̇ pairsInAt e d B))

module _ {n : } (e d B : Fin n) (γ : S ^ n) (h :  γ  envOverAt e d B ) where
  envOver-sv     :  γ  svAt e 
  envOver-sv     = h .fst
  envOver-dom    :  γ  domAt e d 
  envOver-dom    = h .snd .fst
  envOver-values :  γ  valuesInAt e B 
  envOver-values = h .snd .snd .fst
  envOver-pairs  :  γ  pairsInAt e d B 
  envOver-pairs  = h .snd .snd .snd

A description reads the same in any frame that puts the same three sets where it looks. Every reader above is stated through fst of a lookup and nothing else, so moving the description from one environment to another is four transports and no thought. Seven of the twelve clauses bind their own ambient set, and this is what turns "the members of that set are the environments" back into a statement about the set a construction actually built.

valuesInAt-in :  {n} (f B : Fin n) (γ : S ^ n)
               ((x y : S)   pr (fst x) (fst y)  fst (lookup f γ) 
                   fst y  fst (lookup B γ) )
                γ  valuesInAt f B 
valuesInAt-in f B γ k x y hp = k x y
  (subst ⟨_⟩ (appAt-adequate (suc (suc f)) (suc zero) zero (y  x  γ)) hp)

envOverAt-transport :  {n n'} (γ : S ^ n) (γ' : S ^ n')
                      (e d B : Fin n) (e' d' B' : Fin n')
                     fst (lookup e γ)  fst (lookup e' γ')
                     fst (lookup d γ)  fst (lookup d' γ')
                     fst (lookup B γ)  fst (lookup B' γ')
                      γ  envOverAt e d B    γ'  envOverAt e' d' B' 
envOverAt-transport γ γ' e d B e' d' B' qe qd qb h =
    svAt-in e' γ'  x y y' p q 
      svAt-out e γ (envOver-sv e d B γ h) x y y'
        (subst ⟨_⟩ (sym (at x y)) p) (subst ⟨_⟩ (sym (at x y')) q))
  , ( domAt-intro e' d' γ'
       x   m  subst  w   fst x  w ) qd
                (PT.rec (snd (fst x  fst (lookup d γ)))
                   { (y , p)  domAt-out e d γ (envOver-dom e d B γ h) x y
                         (subst ⟨_⟩ (sym (at x y)) p) })
                  m))
            ,  hx  PT.map  { (y , p)  y , subst ⟨_⟩ (at x y) p })
                (domAt-in e d γ (envOver-dom e d B γ h) x
                  (subst  w   fst x  w ) (sym qd) hx))))
    , ( valuesInAt-in e' B' γ'
         x y p  subst  w   fst y  w ) qb
          (valuesInAt-out e B γ (envOver-values e d B γ h) x y
            (subst ⟨_⟩ (sym (at x y)) p)))
      , pairsIn-in e' d' B' γ'
         s s∈  PT.map
           { (u , (v , (u∈ , (v∈ , eq)))) 
            u , (v , ( subst  w   fst u  w ) qd u∈
                     , ( subst  w   fst v  w ) qb v∈ , eq ) )) })
          (pairsIn-out e d B γ (envOver-pairs e d B γ h) s
            (subst  w   fst s  w ) (sym qe) s∈))) ) )
  where
  at : (x y : S)  (pr (fst x) (fst y)  fst (lookup e γ))
                  (pr (fst x) (fst y)  fst (lookup e' γ'))
  at x y = cong  w  pr (fst x) (fst y)  w) qe

Tags

A code carries its constructor as a numeral in the first component of a pair, so reading a code's shape means reading a pair whose first component is a given numeral. The reader for that could be quoted like the others, but it would cost more than writing it: the hierarchy's version names the numeral as a constant of the hierarchy, so the bridge would demand a constructibility witness threaded through the whole shape of the formula.

Writing it takes the shorter road, and the road the bridge chapter recommends. The numeral of L is already an element of the model, so it is already a legal constant here; one unbounded existential says "there is something equal to it, and the pair is built from that". Unbounded costs nothing, and the two readers below reuse the pair reader unchanged rather than re-deriving anything.

The second is the one that does the work later. Every binary constructor of the object language has a code of the same shape, tag applied to the pair of the two subcodes, differing only in which numeral the tag is.

tagAtL :  {n}  Fin n    Fin n  Formula S n
tagAtL s k x = ∃̇ ((var zero  con (numeralL k)) ∧̇ prAtL (suc s) zero (suc x))

tagAtL-adequate :  {n} (s : Fin n) (k : ) (x : Fin n) (γ : S ^ n)
   (γ  tagAtL s k x)
   PairIs (fst (lookup s γ)) (pr (# k) (fst (lookup x γ)))
tagAtL-adequate s k x γ = ⇔toPath fwd bwd
  where
  target = PairIs (fst (lookup s γ)) (pr (# k) (fst (lookup x γ)))

  fwd :  γ  tagAtL s k x    target 
  fwd = PT.rec (snd target)
     { (z , (e , p)) 
      subst ⟨_⟩ (prAtL-adequate (suc s) zero (suc x) (z  γ)) p
       cong  w  pr w (fst (lookup x γ))) (e  numeralL-fst k) })

  bwd :  target    γ  tagAtL s k x 
  bwd q =  numeralL k , (refl , subst ⟨_⟩
      (sym (prAtL-adequate (suc s) zero (suc x) (numeralL k  γ)))
      (q  cong  w  pr w (fst (lookup x γ))) (sym (numeralL-fst k)))) ∣₁

tagPairAtL :  {n}  Fin n    Fin n  Fin n  Formula S n
tagPairAtL s k a b =
  ∃̇ (prAtL zero (suc a) (suc b) ∧̇ tagAtL (suc s) k zero)

tagPairAtL-adequate :  {n} (s : Fin n) (k : ) (a b : Fin n) (γ : S ^ n)
   (γ  tagPairAtL s k a b)
   PairIs (fst (lookup s γ))
      (pr (# k) (pr (fst (lookup a γ)) (fst (lookup b γ))))
tagPairAtL-adequate s k a b γ = ⇔toPath fwd bwd
  where
  A = fst (lookup a γ)
  B = fst (lookup b γ)
  target = PairIs (fst (lookup s γ)) (pr (# k) (pr A B))

  fwd :  γ  tagPairAtL s k a b    target 
  fwd = PT.rec (snd target)
     { (z , (p , t)) 
      subst ⟨_⟩ (tagAtL-adequate (suc s) k zero (z  γ)) t
       cong (pr (# k))
          (subst ⟨_⟩ (prAtL-adequate zero (suc a) (suc b) (z  γ)) p) })

  bwd :  target    γ  tagPairAtL s k a b 
  bwd q =  zS
    , ( subst ⟨_⟩ (sym (prAtL-adequate zero (suc a) (suc b) (zS  γ))) e
      , subst ⟨_⟩ (sym (tagAtL-adequate (suc s) k zero (zS  γ)))
          (q  cong (pr (# k)) (sym e)) ) ∣₁
    where
    zS : S
    zS = prʟ (lookup a γ) (lookup b γ)
    e : fst zS  pr A B
    e = prʟ-fst (lookup a γ) (lookup b γ)

Sets by extension

Every clause of a recursion whose values are sets says the same thing: this value is the set of exactly those things satisfying such-and-such. Written once, with the condition left as a parameter, it is two implications under one quantifier, and its two readings are the two projections. Nothing is proved, which is the point: after this the clauses of a recursion cost only their conditions.

The set operations follow immediately, each one condition long, and each with its meaning already in hand. The rest of a clause's content is whatever the condition says, and that is where the mathematics of a particular recursion lives.

extAt :  {n}  Fin n  Formula S (suc n)  Formula S n
extAt y φ = ∀̇ ((var zero ∈̇ var (suc y)) ⇒̇ φ)
         ∧̇ ∀̇ (φ ⇒̇ (var zero ∈̇ var (suc y)))

module _ {n : } (y : Fin n) (φ : Formula S (suc n)) (γ : S ^ n) where
  extAt-out :  γ  extAt y φ   (z : S)
              fst z  fst (lookup y γ)    (z  γ)  φ 
  extAt-out h = h .fst

  extAt-in :  γ  extAt y φ   (z : S)
             (z  γ)  φ    fst z  fst (lookup y γ) 
  extAt-in h = h .snd

  extAt-in-both : ((z : S)   fst z  fst (lookup y γ)    (z  γ)  φ )
                 ((z : S)   (z  γ)  φ    fst z  fst (lookup y γ) )
                  γ  extAt y φ 
  extAt-in-both f g = f , g

private
  memb :  {n}  Fin n  Formula S (suc n)
  memb a = var zero ∈̇ var (suc a)

interAt :  {n}  Fin n  Fin n  Fin n  Formula S n
interAt y a b = extAt y (memb a ∧̇ memb b)

unionAt :  {n}  Fin n  Fin n  Fin n  Formula S n
unionAt y a b = extAt y (memb a ∨̇ memb b)

diffAt :  {n}  Fin n  Fin n  Fin n  Formula S n
diffAt y a b = extAt y (memb a ∧̇ ¬̇ memb b)

sameAt :  {n}  Fin n  Fin n  Formula S n
sameAt y a = extAt y (memb a)

emptyAt :  {n}  Fin n  Formula S n
emptyAt y = extAt y ⊥̇

implAt :  {n}  Fin n  Fin n  Fin n  Fin n  Formula S n
implAt y e a b = extAt y (memb e ∧̇ (memb a ⇒̇ memb b))

Reading a key in two layers

The codes a recursion ranges over carry their arity: an entry is the arity's numeral paired with the code proper, and the code proper is in turn a tag paired with its payload. So a clause's hypothesis has to read two layers, not one, and reading only the outer one is worse than incomplete. Pairing is injective, so a one-layer reader silently matches the arity against the constructor tag and binds the payload's own tag as though it were a subcode: the clause is then vacuous at every arity but one, and wrong at that one. Nothing in Agda reports this, because the reader is still true; it simply cannot be supplied.

Both layers are read by one existential over the inner code, with the pair reader above pinning the outer layer and the tag reader the inner. The arity is left as a variable, so a clause can speak of it, which the four constructors that change arity need.

arityTagPairAtL :  {n}  Fin n  Fin n    Fin n  Fin n  Formula S n
arityTagPairAtL c ar k a b =
  ∃̇ (prAtL (suc c) (suc ar) zero ∧̇ tagPairAtL zero k (suc a) (suc b))

arityTagPairAtL-adequate :  {n} (c ar : Fin n) (k : ) (a b : Fin n) (γ : S ^ n)
   (γ  arityTagPairAtL c ar k a b)
   PairIs (fst (lookup c γ))
      (pr (fst (lookup ar γ))
        (pr (# k) (pr (fst (lookup a γ)) (fst (lookup b γ)))))
arityTagPairAtL-adequate c ar k a b γ = ⇔toPath fwd bwd
  where
  N = fst (lookup ar γ)
  P = pr (fst (lookup a γ)) (fst (lookup b γ))
  target = PairIs (fst (lookup c γ)) (pr N (pr (# k) P))

  fwd :  γ  arityTagPairAtL c ar k a b    target 
  fwd = PT.rec (snd target)
     { (z , (p , t)) 
      subst ⟨_⟩ (prAtL-adequate (suc c) (suc ar) zero (z  γ)) p
       cong (pr N) (subst ⟨_⟩ (tagPairAtL-adequate zero k (suc a) (suc b) (z  γ)) t) })

  bwd :  target    γ  arityTagPairAtL c ar k a b 
  bwd q =  zS
    , ( subst ⟨_⟩ (sym (prAtL-adequate (suc c) (suc ar) zero (zS  γ)))
          (q  cong (pr N) (sym e))
      , subst ⟨_⟩ (sym (tagPairAtL-adequate zero k (suc a) (suc b) (zS  γ))) e ) ∣₁
    where
    zS : S
    zS = prʟ (numeralL k) (prʟ (lookup a γ) (lookup b γ))
    e : fst zS  pr (# k) P
    e = prʟ-fst (numeralL k) (prʟ (lookup a γ) (lookup b γ))
       cong₂ pr (numeralL-fst k) (prʟ-fst (lookup a γ) (lookup b γ))

arityTagAtL :  {n}  Fin n  Fin n    Fin n  Formula S n
arityTagAtL c ar k a =
  ∃̇ (prAtL (suc c) (suc ar) zero ∧̇ tagAtL zero k (suc a))

arityTagAtL-adequate :  {n} (c ar : Fin n) (k : ) (a : Fin n) (γ : S ^ n)
   (γ  arityTagAtL c ar k a)
   PairIs (fst (lookup c γ))
      (pr (fst (lookup ar γ)) (pr (# k) (fst (lookup a γ))))
arityTagAtL-adequate c ar k a γ = ⇔toPath fwd bwd
  where
  N = fst (lookup ar γ)
  A = fst (lookup a γ)
  target = PairIs (fst (lookup c γ)) (pr N (pr (# k) A))

  fwd :  γ  arityTagAtL c ar k a    target 
  fwd = PT.rec (snd target)
     { (z , (p , t)) 
      subst ⟨_⟩ (prAtL-adequate (suc c) (suc ar) zero (z  γ)) p
       cong (pr N) (subst ⟨_⟩ (tagAtL-adequate zero k (suc a) (z  γ)) t) })

  bwd :  target    γ  arityTagAtL c ar k a 
  bwd q =  zS
    , ( subst ⟨_⟩ (sym (prAtL-adequate (suc c) (suc ar) zero (zS  γ)))
          (q  cong (pr N) (sym e))
      , subst ⟨_⟩ (sym (tagAtL-adequate zero k (suc a) (zS  γ))) e ) ∣₁
    where
    zS : S
    zS = prʟ (numeralL k) (lookup a γ)
    e : fst zS  pr (# k) A
    e = prʟ-fst (numeralL k) (lookup a γ)  cong₂ pr (numeralL-fst k) refl

Looking a subcode up in the table

The frames bind a code's payload but never look the table up at it, because a payload component may be a term code, at which the table has nothing. A relation that does want the value must therefore build the key itself: pair the arity with the component, and read the table there.

That is one existential over the key, and it is the piece four of the twelve relations are built from. The two that speak of a subformula at the next arity need the same thing with the arity bumped, which is this with one more layer.

subValAt :  {n}  Fin n  Fin n  Fin n  Fin n  Formula S n
subValAt T ar a y =
  ∃̇ (prAtL zero (suc ar) (suc a) ∧̇ appAt (suc T) zero (suc y))

subValAt-adequate :  {n} (T ar a y : Fin n) (γ : S ^ n)
   (γ  subValAt T ar a y)
   (pr (pr (fst (lookup ar γ)) (fst (lookup a γ))) (fst (lookup y γ))
       fst (lookup T γ))
subValAt-adequate T ar a y γ = ⇔toPath fwd bwd
  where
  K = pr (fst (lookup ar γ)) (fst (lookup a γ))
  target = pr K (fst (lookup y γ))  fst (lookup T γ)

  fwd :  γ  subValAt T ar a y    target 
  fwd = PT.rec (snd target)
     { (z , (p , q)) 
      subst  w   pr w (fst (lookup y γ))  fst (lookup T γ) )
        (subst ⟨_⟩ (prAtL-adequate zero (suc ar) (suc a) (z  γ)) p)
        (subst ⟨_⟩ (appAt-adequate (suc T) zero (suc y) (z  γ)) q) })

  bwd :  target    γ  subValAt T ar a y 
  bwd h =  zS
    , ( subst ⟨_⟩ (sym (prAtL-adequate zero (suc ar) (suc a) (zS  γ))) e
      , subst ⟨_⟩ (sym (appAt-adequate (suc T) zero (suc y) (zS  γ)))
          (subst  w   pr w (fst (lookup y γ))  fst (lookup T γ) ) (sym e) h) ) ∣₁
    where
    zS : S
    zS = prʟ (lookup ar γ) (lookup a γ)
    e : fst zS  K
    e = prʟ-fst (lookup ar γ) (lookup a γ)

The shape of a clause

A recursion on codes is stated by clauses, and the clauses come in a few shapes rather than twelve. A binary constructor's clause says: for every code in the index with this tag over these two subcodes, and for the values the table records at the three of them, such-and-such holds. All of that is fixed except the such-and-such, so it is written once with the relation as a parameter, and the three binary constructors differ only in which relation they hand it.

Five things are bound, in the order a reader meets them: the code, its arity, its two payload components, and the value the table records at the code. The values at the payload components are not bound, and that is what makes the frame general. A connective's payload is a pair of formula codes and its clause does want them, but an atom's payload is a pair of term codes, at which the table has no entries at all, and a bounded quantifier's payload mixes the two. So the frame binds what every constructor has and leaves the lookups to the relation, which may perform them freely.

Reading the clause back is one chain of substitutions along the readers' adequacy, and it is stated in the direction a soundness proof consumes: given a code of that shape in the index and the three recorded values, the relation holds.

module _ {n : } where
  private
    sh5 : Fin n  Fin (5 + n)
    sh5 i = suc (suc (suc (suc (suc i))))

    c5 n5 a5 b5 yc5 : Fin (5 + n)
    c5  = suc (suc (suc (suc zero)))
    n5  = suc (suc (suc zero))
    a5  = suc (suc zero)
    b5  = suc zero
    yc5 = zero

  binClauseAt : Fin n  Fin n    Formula S (5 + n)  Formula S n
  binClauseAt C T k rel =
    ∀̇∈ (var C) (∀̇ (∀̇ (∀̇ (∀̇
      ( arityTagPairAtL c5 n5 k a5 b5
      ⇒̇ ( appAt (sh5 T) c5 yc5
      ⇒̇ rel ))))))

  binClause-out : (C T : Fin n) (k : ) (rel : Formula S (5 + n)) (γ : S ^ n)
      γ  binClauseAt C T k rel 
     (c ar a b yc : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
      pr (fst c) (fst yc)  fst (lookup T γ) 
      (yc  b  a  ar  c  γ)  rel 
  binClause-out C T k rel γ h c ar a b yc c∈ shape hc =
    h c c∈ ar a b yc
      (subst ⟨_⟩ (sym (arityTagPairAtL-adequate c5 n5 k a5 b5 δ)) shape)
      (subst ⟨_⟩ (sym (appAt-adequate (sh5 T) c5 yc5 δ)) hc)
    where
    δ : S ^ (5 + n)
    δ = yc  b  a  ar  c  γ

Each frame reads the other way too, and the other way is what an instance uses. The elimination takes a clause apart for a consumer who has a code in hand; the introduction assembles one for a table that has to satisfy it. Both frames introduce by a lambda, because a bounded universal over the model is a function on members and an implication is a function on the reader's proof, so the two are the same substitutions run backwards.

  binClause-in : (C T : Fin n) (k : ) (rel : Formula S (5 + n)) (γ : S ^ n)
     ((c ar a b yc : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
         pr (fst c) (fst yc)  fst (lookup T γ) 
         (yc  b  a  ar  c  γ)  rel )
      γ  binClauseAt C T k rel 
  binClause-in C T k rel γ g c c∈ ar a b yc sh hc =
    g c ar a b yc c∈
      (subst ⟨_⟩ (arityTagPairAtL-adequate c5 n5 k a5 b5 δ) sh)
      (subst ⟨_⟩ (appAt-adequate (sh5 T) c5 yc5 δ) hc)
    where
    δ : S ^ (5 + n)
    δ = yc  b  a  ar  c  γ

Counting the shapes is worth a moment, because it says how much of the twelve is really there, and because counting it wrong is easy: this paragraph has been wrong twice.

The frames distinguish exactly one thing, whether the payload is a pair or a single component. The pair frame covers the two atoms, the three connectives and the two bounded quantifiers, which is seven; the single-component frame covers negation, the two unbounded quantifiers, and the two constants, which is five, since a constant's payload is a numeral and the frame does not care what a component is. Two frames, then, and twelve relations above them.

What the frames must not distinguish is what the payload components are. Grouping by that gives five kinds of relation, not five frames: term against term, formula against formula, term against formula, one formula, and one formula at the next arity. That is where the twelve actually divide, and it divides them in the relations, where the lookups live.

The single-component frame is the pair frame with one binder fewer, and reads back the same way.

  private
    sh4 : Fin n  Fin (4 + n)
    sh4 i = suc (suc (suc (suc i)))

    c4 n4 a4 yc4 : Fin (4 + n)
    c4  = suc (suc (suc zero))
    n4  = suc (suc zero)
    a4  = suc zero
    yc4 = zero

  unClauseAt : Fin n  Fin n    Formula S (4 + n)  Formula S n
  unClauseAt C T k rel =
    ∀̇∈ (var C) (∀̇ (∀̇ (∀̇
      ( arityTagAtL c4 n4 k a4
      ⇒̇ ( appAt (sh4 T) c4 yc4
      ⇒̇ rel )))))

  unClause-out : (C T : Fin n) (k : ) (rel : Formula S (4 + n)) (γ : S ^ n)
      γ  unClauseAt C T k rel 
     (c ar a yc : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (fst a))
      pr (fst c) (fst yc)  fst (lookup T γ) 
      (yc  a  ar  c  γ)  rel 
  unClause-out C T k rel γ h c ar a yc c∈ shape hc =
    h c c∈ ar a yc
      (subst ⟨_⟩ (sym (arityTagAtL-adequate c4 n4 k a4 δ)) shape)
      (subst ⟨_⟩ (sym (appAt-adequate (sh4 T) c4 yc4 δ)) hc)
    where
    δ : S ^ (4 + n)
    δ = yc  a  ar  c  γ
  unClause-in : (C T : Fin n) (k : ) (rel : Formula S (4 + n)) (γ : S ^ n)
     ((c ar a yc : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (fst a))
         pr (fst c) (fst yc)  fst (lookup T γ) 
         (yc  a  ar  c  γ)  rel )
      γ  unClauseAt C T k rel 
  unClause-in C T k rel γ g c c∈ ar a yc sh hc =
    g c ar a yc c∈
      (subst ⟨_⟩ (arityTagAtL-adequate c4 n4 k a4 δ) sh)
      (subst ⟨_⟩ (appAt-adequate (sh4 T) c4 yc4 δ) hc)
    where
    δ : S ^ (4 + n)
    δ = yc  a  ar  c  γ

The positive connectives

Two of the twelve can be written now, and they are the two that need nothing the chapter has not got. Conjunction and disjunction relate the value at a code to the values at its two subcodes by intersection and union, at the same arity, and that is the whole of their content.

The shared part is a relation that binds the two subvalues and guards them with the table lookups; the operation is what is left over, and it speaks of the value at the code and the two subvalues, at positions two, one and zero. So a propositional clause is one line above the shared part.

Implication and negation want the complement, hence the set of all environments at the code's arity, which the chapter does not yet name. They wait for it. The split is not arbitrary: it is exactly the split between the connectives whose truth is monotone in their parts and those whose truth is not.

module _ {n : } where
  private
    sh7 : Fin n  Fin (7 + n)
    sh7 i = suc (suc (suc (suc (suc (suc (suc i))))))

  c7 ar7 a7 b7 yc7 ya7 yb7 : Fin (7 + n)
  c7  = suc (suc (suc (suc (suc (suc zero)))))
  ar7 = suc (suc (suc (suc (suc zero))))
  a7  = suc (suc (suc (suc zero)))
  b7  = suc (suc (suc zero))
  yc7 = suc (suc zero)
  ya7 = suc zero
  yb7 = zero

  propRel : Fin n  Formula S (7 + n)  Formula S (5 + n)
  propRel T op =
    ∀̇ (∀̇ ( subValAt (sh7 T) ar7 a7 ya7
         ⇒̇ ( subValAt (sh7 T) ar7 b7 yb7
         ⇒̇ op )))

  propClauseAt : Fin n  Fin n    Formula S (7 + n)  Formula S n
  propClauseAt C T k op = binClauseAt C T k (propRel T op)

  propClause-out : (C T : Fin n) (k : ) (op : Formula S (7 + n)) (γ : S ^ n)
      γ  propClauseAt C T k op 
     (c ar a b yc ya yb : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
      pr (fst c) (fst yc)  fst (lookup T γ) 
      pr (pr (fst ar) (fst a)) (fst ya)  fst (lookup T γ) 
      pr (pr (fst ar) (fst b)) (fst yb)  fst (lookup T γ) 
      (yb  ya  yc  b  a  ar  c  γ)  op 
  propClause-out C T k op γ h c ar a b yc ya yb c∈ shape hc ha hb =
    binClause-out C T k (propRel T op) γ h c ar a b yc c∈ shape hc ya yb
      (subst ⟨_⟩ (sym (subValAt-adequate (sh7 T) ar7 a7 ya7 δ)) ha)
      (subst ⟨_⟩ (sym (subValAt-adequate (sh7 T) ar7 b7 yb7 δ)) hb)
    where
    δ : S ^ (7 + n)
    δ = yb  ya  yc  b  a  ar  c  γ

  propClause-in : (C T : Fin n) (k : ) (op : Formula S (7 + n)) (γ : S ^ n)
     ((c ar a b yc ya yb : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
         pr (fst c) (fst yc)  fst (lookup T γ) 
         pr (pr (fst ar) (fst a)) (fst ya)  fst (lookup T γ) 
         pr (pr (fst ar) (fst b)) (fst yb)  fst (lookup T γ) 
         (yb  ya  yc  b  a  ar  c  γ)  op )
      γ  propClauseAt C T k op 
  propClause-in C T k op γ g =
    binClause-in C T k (propRel T op) γ
       c ar a b yc c∈ sh hc ya yb ha hb 
        g c ar a b yc ya yb c∈ sh hc
          (subst ⟨_⟩
            (subValAt-adequate (sh7 T) ar7 a7 ya7 (yb  ya  yc  b  a  ar  c  γ)) ha)
          (subst ⟨_⟩
            (subValAt-adequate (sh7 T) ar7 b7 yb7 (yb  ya  yc  b  a  ar  c  γ)) hb))

  andClauseAt : Fin n  Fin n  Formula S n
  andClauseAt C T = propClauseAt C T 2 (interAt yc7 ya7 yb7)

  orClauseAt : Fin n  Fin n  Formula S n
  orClauseAt C T = propClauseAt C T 3 (unionAt yc7 ya7 yb7)

The negative connectives

Negation wants the complement, so it wants the set of all environments at the code's arity, and the arity is a variable the frame bound. So the ambient set is a variable too, constrained by saying what its members are, which is the extension frame applied to the environment predicate. One line, and no new machinery: what looked like an obligation to construct a set is, inside a clause, an obligation to describe one.

That the set exists is a different matter and belongs to the chapter that builds a table rather than the one that says what a table is. The clause only has to say, of whatever the table records, that it stands in the right relation to the ambient set; the construction has to produce an ambient set standing there.

envSetAt :  {n}  Fin n  Fin n  Fin n  Formula S n
envSetAt E ar B = extAt E (envOverAt zero (suc ar) (suc B))

module _ {n : } where
  private
    sh6 : Fin n  Fin (6 + n)
    sh6 i = suc (suc (suc (suc (suc (suc i)))))

    c6 ar6 a6 yc6 ya6 E6 : Fin (6 + n)
    c6  = suc (suc (suc (suc (suc zero))))
    ar6 = suc (suc (suc (suc zero)))
    a6  = suc (suc (suc zero))
    yc6 = suc (suc zero)
    ya6 = suc zero
    E6  = zero

    negRel : Fin n  Fin n  Formula S (4 + n)
    negRel T B =
      ∀̇ (∀̇ ( subValAt (sh6 T) ar6 a6 ya6
           ⇒̇ ( envSetAt E6 ar6 (sh6 B)
           ⇒̇ diffAt yc6 E6 ya6 )))

  negClauseAt : Fin n  Fin n  Fin n  Formula S n
  negClauseAt C T B = unClauseAt C T 5 (negRel T B)

  negClause-out : (C T B : Fin n) (γ : S ^ n)
      γ  negClauseAt C T B 
     (c ar a yc ya E : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# 5) (fst a))
      pr (fst c) (fst yc)  fst (lookup T γ) 
      pr (pr (fst ar) (fst a)) (fst ya)  fst (lookup T γ) 
      (E  ya  yc  a  ar  c  γ)  envSetAt E6 ar6 (sh6 B) 
      (E  ya  yc  a  ar  c  γ)  diffAt yc6 E6 ya6 
  negClause-out C T B γ h c ar a yc ya E c∈ shape hc ha hE =
    unClause-out C T 5 (negRel T B) γ h c ar a yc c∈ shape hc ya E
      (subst ⟨_⟩ (sym (subValAt-adequate (sh6 T) ar6 a6 ya6 δ)) ha) hE
    where
    δ : S ^ (6 + n)
    δ = E  ya  yc  a  ar  c  γ
  negClause-in : (C T B : Fin n) (γ : S ^ n)
     ((c ar a yc ya E : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# 5) (fst a))
         pr (fst c) (fst yc)  fst (lookup T γ) 
         pr (pr (fst ar) (fst a)) (fst ya)  fst (lookup T γ) 
         (E  ya  yc  a  ar  c  γ)  envSetAt E6 ar6 (sh6 B) 
         (E  ya  yc  a  ar  c  γ)  diffAt yc6 E6 ya6 )
      γ  negClauseAt C T B 
  negClause-in C T B γ g = unClause-in C T 5 (negRel T B) γ
     c ar a yc c∈ sh hc ya E ha hE 
      g c ar a yc ya E c∈ sh hc
        (subst ⟨_⟩ (subValAt-adequate (sh6 T) ar6 a6 ya6
          (E  ya  yc  a  ar  c  γ)) ha) hE)

Implication, and the two constants

Implication is stated the way the reference semantics states it, as an implication, and not as the complement of the antecedent joined with the consequent. The two agree classically and do not agree here. The truth algebra's arrow is a function space, so the joined form is the weaker of the two, and recovering the intended one from it is excluded middle for "this environment satisfies the antecedent". A chapter that takes no classical parameter may not quietly need one.

Said as an implication it is shorter than the joined form as well: the temporary that held the difference is gone, and the object language's own arrow does the work inside the extension frame. Negation keeps its difference, which is not the same trade: a difference read as "in the ambient set and not in this one" is the negation the algebra means.

The constants are the shortest. Truth at an arity is the whole ambient set, and falsity is empty, so one binds the ambient set and the other binds nothing. They go through the single-component frame, since a constant's payload is a numeral and the frame does not look at what a component is; their relations simply ignore it.

module _ {n : } where
  private
    sh8 : Fin n  Fin (8 + n)
    sh8 i = suc (suc (suc (suc (suc (suc (suc (suc i)))))))

    ar8 a8 b8 yc8 ya8 yb8 E8 : Fin (8 + n)
    ar8 = suc (suc (suc (suc (suc (suc zero)))))
    a8  = suc (suc (suc (suc (suc zero))))
    b8  = suc (suc (suc (suc zero)))
    yc8 = suc (suc (suc zero))
    ya8 = suc (suc zero)
    yb8 = suc zero
    E8  = zero

    impRel : Fin n  Fin n  Formula S (5 + n)
    impRel T B =
      ∀̇ (∀̇ (∀̇ ( subValAt (sh8 T) ar8 a8 ya8
              ⇒̇ ( subValAt (sh8 T) ar8 b8 yb8
              ⇒̇ ( envSetAt E8 ar8 (sh8 B)
              ⇒̇ implAt yc8 E8 ya8 yb8 )))))

    sh5 : Fin n  Fin (5 + n)
    sh5 i = suc (suc (suc (suc (suc i))))

    ar5 yc5 E5 : Fin (5 + n)
    ar5 = suc (suc (suc zero))
    yc5 = suc zero
    E5  = zero

    topRel : Fin n  Formula S (4 + n)
    topRel B = ∀̇ ( envSetAt E5 ar5 (sh5 B) ⇒̇ sameAt yc5 E5 )

  impClauseAt : Fin n  Fin n  Fin n  Formula S n
  impClauseAt C T B = binClauseAt C T 4 (impRel T B)

  topClauseAt : Fin n  Fin n  Fin n  Formula S n
  topClauseAt C T B = unClauseAt C T 6 (topRel B)

  botClauseAt : Fin n  Fin n  Formula S n
  botClauseAt C T = unClauseAt C T 7 (emptyAt zero)

Three more pairs of readers, and the pattern does not change: an elimination peels the frame and the relation's own binders off, an introduction puts them back. The constants are shorter than the connective because their relations bind less, not because they are special.

  impClause-out : (C T B : Fin n) (γ : S ^ n)
      γ  impClauseAt C T B 
     (c ar a b yc ya yb E : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# 4) (pr (fst a) (fst b)))
      pr (fst c) (fst yc)  fst (lookup T γ) 
      pr (pr (fst ar) (fst a)) (fst ya)  fst (lookup T γ) 
      pr (pr (fst ar) (fst b)) (fst yb)  fst (lookup T γ) 
      (E  yb  ya  yc  b  a  ar  c  γ)  envSetAt E8 ar8 (sh8 B) 
      (E  yb  ya  yc  b  a  ar  c  γ)  implAt yc8 E8 ya8 yb8 
  impClause-out C T B γ h c ar a b yc ya yb E c∈ shape hc ha hb hE =
    binClause-out C T 4 (impRel T B) γ h c ar a b yc c∈ shape hc ya yb E
      (subst ⟨_⟩ (sym (subValAt-adequate (sh8 T) ar8 a8 ya8 δ)) ha)
      (subst ⟨_⟩ (sym (subValAt-adequate (sh8 T) ar8 b8 yb8 δ)) hb) hE
    where
    δ : S ^ (8 + n)
    δ = E  yb  ya  yc  b  a  ar  c  γ

  impClause-in : (C T B : Fin n) (γ : S ^ n)
     ((c ar a b yc ya yb E : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# 4) (pr (fst a) (fst b)))
         pr (fst c) (fst yc)  fst (lookup T γ) 
         pr (pr (fst ar) (fst a)) (fst ya)  fst (lookup T γ) 
         pr (pr (fst ar) (fst b)) (fst yb)  fst (lookup T γ) 
         (E  yb  ya  yc  b  a  ar  c  γ)  envSetAt E8 ar8 (sh8 B) 
         (E  yb  ya  yc  b  a  ar  c  γ)  implAt yc8 E8 ya8 yb8 )
      γ  impClauseAt C T B 
  impClause-in C T B γ g = binClause-in C T 4 (impRel T B) γ
     c ar a b yc c∈ sh hc ya yb E ha hb hE 
      g c ar a b yc ya yb E c∈ sh hc
        (subst ⟨_⟩ (subValAt-adequate (sh8 T) ar8 a8 ya8
          (E  yb  ya  yc  b  a  ar  c  γ)) ha)
        (subst ⟨_⟩ (subValAt-adequate (sh8 T) ar8 b8 yb8
          (E  yb  ya  yc  b  a  ar  c  γ)) hb) hE)

  topClause-out : (C T B : Fin n) (γ : S ^ n)
      γ  topClauseAt C T B 
     (c ar a yc E : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# 6) (fst a))
      pr (fst c) (fst yc)  fst (lookup T γ) 
      (E  yc  a  ar  c  γ)  envSetAt E5 ar5 (sh5 B) 
      (E  yc  a  ar  c  γ)  sameAt yc5 E5 
  topClause-out C T B γ h c ar a yc E c∈ shape hc hE =
    unClause-out C T 6 (topRel B) γ h c ar a yc c∈ shape hc E hE

  topClause-in : (C T B : Fin n) (γ : S ^ n)
     ((c ar a yc E : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# 6) (fst a))
         pr (fst c) (fst yc)  fst (lookup T γ) 
         (E  yc  a  ar  c  γ)  envSetAt E5 ar5 (sh5 B) 
         (E  yc  a  ar  c  γ)  sameAt yc5 E5 )
      γ  topClauseAt C T B 
  topClause-in C T B γ g = unClause-in C T 6 (topRel B) γ
     c ar a yc c∈ sh hc E hE  g c ar a yc E c∈ sh hc hE)

  botClause-out : (C T : Fin n) (γ : S ^ n)
      γ  botClauseAt C T 
     (c ar a yc : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# 7) (fst a))
      pr (fst c) (fst yc)  fst (lookup T γ) 
      (yc  a  ar  c  γ)  emptyAt zero 
  botClause-out C T γ h = unClause-out C T 7 (emptyAt zero) γ h

  botClause-in : (C T : Fin n) (γ : S ^ n)
     ((c ar a yc : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# 7) (fst a))
         pr (fst c) (fst yc)  fst (lookup T γ) 
         (yc  a  ar  c  γ)  emptyAt zero )
      γ  botClauseAt C T 
  botClause-in C T γ = unClause-in C T 7 (emptyAt zero) γ

The next arity

Four of the twelve bind a variable, so their subformula sits one arity higher and the table has to be consulted there. The successor reader is already written on the hierarchy side and names no constants, so it crosses by quoting, and the lookup at the next arity is the lookup at a fresh arity constrained to be the successor of the one the frame bound.

The backward direction needs the successor as an element of the model, and the numeral chapter supplies it: the model's own successor, read through the underlying set, is the hierarchy's.

sucAtL :  {n}  Fin n  Fin n  Formula S n
sucAtL i j = liftFo (sucAt i j) _

sucAtL-adequate :  {n} (i j : Fin n) (γ : S ^ n)
   (γ  sucAtL i j)  PairIs (fst (lookup j γ)) (sucV (fst (lookup i γ)))
sucAtL-adequate i j γ =
    transferFo (sucAt i j) _ (Δ₀-sucAt i j) γ
   sucAt-adequate i j (map fst γ)
   cong₂ PairIs (lookup-fst j γ) (cong sucV (lookup-fst i γ))

subValSuccAt :  {n}  Fin n  Fin n  Fin n  Fin n  Formula S n
subValSuccAt T ar a y =
  ∃̇ (sucAtL (suc ar) zero ∧̇ subValAt (suc T) zero (suc a) (suc y))

subValSuccAt-adequate :  {n} (T ar a y : Fin n) (γ : S ^ n)
   (γ  subValSuccAt T ar a y)
   (pr (pr (sucV (fst (lookup ar γ))) (fst (lookup a γ))) (fst (lookup y γ))
       fst (lookup T γ))
subValSuccAt-adequate T ar a y γ = ⇔toPath fwd bwd
  where
  key : V   V 
  key w = pr (pr w (fst (lookup a γ))) (fst (lookup y γ))
  target = key (sucV (fst (lookup ar γ)))  fst (lookup T γ)

  fwd :  γ  subValSuccAt T ar a y    target 
  fwd = PT.rec (snd target)
     { (z , (sz , v)) 
      subst  w   key w  fst (lookup T γ) )
        (subst ⟨_⟩ (sucAtL-adequate (suc ar) zero (z  γ)) sz)
        (subst ⟨_⟩ (subValAt-adequate (suc T) zero (suc a) (suc y) (z  γ)) v) })

  bwd :  target    γ  subValSuccAt T ar a y 
  bwd h =  zS
    , ( subst ⟨_⟩ (sym (sucAtL-adequate (suc ar) zero (zS  γ))) e
      , subst ⟨_⟩ (sym (subValAt-adequate (suc T) zero (suc a) (suc y) (zS  γ)))
          (subst  w   key w  fst (lookup T γ) ) (sym e) h) ) ∣₁
    where
    zS : S
    zS = sucʟ (lookup ar γ)
    e : fst zS  sucV (fst (lookup ar γ))
    e = sucʟ-fst (lookup ar γ)

Extending an environment

The other half of a quantifier clause: the environment the subformula is evaluated in is the one at hand with a value pushed on the front. That reader is already written on the hierarchy side, and its meaning there is stated against a meta-level family, which is exactly the form a soundness proof will want. So it is worth quoting rather than rewriting, even though quoting is not free here: it names a numeral as a hierarchy constant, so the bridge asks for that numeral's constructibility at every place the shape mentions it.

Those places are written out once, per reader, and then the whole extension reader's admissibility is three of them. The numeral's own constructibility comes from the numeral chapter, which is why it sits here rather than with the codes.

numL : (k : )  InL (# k)
numL k = subst  w   isL w ) (numeralL-fst k) (numeralL k .snd)

private
  bddSglCon :  {n} (k : Fin n) (j : )  BoundedFo InL (sglConAt k (# j))
  bddSglCon k j = (numL j , _) , (_ , (_ , numL j))

  bddPairCon :  {n} (k : Fin n) (j : ) (x : Fin n)
              BoundedFo InL (pairConAt k (# j) x)
  bddPairCon k j x = (numL j , _) , ((_ , _) , (_ , ((_ , numL j) , (_ , _))))

  bddTag :  {n} (s : Fin n) (j : ) (x : Fin n)  BoundedFo InL (tagAt s j x)
  bddTag {n} s j x =
      (_ , bddSglCon {suc n} zero j)
    , ( (_ , bddPairCon {suc n} zero j (suc x))
      , (_ , (bddSglCon {suc n} zero j , bddPairCon {suc n} zero j (suc x))) )

  bddShift :  {n} (p' p : Fin n)  BoundedFo InL (shiftPairAt p' p)
  bddShift p' p = _

  bddCons :  {n} (e' m e : Fin n)  BoundedFo InL (consAt e' m e)
  bddCons {n} e' m e =
      (_ , bddTag {suc n} zero 0 (suc m))
    , ( (_ , (_ , bddShift {suc (suc n)} zero (suc zero)))
      , (_ , ( bddTag {suc n} zero 0 (suc m)
             , (_ , bddShift {suc (suc n)} (suc zero) zero) )) )

consAtL :  {n}  Fin n  Fin n  Fin n  Formula S n
consAtL e' m e = liftFo (consAt e' m e) (bddCons e' m e)

consAtL-adequate :  {n} (e' m e : Fin n) (γ : S ^ n)
  {k : } (g : Fin k  V )
   fst (lookup e γ)  env g
   (γ  consAtL e' m e)
   PairIs (fst (lookup e' γ)) (env (cons (fst (lookup m γ)) g))
consAtL-adequate e' m e γ g hE =
    transferFo (consAt e' m e) (bddCons e' m e) (Δ₀-consAt e' m e) γ
   consAt-adequate e' m e (map fst γ) g
      (lookup-fst e γ  hE)
   cong₂ PairIs (lookup-fst e' γ)
      (cong  w  env (cons w g)) (lookup-fst m γ))

consAtL-transport :  {n n'} (γ : S ^ n) (γ' : S ^ n')
                    (e₁ m₁ d₁ : Fin n) (e₂ m₂ d₂ : Fin n')
                    {k : } (g : Fin k  V )
                   fst (lookup d₁ γ)  env g
                   fst (lookup e₁ γ)  fst (lookup e₂ γ')
                   fst (lookup m₁ γ)  fst (lookup m₂ γ')
                   fst (lookup d₁ γ)  fst (lookup d₂ γ')
                    γ  consAtL e₁ m₁ d₁    γ'  consAtL e₂ m₂ d₂ 
consAtL-transport γ γ' e₁ m₁ d₁ e₂ m₂ d₂ g hE qe qm qd h =
  subst ⟨_⟩ (sym (consAtL-adequate e₂ m₂ d₂ γ' g (sym qd  hE)))
    (subst2  p q   PairIs p (env (cons q g)) ) qe qm
      (subst ⟨_⟩ (consAtL-adequate e₁ m₁ d₁ γ g hE) h))

The unbounded quantifiers

An environment satisfies an existential exactly when some value from the structure, pushed onto the front, gives an environment satisfying the body, and the body's value is recorded one arity higher. So the clause binds the value at the next arity, binds the ambient set at its own arity, and then describes its own value by extension: the environments in the ambient set that can be extended into the body's.

Nine things are in scope by the innermost point, which is the deepest the chapter goes, and every one of them was needed: the code and its parts from the frame, the two values, the environment being classified, the value pushed on, and the extended environment. The universal clause turns the two innermost quantifiers around, each taking the connective its form asks for: a conjunction under the existential, an implication under the universal.

Nothing else moves, and the outermost conjunct in particular does not. The one that puts the environment in the ambient set is a conjunction in both, as it is in every clause written in this frame, and the reason is worth stating because getting it wrong is not a wrong clause but an unsatisfiable one. extAt makes a value the set of exactly what its condition holds of; a condition that could hold outside the ambient set would be asking for a value that is not a set.

module _ {n : } where
  private
    sh6' : Fin n  Fin (6 + n)
    sh6' i = suc (suc (suc (suc (suc (suc i)))))

    sh7' : Fin n  Fin (7 + n)
    sh7' i = suc (suc (suc (suc (suc (suc (suc i))))))

    ar6' a6' yc6' ya6' E6' : Fin (6 + n)
    ar6' = suc (suc (suc (suc zero)))
    a6'  = suc (suc (suc zero))
    yc6' = suc (suc zero)
    ya6' = suc zero
    E6'  = zero

    -- at the innermost point: e' = 0, m = 1, e = 2, E = 3, ya = 4
  body∃ body∀ : Fin n  Formula S (7 + n)
  body∃ B = (var zero ∈̇ var (suc zero))
            ∧̇ ∃̇∈ (var (sh7' B)) (∃̇
                ( consAtL zero (suc zero) (suc (suc zero))
                ∧̇ (var zero ∈̇ var (suc (suc (suc (suc zero))))) ))
  body∀ B = (var zero ∈̇ var (suc zero))
            ∧̇ ∀̇∈ (var (sh7' B)) (∀̇
                ( consAtL zero (suc zero) (suc (suc zero))
                ⇒̇ (var zero ∈̇ var (suc (suc (suc (suc zero))))) ))

  QuantWit : Fin n  S ^ (7 + n)  Type (ℓ-suc )
  QuantWit B γ = Σ[ x  S ] ( fst x  fst (lookup (sh7' B) γ) 
    × (Σ[ e'  S ] ( (e'  x  γ)  consAtL zero (suc zero) (suc (suc zero)) 
                    ×  fst e'  fst (lookup (suc (suc zero)) γ) )))

  body∃-in : (B : Fin n) (γ : S ^ (7 + n))
             fst (lookup zero γ)  fst (lookup (suc zero) γ) 
             QuantWit B γ ∥₁   γ  body∃ B 
  body∃-in B γ h k =
    h , PT.map  { (x , (x∈ , (e' , r)))  x , (x∈ ,  e' , r ∣₁) }) k

  body∃-out : (B : Fin n) (γ : S ^ (7 + n))   γ  body∃ B 
              fst (lookup zero γ)  fst (lookup (suc zero) γ) 
            ×  QuantWit B γ ∥₁
  body∃-out B γ h = h .fst , PT.rec squash₁
     { (x , (x∈ , hv))  PT.map  { (e' , r)  x , (x∈ , (e' , r)) }) hv })
    (h .snd)

  body∀-in : (B : Fin n) (γ : S ^ (7 + n))
             fst (lookup zero γ)  fst (lookup (suc zero) γ) 
            ((x e' : S)   fst x  fst (lookup (sh7' B) γ) 
                (e'  x  γ)  consAtL zero (suc zero) (suc (suc zero)) 
                fst e'  fst (lookup (suc (suc zero)) γ) )
             γ  body∀ B 
  body∀-in B γ h k = h ,  x x∈ e' hc  k x e' x∈ hc)

  body∀-out : (B : Fin n) (γ : S ^ (7 + n))   γ  body∀ B 
              fst (lookup zero γ)  fst (lookup (suc zero) γ) 
            × ((x e' : S)   fst x  fst (lookup (sh7' B) γ) 
                 (e'  x  γ)  consAtL zero (suc zero) (suc (suc zero)) 
                 fst e'  fst (lookup (suc (suc zero)) γ) )
  body∀-out B γ h = h .fst ,  x e' x∈ hc  h .snd x x∈ e' hc)

  quantRel : Fin n  Fin n  Formula S (7 + n)  Formula S (4 + n)
  quantRel T B body =
      ∀̇ (∀̇ ( subValSuccAt (sh6' T) ar6' a6' ya6'
           ⇒̇ ( envSetAt E6' ar6' (sh6' B)
           ⇒̇ extAt yc6' body )))

  existClauseAt : Fin n  Fin n  Fin n  Formula S n
  existClauseAt C T B = unClauseAt C T 8 (quantRel T B (body∃ B))

  forallClauseAt : Fin n  Fin n  Fin n  Formula S n
  forallClauseAt C T B = unClauseAt C T 9 (quantRel T B (body∀ B))

The quantifier clauses read the same way, and the tag and the body are what a caller supplies, so one pair of readers serves both. The subvalue sits an arity up, which is the only difference from negation.

  quantClause-out : (C T B : Fin n) (k : ) (body : Formula S (7 + n)) (γ : S ^ n)
      γ  unClauseAt C T k (quantRel T B body) 
     (c ar a yc ya E : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (fst a))
      pr (fst c) (fst yc)  fst (lookup T γ) 
      pr (pr (sucV (fst ar)) (fst a)) (fst ya)  fst (lookup T γ) 
      (E  ya  yc  a  ar  c  γ)  envSetAt E6' ar6' (sh6' B) 
      (E  ya  yc  a  ar  c  γ)  extAt yc6' body 
  quantClause-out C T B k body γ h c ar a yc ya E c∈ sh hc ha hE =
    unClause-out C T k (quantRel T B body) γ h c ar a yc c∈ sh hc ya E
      (subst ⟨_⟩ (sym (subValSuccAt-adequate (sh6' T) ar6' a6' ya6' δ)) ha) hE
    where
    δ : S ^ (6 + n)
    δ = E  ya  yc  a  ar  c  γ

  quantClause-in : (C T B : Fin n) (k : ) (body : Formula S (7 + n)) (γ : S ^ n)
     ((c ar a yc ya E : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (fst a))
         pr (fst c) (fst yc)  fst (lookup T γ) 
         pr (pr (sucV (fst ar)) (fst a)) (fst ya)  fst (lookup T γ) 
         (E  ya  yc  a  ar  c  γ)  envSetAt E6' ar6' (sh6' B) 
         (E  ya  yc  a  ar  c  γ)  extAt yc6' body )
      γ  unClauseAt C T k (quantRel T B body) 
  quantClause-in C T B k body γ g = unClause-in C T k (quantRel T B body) γ
     c ar a yc c∈ sh hc ya E ha hE 
      g c ar a yc ya E c∈ sh hc
        (subst ⟨_⟩ (subValSuccAt-adequate (sh6' T) ar6' a6' ya6'
          (E  ya  yc  a  ar  c  γ)) ha) hE)

Evaluating a term, and the atoms

The last thing the chapter lacked, and the place a wrong sentence sat for a day. A term is a variable or a constant, so a reader for its value has two cases, not one: a variable's code is the variable tag over a key and its value is what the environment records at that key; a constant's code is the constant tag over the constant itself, and its value is that, in any environment at all.

The one-case version was written when the alphabet was empty, and the sentence that justified it, "a term of a parameter-free formula is a variable", stayed true of the alphabet and stopped being true of the chapter. What made it a defect rather than a gap is that this reader sits under extAt, which asserts both directions: a constant was not left unconstrained, its value was pinned to the empty set. And the case is the normal form rather than a corner, since relativization gives every bounded quantifier a constant bound.

So the reader is stated with a characterization this time, in both directions, which is what makes the shape of the defect impossible to reintroduce silently.

The atoms then read both sides and compare them. Their payload is a pair of term codes, at which the table has nothing, which is why the frame was made not to look there; here is where that pays. The two atoms differ in one atom of the object language, membership against equality, so they share everything else.

tmValAt :  {n}  Fin n  Fin n  Fin n  Formula S n
tmValAt t e v = ∃̇ (tagAtL (suc t) 1 zero ∧̇ appAt (suc e) zero (suc v))
              ∨̇ tagAtL t 0 v

module _ {n : } (t e v : Fin n) (γ : S ^ n) where
  private
    T = fst (lookup t γ)
    Val = fst (lookup v γ)
    Env = fst (lookup e γ)

    Var : Type (ℓ-suc )
    Var = Σ[ k  S ] ((T  pr (# 1) (fst k)) ×  pr (fst k) Val  Env )

    Con : Type (ℓ-suc )
    Con = T  pr (# 0) Val

  tmValAt-var : (k : S)  T  pr (# 1) (fst k)   pr (fst k) Val  Env 
                γ  tmValAt t e v 
  tmValAt-var k q m =  inl  k
    , ( subst ⟨_⟩ (sym (tagAtL-adequate (suc t) 1 zero (k  γ))) q
      , subst ⟨_⟩ (sym (appAt-adequate (suc e) zero (suc v) (k  γ))) m ) ∣₁ ∣₁

  tmValAt-con : T  pr (# 0) Val   γ  tmValAt t e v 
  tmValAt-con q =  inr (subst ⟨_⟩ (sym (tagAtL-adequate t 0 v γ)) q) ∣₁

  tmValAt-out :  γ  tmValAt t e v    (Var  Con) ∥₁
  tmValAt-out = PT.rec squash₁
     { (inl h)  PT.map
            { (k , (ht , hm))  inl (k
             , ( subst ⟨_⟩ (tagAtL-adequate (suc t) 1 zero (k  γ)) ht
               , subst ⟨_⟩ (appAt-adequate (suc e) zero (suc v) (k  γ)) hm )) })
           h
       ; (inr h)   inr (subst ⟨_⟩ (tagAtL-adequate t 0 v γ) h) ∣₁ })

module _ {n : } where
  private
    sh6″ : Fin n  Fin (6 + n)
    sh6″ i = suc (suc (suc (suc (suc (suc i)))))

    ar6″ yc6″ E6″ : Fin (6 + n)
    ar6″ = suc (suc (suc (suc zero)))
    yc6″ = suc zero
    E6″  = zero

    -- at the innermost point: w = 0, v = 1, e = 2, E = 3, yc = 4, b = 5, a = 6
    a9″ b9″ e9″ v9″ w9″ : Fin (9 + n)
    a9″ = suc (suc (suc (suc (suc (suc zero)))))
    b9″ = suc (suc (suc (suc (suc zero))))
    e9″ = suc (suc zero)
    v9″ = suc zero
    w9″ = zero

  atomBody : Formula S (9 + n)  Formula S (7 + n)
  atomBody cmp =
      (var zero ∈̇ var (suc zero))
      ∧̇ ∃̇ (∃̇ ( tmValAt a9″ e9″ v9″
             ∧̇ ( tmValAt b9″ e9″ w9″
             ∧̇ cmp )))

  atomRel : Fin n  Formula S (9 + n)  Formula S (5 + n)
  atomRel B cmp =
      ∀̇ ( envSetAt E6″ ar6″ (sh6″ B) ⇒̇ extAt yc6″ (atomBody cmp) )

  AtomWit : Formula S (9 + n)  S ^ (7 + n)  Type (ℓ-suc )
  AtomWit cmp γ = Σ[ v  S ] (Σ[ w  S ]
    ( (w  v  γ)  tmValAt a9″ e9″ v9″ 
     × ( (w  v  γ)  tmValAt b9″ e9″ w9″  ×  (w  v  γ)  cmp )))

  atomBody-in : (cmp : Formula S (9 + n)) (γ : S ^ (7 + n))
                fst (lookup zero γ)  fst (lookup (suc zero) γ) 
                AtomWit cmp γ ∥₁   γ  atomBody cmp 
  atomBody-in cmp γ h k =
    h , PT.map  { (v , (w , r))  v ,  w , r ∣₁ }) k

  atomBody-out : (cmp : Formula S (9 + n)) (γ : S ^ (7 + n))
                 γ  atomBody cmp 
                 fst (lookup zero γ)  fst (lookup (suc zero) γ) 
               ×  AtomWit cmp γ ∥₁
  atomBody-out cmp γ h =
    h .fst , PT.rec squash₁  { (v , hv) 
      PT.map  { (w , r)  v , (w , r) }) hv }) (h .snd)

  memRel eqRel : Formula S (9 + n)
  memRel = var v9″ ∈̇ var w9″
  eqRel  = var v9″  var w9″

  memClauseAt : Fin n  Fin n  Fin n  Formula S n
  memClauseAt C T B = binClauseAt C T 0 (atomRel B memRel)

  eqClauseAt : Fin n  Fin n  Fin n  Formula S n
  eqClauseAt C T B = binClauseAt C T 1 (atomRel B eqRel)
  atomClause-out : (C T B : Fin n) (k : ) (cmp : Formula S (9 + n)) (γ : S ^ n)
      γ  binClauseAt C T k (atomRel B cmp) 
     (c ar a b yc E : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
      pr (fst c) (fst yc)  fst (lookup T γ) 
      (E  yc  b  a  ar  c  γ)  envSetAt E6″ ar6″ (sh6″ B) 
      (E  yc  b  a  ar  c  γ)  extAt yc6″ (atomBody cmp) 
  atomClause-out C T B k cmp γ h c ar a b yc E c∈ sh hc hE =
    binClause-out C T k (atomRel B cmp) γ h c ar a b yc c∈ sh hc E hE

  atomClause-in : (C T B : Fin n) (k : ) (cmp : Formula S (9 + n)) (γ : S ^ n)
     ((c ar a b yc E : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
         pr (fst c) (fst yc)  fst (lookup T γ) 
         (E  yc  b  a  ar  c  γ)  envSetAt E6″ ar6″ (sh6″ B) 
         (E  yc  b  a  ar  c  γ)  extAt yc6″ (atomBody cmp) )
      γ  binClauseAt C T k (atomRel B cmp) 
  atomClause-in C T B k cmp γ g = binClause-in C T k (atomRel B cmp) γ
     c ar a b yc c∈ sh hc E hE  g c ar a b yc E c∈ sh hc hE)

The bounded quantifiers

The last two, and they need nothing new. A bounded quantifier's payload is a term code paired with a formula code, so the bound is evaluated in the environment and the body's value is read one arity higher; then the values pushed on are the ones lying in both the carrier and the bound, and the extended environments are looked for in the body's value.

Ranging over the carrier as well as the bound is not redundant. The reference semantics quantifies over the carrier and guards by membership in the bound, and a bound may perfectly well have members outside the carrier; quantifying over the bound alone would then demand entries the table does not have.

Every piece has appeared: the next-arity lookup for the body, the ambient set for the extension frame, term evaluation for the bound, and environment extension for the step. The two differ, as the unbounded pair did, only in which quantifier each of the three innermost binders carries.

module _ {n : } where
  private
    sh7B : Fin n  Fin (7 + n)
    sh7B i = suc (suc (suc (suc (suc (suc (suc i))))))

    -- at depth 7: E = 0, yb = 1, yc = 2, b = 3, a = 4, ar = 5, c = 6
    ar7B b7B yc7B yb7B E7B : Fin (7 + n)
    ar7B = suc (suc (suc (suc (suc zero))))
    b7B  = suc (suc (suc zero))
    yc7B = suc (suc zero)
    yb7B = suc zero
    E7B  = zero

    -- at depth 9: w = 0, e = 1, a = 6
    a9B e9B w9B : Fin (9 + n)
    a9B = suc (suc (suc (suc (suc (suc zero)))))
    e9B = suc zero
    w9B = zero

    -- at depth 11: e' = 0, m = 1, e = 3, yb = 5
    e'11 m11 e11 yb11 : Fin (11 + n)
    e'11 = zero
    m11  = suc zero
    e11  = suc (suc (suc zero))
    yb11 = suc (suc (suc (suc (suc zero))))

    sh9B : Fin n  Fin (9 + n)
    sh9B i = suc (suc (suc (suc (suc (suc (suc (suc (suc i))))))))

    -- inside the bound's quantifier, at depth 10: m = 0, w = 1
  bodyAll bodyEx : Fin n  Formula S (8 + n)
  bodyAll B = (var zero ∈̇ var (suc zero))
              ∧̇ ∀̇ ( tmValAt a9B e9B w9B
                  ⇒̇ ∀̇∈ (var (sh9B B))
                      ( (var zero ∈̇ var (suc zero))
                      ⇒̇ ∀̇ ( consAtL e'11 m11 e11
                          ⇒̇ (var e'11 ∈̇ var yb11) )))
  bodyEx  B = (var zero ∈̇ var (suc zero))
              ∧̇ ∃̇ ( tmValAt a9B e9B w9B
                  ∧̇ ∃̇∈ (var (sh9B B))
                      ( (var zero ∈̇ var (suc zero))
                      ∧̇ ∃̇ ( consAtL e'11 m11 e11
                          ∧̇ (var e'11 ∈̇ var yb11) )))

  BndWit : Fin n  S ^ (8 + n)  S  Type (ℓ-suc )
  BndWit B γ w = Σ[ x  S ] (( fst x  fst (lookup (sh9B B) (w  γ)) 
    ×  fst x  fst w )
    × (Σ[ e'  S ] ( (e'  x  w  γ)  consAtL e'11 m11 e11 
                    ×  fst e'  fst (lookup (suc (suc zero)) γ) )))

  bodyEx-in : (B : Fin n) (γ : S ^ (8 + n))
              fst (lookup zero γ)  fst (lookup (suc zero) γ) 
              (Σ[ w  S ] ( (w  γ)  tmValAt a9B e9B w9B 
                             ×  BndWit B γ w ∥₁)) ∥₁
              γ  bodyEx B 
  bodyEx-in B γ h k = h , PT.map
     { (w , (hw , hx))  w , (hw , PT.map
       { (x , ((x∈B , x∈w) , (e' , r)))  x , (x∈B , (x∈w ,  e' , r ∣₁)) })
      hx) }) k

  bodyEx-out : (B : Fin n) (γ : S ^ (8 + n))   γ  bodyEx B 
               fst (lookup zero γ)  fst (lookup (suc zero) γ) 
             ×  (Σ[ w  S ] ( (w  γ)  tmValAt a9B e9B w9B 
                              ×  BndWit B γ w ∥₁)) ∥₁
  bodyEx-out B γ h = h .fst , PT.map
     { (w , (hw , hx))  w , (hw , PT.rec squash₁
       { (x , (x∈B , (x∈w , hv)))  PT.map
         { (e' , r)  x , ((x∈B , x∈w) , (e' , r)) }) hv })
      hx) }) (h .snd)

  bodyAll-in : (B : Fin n) (γ : S ^ (8 + n))
               fst (lookup zero γ)  fst (lookup (suc zero) γ) 
              ((w : S)   (w  γ)  tmValAt a9B e9B w9B 
                 (x e' : S)   fst x  fst (lookup (sh9B B) (w  γ)) 
                  fst x  fst w 
                  (e'  x  w  γ)  consAtL e'11 m11 e11 
                  fst e'  fst (lookup (suc (suc zero)) γ) )
               γ  bodyAll B 
  bodyAll-in B γ h k =
    h ,  w hw x x∈B x∈w e' hc  k w hw x e' x∈B x∈w hc)

  bodyAll-out : (B : Fin n) (γ : S ^ (8 + n))   γ  bodyAll B 
                fst (lookup zero γ)  fst (lookup (suc zero) γ) 
              × ((w : S)   (w  γ)  tmValAt a9B e9B w9B 
                  (x e' : S)   fst x  fst (lookup (sh9B B) (w  γ)) 
                   fst x  fst w 
                   (e'  x  w  γ)  consAtL e'11 m11 e11 
                   fst e'  fst (lookup (suc (suc zero)) γ) )
  bodyAll-out B γ h =
    h .fst ,  w hw x e' x∈B x∈w hc  h .snd w hw x x∈B x∈w e' hc)

  bndRel : Fin n  Fin n  Formula S (8 + n)  Formula S (5 + n)
  bndRel T B body =
      ∀̇ (∀̇ ( subValSuccAt (sh7B T) ar7B b7B yb7B
           ⇒̇ ( envSetAt E7B ar7B (sh7B B)
           ⇒̇ extAt yc7B body )))

  allInClauseAt : Fin n  Fin n  Fin n  Formula S n
  allInClauseAt C T B = binClauseAt C T 10 (bndRel T B (bodyAll B))

  exInClauseAt : Fin n  Fin n  Fin n  Formula S n
  exInClauseAt C T B = binClauseAt C T 11 (bndRel T B (bodyEx B))
  bndClause-out : (C T B : Fin n) (k : ) (body : Formula S (8 + n)) (γ : S ^ n)
      γ  binClauseAt C T k (bndRel T B body) 
     (c ar a b yc yb E : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
      pr (fst c) (fst yc)  fst (lookup T γ) 
      pr (pr (sucV (fst ar)) (fst b)) (fst yb)  fst (lookup T γ) 
      (E  yb  yc  b  a  ar  c  γ)  envSetAt E7B ar7B (sh7B B) 
      (E  yb  yc  b  a  ar  c  γ)  extAt yc7B body 
  bndClause-out C T B k body γ h c ar a b yc yb E c∈ sh hc hb hE =
    binClause-out C T k (bndRel T B body) γ h c ar a b yc c∈ sh hc yb E
      (subst ⟨_⟩ (sym (subValSuccAt-adequate (sh7B T) ar7B b7B yb7B δ)) hb) hE
    where
    δ : S ^ (7 + n)
    δ = E  yb  yc  b  a  ar  c  γ

  bndClause-in : (C T B : Fin n) (k : ) (body : Formula S (8 + n)) (γ : S ^ n)
     ((c ar a b yc yb E : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
         pr (fst c) (fst yc)  fst (lookup T γ) 
         pr (pr (sucV (fst ar)) (fst b)) (fst yb)  fst (lookup T γ) 
         (E  yb  yc  b  a  ar  c  γ)  envSetAt E7B ar7B (sh7B B) 
         (E  yb  yc  b  a  ar  c  γ)  extAt yc7B body )
      γ  binClauseAt C T k (bndRel T B body) 
  bndClause-in C T B k body γ g = binClause-in C T k (bndRel T B body) γ
     c ar a b yc c∈ sh hc yb E hb hE 
      g c ar a b yc yb E c∈ sh hc
        (subst ⟨_⟩ (subValSuccAt-adequate (sh7B T) ar7B b7B yb7B
          (E  yb  yc  b  a  ar  c  γ)) hb) hE)

A domain that is closed under subcodes

The clauses above constrain a table wherever both a code and its subcodes carry entries, and say nothing where the subcodes do not. That is the right reading, and it is also the reason a table satisfying all twelve can be almost empty: take the index set to be one compound code and the table one entry there, with any value at all. The eight clauses that consult a subcode go vacuous because the subcodes carry no entry, and the four that do not consult one, the two atoms and the two constants, go vacuous because the index holds nothing of their shape. So the clauses alone do not pin a value, and what pins it is a further demand on the index set, that it contain the subcodes of everything in it. Compound matters: put the one entry at a constant's code instead and the clause for ⊥̇ pins the value outright, which is the shape of the whole argument in miniature.

Stating that demand needs the same two frames as the clauses, minus the table. What is left is the shape reader and the implication: for every key in the set of that shape, such and such keys are in the set too. A key is an arity paired with a code, so a subkey is built from the same arity, or from its successor for the four constructors that bind a variable, and appAt is already the reader for "this pair is in that set".

Eight of the twelve say something. The two atoms have term codes below them and the two constants have a numeral, and none of the four has a subformula, so their clauses would be empty and are not written.

module _ {n : } where
  private
    sh4 : Fin n  Fin (4 + n)
    sh4 i = suc (suc (suc (suc i)))

    c4 n4 a4 b4 : Fin (4 + n)
    c4 = suc (suc (suc zero))
    n4 = suc (suc zero)
    a4 = suc zero
    b4 = zero

    sh3 : Fin n  Fin (3 + n)
    sh3 i = suc (suc (suc i))

    c3 n3 a3 : Fin (3 + n)
    c3 = suc (suc zero)
    n3 = suc zero
    a3 = zero

  binShapeAt : Fin n    Formula S (4 + n)  Formula S n
  binShapeAt C k rel =
    ∀̇∈ (var C) (∀̇ (∀̇ (∀̇ ( arityTagPairAtL c4 n4 k a4 b4 ⇒̇ rel))))

  unShapeAt : Fin n    Formula S (3 + n)  Formula S n
  unShapeAt C k rel =
    ∀̇∈ (var C) (∀̇ (∀̇ ( arityTagAtL c3 n3 k a3 ⇒̇ rel)))

  binShape-out : (C : Fin n) (k : ) (rel : Formula S (4 + n)) (γ : S ^ n)
      γ  binShapeAt C k rel 
     (c ar a b : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
      (b  a  ar  c  γ)  rel 
  binShape-out C k rel γ h c ar a b c∈ shape =
    h c c∈ ar a b
      (subst ⟨_⟩ (sym (arityTagPairAtL-adequate c4 n4 k a4 b4 (b  a  ar  c  γ)))
        shape)

  unShape-out : (C : Fin n) (k : ) (rel : Formula S (3 + n)) (γ : S ^ n)
      γ  unShapeAt C k rel 
     (c ar a : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (fst a))
      (a  ar  c  γ)  rel 
  unShape-out C k rel γ h c ar a c∈ shape =
    h c c∈ ar a
      (subst ⟨_⟩ (sym (arityTagAtL-adequate c3 n3 k a3 (a  ar  c  γ))) shape)

Four relations, and they divide the eight the way the arities do. The three binary connectives want both components at the arity they were read at. Negation wants its one component there. The two unbounded quantifiers want their one component one arity up, which is an existential over the successor, and the two bounded ones want their second component there, the first being a term.

  bothSameAt : Fin n  Formula S (4 + n)
  bothSameAt C = appAt (sh4 C) n4 a4 ∧̇ appAt (sh4 C) n4 b4

  oneSameAt : Fin n  Formula S (3 + n)
  oneSameAt C = appAt (sh3 C) n3 a3

  oneSuccAt : Fin n  Formula S (3 + n)
  oneSuccAt C = ∃̇ (sucAtL (suc n3) zero ∧̇ appAt (suc (sh3 C)) zero (suc a3))

  succSndAt : Fin n  Formula S (4 + n)
  succSndAt C = ∃̇ (sucAtL (suc n4) zero ∧̇ appAt (suc (sh4 C)) zero (suc b4))

Reading them back is what a consumer does, so each is stated at the clause, already composed with its frame: given a key of that shape in the set, the keys the constructor demands are in the set. The two that change arity discharge a truncation on the way, which the target admits because membership is a proposition.

  binSameClosed-out : (C : Fin n) (k : ) (γ : S ^ n)
      γ  binShapeAt C k (bothSameAt C) 
     (c ar a b : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
      pr (fst ar) (fst a)  fst (lookup C γ) 
    ×  pr (fst ar) (fst b)  fst (lookup C γ) 
  binSameClosed-out C k γ h c ar a b c∈ shape =
      subst ⟨_⟩ (appAt-adequate (sh4 C) n4 a4 δ) (r .fst)
    , subst ⟨_⟩ (appAt-adequate (sh4 C) n4 b4 δ) (r .snd)
    where
    δ : S ^ (4 + n)
    δ = b  a  ar  c  γ
    r = binShape-out C k (bothSameAt C) γ h c ar a b c∈ shape

  unSameClosed-out : (C : Fin n) (k : ) (γ : S ^ n)
      γ  unShapeAt C k (oneSameAt C) 
     (c ar a : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (fst a))
      pr (fst ar) (fst a)  fst (lookup C γ) 
  unSameClosed-out C k γ h c ar a c∈ shape =
    subst ⟨_⟩ (appAt-adequate (sh3 C) n3 a3 (a  ar  c  γ))
      (unShape-out C k (oneSameAt C) γ h c ar a c∈ shape)

  unSuccClosed-out : (C : Fin n) (k : ) (γ : S ^ n)
      γ  unShapeAt C k (oneSuccAt C) 
     (c ar a : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (fst a))
      pr (sucV (fst ar)) (fst a)  fst (lookup C γ) 
  unSuccClosed-out C k γ h c ar a c∈ shape =
    PT.rec (snd target)
       { (z , (sz , ap)) 
        subst  w   pr w (fst a)  fst (lookup C γ) )
          (subst ⟨_⟩ (sucAtL-adequate (suc n3) zero (z  δ)) sz)
          (subst ⟨_⟩ (appAt-adequate (suc (sh3 C)) zero (suc a3) (z  δ)) ap) })
      (unShape-out C k (oneSuccAt C) γ h c ar a c∈ shape)
    where
    δ : S ^ (3 + n)
    δ = a  ar  c  γ
    target = pr (sucV (fst ar)) (fst a)  fst (lookup C γ)

  binSuccClosed-out : (C : Fin n) (k : ) (γ : S ^ n)
      γ  binShapeAt C k (succSndAt C) 
     (c ar a b : S)
      fst c  fst (lookup C γ) 
     fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
      pr (sucV (fst ar)) (fst b)  fst (lookup C γ) 
  binSuccClosed-out C k γ h c ar a b c∈ shape =
    PT.rec (snd target)
       { (z , (sz , ap)) 
        subst  w   pr w (fst b)  fst (lookup C γ) )
          (subst ⟨_⟩ (sucAtL-adequate (suc n4) zero (z  δ)) sz)
          (subst ⟨_⟩ (appAt-adequate (suc (sh4 C)) zero (suc b4) (z  δ)) ap) })
      (binShape-out C k (succSndAt C) γ h c ar a b c∈ shape)
    where
    δ : S ^ (4 + n)
    δ = b  a  ar  c  γ
    target = pr (sucV (fst ar)) (fst b)  fst (lookup C γ)

The eight clauses, and their conjunction. A consumer takes the conjunct it wants and hands it to the reader that goes with it; nothing else is needed, which is why the eight are written without a module around them.

  andClosedAt orClosedAt impClosedAt negClosedAt : Fin n  Formula S n
  existClosedAt forallClosedAt allInClosedAt exInClosedAt : Fin n  Formula S n

  andClosedAt    C = binShapeAt C 2 (bothSameAt C)
  orClosedAt     C = binShapeAt C 3 (bothSameAt C)
  impClosedAt    C = binShapeAt C 4 (bothSameAt C)
  negClosedAt    C = unShapeAt  C 5 (oneSameAt C)
  existClosedAt  C = unShapeAt  C 8 (oneSuccAt C)
  forallClosedAt C = unShapeAt  C 9 (oneSuccAt C)
  allInClosedAt  C = binShapeAt C 10 (succSndAt C)
  exInClosedAt   C = binShapeAt C 11 (succSndAt C)

  closedAt : Fin n  Formula S n
  closedAt C =
    andClosedAt C ∧̇ (orClosedAt C ∧̇ (impClosedAt C ∧̇ (negClosedAt C
      ∧̇ (existClosedAt C ∧̇ (forallClosedAt C
      ∧̇ (allInClosedAt C ∧̇ exInClosedAt C))))))

The other direction, which the first instance needs and no clause needed. A consumer of a recursion reads its hypotheses; the meta-level set that will be handed to one has to satisfy them, so every frame and every relation is owed an introduction as well as an elimination. Both frames introduce by a lambda, since a bounded universal over the model is a function on members and the implication is a function on the reader's proof. The two arity-raising relations build the successor as an element of the model, which the numeral chapter supplies.

  binShape-in : (C : Fin n) (k : ) (rel : Formula S (4 + n)) (γ : S ^ n)
     ((c ar a b : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
         (b  a  ar  c  γ)  rel )
      γ  binShapeAt C k rel 
  binShape-in C k rel γ g c c∈ ar a b sh =
    g c ar a b c∈
      (subst ⟨_⟩ (arityTagPairAtL-adequate c4 n4 k a4 b4 (b  a  ar  c  γ)) sh)

  unShape-in : (C : Fin n) (k : ) (rel : Formula S (3 + n)) (γ : S ^ n)
     ((c ar a : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (fst a))
         (a  ar  c  γ)  rel )
      γ  unShapeAt C k rel 
  unShape-in C k rel γ g c c∈ ar a sh =
    g c ar a c∈
      (subst ⟨_⟩ (arityTagAtL-adequate c3 n3 k a3 (a  ar  c  γ)) sh)

  binSameClosed-in : (C : Fin n) (k : ) (γ : S ^ n)
     ((c ar a b : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
         pr (fst ar) (fst a)  fst (lookup C γ) 
       ×  pr (fst ar) (fst b)  fst (lookup C γ) )
      γ  binShapeAt C k (bothSameAt C) 
  binSameClosed-in C k γ g = binShape-in C k (bothSameAt C) γ
     c ar a b c∈ sh 
        subst ⟨_⟩ (sym (appAt-adequate (sh4 C) n4 a4 (b  a  ar  c  γ)))
          (g c ar a b c∈ sh .fst)
      , subst ⟨_⟩ (sym (appAt-adequate (sh4 C) n4 b4 (b  a  ar  c  γ)))
          (g c ar a b c∈ sh .snd))

  unSameClosed-in : (C : Fin n) (k : ) (γ : S ^ n)
     ((c ar a : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (fst a))
         pr (fst ar) (fst a)  fst (lookup C γ) )
      γ  unShapeAt C k (oneSameAt C) 
  unSameClosed-in C k γ g = unShape-in C k (oneSameAt C) γ
     c ar a c∈ sh 
      subst ⟨_⟩ (sym (appAt-adequate (sh3 C) n3 a3 (a  ar  c  γ)))
        (g c ar a c∈ sh))

  unSuccClosed-in : (C : Fin n) (k : ) (γ : S ^ n)
     ((c ar a : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (fst a))
         pr (sucV (fst ar)) (fst a)  fst (lookup C γ) )
      γ  unShapeAt C k (oneSuccAt C) 
  unSuccClosed-in C k γ g = unShape-in C k (oneSuccAt C) γ
     c ar a c∈ sh   sucʟ ar
      , ( subst ⟨_⟩ (sym (sucAtL-adequate (suc n3) zero
            (sucʟ ar  a  ar  c  γ))) (sucʟ-fst ar)
        , subst ⟨_⟩ (sym (appAt-adequate (suc (sh3 C)) zero (suc a3)
            (sucʟ ar  a  ar  c  γ)))
            (subst  w   pr w (fst a)  fst (lookup C γ) )
              (sym (sucʟ-fst ar)) (g c ar a c∈ sh)) ) ∣₁)

  binSuccClosed-in : (C : Fin n) (k : ) (γ : S ^ n)
     ((c ar a b : S)
         fst c  fst (lookup C γ) 
        fst c  pr (fst ar) (pr (# k) (pr (fst a) (fst b)))
         pr (sucV (fst ar)) (fst b)  fst (lookup C γ) )
      γ  binShapeAt C k (succSndAt C) 
  binSuccClosed-in C k γ g = binShape-in C k (succSndAt C) γ
     c ar a b c∈ sh   sucʟ ar
      , ( subst ⟨_⟩ (sym (sucAtL-adequate (suc n4) zero
            (sucʟ ar  b  a  ar  c  γ))) (sucʟ-fst ar)
        , subst ⟨_⟩ (sym (appAt-adequate (suc (sh4 C)) zero (suc b4)
            (sucʟ ar  b  a  ar  c  γ)))
            (subst  w   pr w (fst b)  fst (lookup C γ) )
              (sym (sucʟ-fst ar)) (g c ar a b c∈ sh)) ) ∣₁)

Recap

prAtL says, in the object language of the model, that one set is the ordered pair of two others, appAt that a function contains a given pair,

svAt that it contains at most one pair per argument, and

domAt that a given set is exactly the arguments it answers for. Together they are what "function" means in the object language, and every recursion graph is written through them. prʟ is the pair on the value side, so a construction can build a code as well as read one; and tagAtL and

tagPairAtL read a code's constructor, the second matching the shape every binary constructor's code has. envOverAt then says what it is to be an environment over a set.

extAt is the frame every set-valued clause is written in, the set operations are its shortest instances, and the recursion's clauses are written in two frames rather than twelve clauses: binClauseAt for the seven constructors whose payload is a pair, unClauseAt for the five whose payload is a single component, the constants included. Both read the key in two layers, arity outside and tag within, and both leave every lookup on a payload component to the relation handed to them, which performs it with

subValAt. All twelve are written out: the four connectives, the two constants, the two atoms, and the four quantifiers. Two frames, twelve relations, and five idioms among the relations. envSetAt is what the negative ones needed, and it makes the point the chapter turns on: inside a clause, the ambient set of environments is described rather than constructed.

closedAt is the demand the clauses cannot make: that the index set contain the subcodes of everything in it. Without it a table with one entry at a compound code satisfies all twelve clauses and no value is pinned, so it is not an optimization but the other half of the definition. Eight of the twelve constructors say something under it, and it reuses the two frames with the table struck out. It is the other half as the clauses are written: guarding a subvalue by a universal over the table is what makes a clause vacuous where the entry is missing, and demanding the subvalues existentially instead would pin the same values with no closedness predicate. That road was not taken, and the reason is that the demand belongs to the index set rather than to each of eight clauses.

Two roads were used and both belong here. A reader with no constants is quoted, which costs a four-link chain and no thought. A reader naming a numeral is written instead, because quoting it would thread a constructibility witness through the whole shape of the formula while writing it needs one unbounded existential, and unbounded is free. It was obtained by quoting, not by re-proving: the reader and its characterization stay where they were written, and the crossing cost one induction on environments.

That is the pattern for every reader that follows, and it is the reason the coding chapters did not have to be re-based. What it does not cover is any predicate that is not Δ₀, and those are to be written directly over the model instead, since nothing in the model's comprehension asks them to be bounded.