Cantor–Schröder–Bernstein inside L

Read this chapter directly, or use the reading guide and dependency map to choose another route.

Reading guide · Dependency map

Suppose two constructible sets admit coded injections in both directions. Their member types then admit a bijection, merely as an existence statement. This is the internal form of the Cantor–Schröder–Bernstein theorem used here: the hypotheses are expressed in the language of L, while the resulting bijection compares the ordinary types presenting the two sets.

The argument passes through two levels. A set of L carries an underlying set in the ambient cumulative hierarchy. Its members form an ordinary type, written ⟪ fst a ⟫; coded injections belong to the object theory, whereas functions between these member types belong to the metatheory.

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

open import Base.Prelude
open import Base.Classical using ( LEM; lowerLEM )

module L.CantorBernstein { : Level} (lem : LEM (ℓ-suc )) where

open import FOL.ZFStructure using ( module hPropStructure )

To apply the type-level theorem, each member type must be an h-set. The cumulative hierarchy already supplies this property: paths between two members carry no additional higher information. Thus setPL provides exactly the h-set certificate required for every presentation.

open import V.CantorBernstein {} (lowerLEM lem)
  using ( small-set; module MutualInj )
open import L.Constructible {} using ( 𝒮ʟ )
open import L.Cardinal {} lem using ( InjCode; InjL )
open import L.Coding.Injection {} lem using ( module Small )

An injection code consists of a constructible graph together with three satisfaction facts and one value-range condition. They say that the graph is single-valued, has the prescribed domain, is injective, and sends every input into the prescribed codomain. These conditions contain precisely the information needed to recover a metatheoretic injection.

open import Cubical.HITs.CumulativeHierarchy.Properties using ( ⟪_⟫ )
import Cubical.HITs.PropositionalTruncation as PT
open PT using ( ∥_∥₁ )

open hPropStructure 𝒮ʟ using ( S )
setPL : (a : S)  isSet ( fst a )

The function readL performs this passage. Given a coded graph from a to b, it returns an actual function from the members of a to the members of b, together with a proof that equal outputs have equal inputs. The construction itself is supplied by the preceding analysis of coded injections.

setPL a = small-set (fst a)
readL : (a b : S)  Σ[ F  S ] InjCode F a b
       Σ[ f  ( fst a    fst b ) ]
          ((x y :  fst a )  f x  f y  x  y)
readL a b (F , sv , dm , ij , ran) = SM.small , SM.small-inj

The abstract Cantor–Schröder–Bernstein argument can now be instantiated with constructible sets as objects, their member types as presentations, and coded graphs as injections. The h-set certificates and readL verify its two structural requirements. The same instantiation provides both a version for explicit witnesses and a version for merely existing witnesses.

  where
  module SM = Small F a b sv dm ij ran

module MutualInjL = MutualInj S  a   fst a )
   a b  Σ[ F  S ] InjCode F a b) setPL readL
mutual-inj→bijection : (a b : S)  InjL a b  InjL b a

The public theorem uses the second form because InjL records only the propositional truncation of an injection code. From the two truncated hypotheses it therefore derives a truncated bijection. Excluded middle is used inside the underlying type-level proof to separate the Cantor–Schröder–Bernstein construction into its cases; unique preimages are recovered from injectivity and the h-set condition, rather than from any choice principle.

    Σ[ h  ( fst a    fst b ) ]
       (((x y :  fst a )  h x  h y  x  y)
     × ((y :  fst b )   Σ[ x   fst a  ] (h x  y) ∥₁)) ∥₁
mutual-inj→bijection = MutualInjL.∃bijection