\begin{code} {-# OPTIONS --cubical --safe --postfix-projections #-} module Cardinality.Finite.Cardinal where open import Prelude open import Cardinality.Finite.ManifestBishop open import Cardinality.Finite.ManifestBishop.Inductive open import Cardinality.Finite.ManifestBishop.Isomorphism open import Cardinality.Finite.SplitEnumerable hiding (_|×|_) open import Cardinality.Finite.SplitEnumerable.Isomorphism open import HITs.PropositionalTruncation open import HITs.PropositionalTruncation.Sugar open import Relation.Nullary.Discrete.Properties open import Relation.Nullary.Decidable.Logic open import Data.Fin 𝒞 : Type a → Type a \end{code} %<*cardinal-def> \begin{code} 𝒞 A = ∥ ℬ A ∥ \end{code} %</cardinal-def> %<*no-gap-card-bishop> \begin{code} ¬⟨𝒞⋂ℬᶜ⟩ : ¬ Σ[ A ⦂ Type a ] 𝒞 A × ¬ ℬ A ¬⟨𝒞⋂ℬᶜ⟩ (_ , c , ¬b) = rec isProp⊥ ¬b c \end{code} %</no-gap-card-bishop> %<*refute-trunc-pair> \begin{code} ¬⟨∥A∥׬A⟩ : ¬ ∥ A ∥ × ¬ A ¬⟨∥A∥׬A⟩ (∣A∣ , ¬A) = rec isProp⊥ ¬A ∣A∣ \end{code} %</refute-trunc-pair> \begin{code} 𝒞≃Fin≃ : 𝒞 A ⇔ ∥ Σ[ n ⦂ ℕ ] (Fin n ≃ A) ∥ 𝒞≃Fin≃ = iso (ℬ⇔Fin≃ .fun ∘ 𝕃⇔ℒ⟨ℬ⟩ .fun ∥$∥_) (𝕃⇔ℒ⟨ℬ⟩ .inv ∘ ℬ⇔Fin≃ .inv ∥$∥_) (λ _ → squash _ _) λ _ → squash _ _ ℬ⇒𝒞 : ℬ A → 𝒞 A ℬ⇒𝒞 = ∣_∣ private variable u : Level U : A → Type u 𝒞⇒Choice : 𝒞 A → Π[ x ⦂ A ] ∥ U x ∥ → ∥ Π[ x ⦂ A ] U x ∥ 𝒞⇒Choice ca p = ca >>= flip ℬ⇒Choice p 𝒞⟨⊥⟩ : 𝒞 ⊥ 𝒞⟨⊥⟩ = ∣ ℰ!⇒ℬ ℰ!⟨⊥⟩ ∣ 𝒞⟨⊤⟩ : 𝒞 ⊤ 𝒞⟨⊤⟩ = ∣ ℰ!⇒ℬ ℰ!⟨⊤⟩ ∣ 𝒞⟨Bool⟩ : 𝒞 Bool 𝒞⟨Bool⟩ = ∣ ℰ!⇒ℬ ℰ!⟨2⟩ ∣ infixr 3 _∥Σ∥_ _∥Σ∥_ : 𝒞 A → (∀ x → 𝒞 (U x)) → 𝒞 (Σ A U) xs ∥Σ∥ ys = do x ← xs y ← ℬ⇒Choice x ys ∣ ℰ!⇒ℬ (ℬ⇒ℰ! x |Σ| (ℬ⇒ℰ! ∘ y)) ∣ _∥⊎∥_ : 𝒞 A → 𝒞 B → 𝒞 (A ⊎ B) xs ∥⊎∥ ys = do x ← xs y ← ys ∣ ℰ!⇒ℬ (ℬ⇒ℰ! x |⊎| ℬ⇒ℰ! y) ∣ _∥Π∥_ : 𝒞 A → (∀ x → 𝒞 (U x)) → 𝒞 (Π A U) xs ∥Π∥ ys = do x ← xs y ← ℬ⇒Choice x ys ∣ ℰ!⇒ℬ (ℬ⇒ℰ! x |Π| (ℬ⇒ℰ! ∘ y)) ∣ _∥→∥_ : 𝒞 A → 𝒞 B → 𝒞 (A → B) xs ∥→∥ ys = xs ∥Π∥ const ys open BishopClosures \end{code} %<*times-clos-impl> \begin{code} _∥×∥_ : 𝒞 A → 𝒞 B → 𝒞 (A × B) xs ∥×∥ ys = do x ← xs y ← ys ∣ x |×| y ∣ \end{code} %</times-clos-impl> \begin{code} 𝒞⇒Discrete : \end{code} %<*card-discrete> \begin{code} 𝒞 A → Discrete A \end{code} %</card-discrete> \begin{code} 𝒞⇒Discrete = rec isPropDiscrete (ℰ!⇒Discrete ∘ 𝕃⇔ℒ⟨ℰ!⟩ .fun ∘ ℬ⇒ℰ!) open import Data.Sigma.Properties open import Data.Fin.Properties using (Fin-inj) open import Data.Nat.Properties using (isSetℕ) open import Cubical.Foundations.HLevels cardinality : ∥ ∃[ n ] (Fin n ≃ A) ∥ → ∃[ n ] ∥ Fin n ≃ A ∥ cardinality {A = A} = rec→set card-isSet alg const-alg where card-isSet : isSet (∃[ n ] ∥ Fin n ≃ A ∥) card-isSet = isOfHLevelΣ 2 isSetℕ λ _ → isProp→isSet squash alg : Σ[ n ⦂ ℕ ] (Fin n ≃ A) → Σ[ n ⦂ ℕ ] ∥ Fin n ≃ A ∥ alg (n , f≃A) = n , ∣ f≃A ∣ const-alg : (x y : ∃[ n ] (Fin n ≃ A)) → alg x ≡ alg y const-alg (n , x) (m , y) = ΣProp≡ (λ _ → squash) {n , ∣ x ∣} {m , ∣ y ∣} (Fin-inj n m (ua (x ⟨ trans-≃ ⟩ (sym-≃ y)))) # : 𝒞 A → ℕ # = fst ∘ cardinality ∘ _∥$∥_ (ℬ⇔Fin≃ .fun ∘ 𝕃⇔ℒ⟨ℬ⟩ .fun) ∥map∥ : (A → B) → ∥ A ∥ → ∥ B ∥ ∥map∥ f = rec squash (∣_∣ ∘ f) module _ {a} {A : Type a} where \end{code} %<*cardinality-is-unique> \begin{code} cardinality-is-unique : 𝒞 A → ∃[ n ] ∥ Fin n ≃ A ∥ \end{code} %</cardinality-is-unique> %<*cardinality-is-unique-impl> \begin{code} cardinality-is-unique = rec→set card-isSet alg const-alg ∘ ∥map∥ ℬ⇒Fin≃ \end{code} %</cardinality-is-unique-impl> \begin{code} where \end{code} %<*card-isSet> \begin{code} card-isSet : isSet (∃[ n ] ∥ Fin n ≃ A ∥) \end{code} %</card-isSet> \begin{code} card-isSet = isOfHLevelΣ 2 isSetℕ λ _ → isProp→isSet squash \end{code} %<*alg> \begin{code} alg : Σ[ n ⦂ ℕ ] (Fin n ≃ A) → Σ[ n ⦂ ℕ ] ∥ Fin n ≃ A ∥ alg (n , f≃A) = n , ∣ f≃A ∣ \end{code} %</alg> %<*const-alg> \begin{code} const-alg : (x y : ∃[ n ] (Fin n ≃ A)) → alg x ≡ alg y \end{code} %</const-alg> \begin{code} const-alg (n , x) (m , y) = ΣProp≡ (λ _ → squash) {n , ∣ x ∣} {m , ∣ y ∣} (Fin-inj n m (ua (x ⟨ trans-≃ ⟩ (sym-≃ y)))) module _ {a b} {A : Type a} {B : Type b} where _∥⇔∥_ : 𝒞 A → 𝒞 B → 𝒞 (A ⇔ B) xs ∥⇔∥ ys = subst 𝒞 (isoToPath form) p where 𝒞⟨f⟩ : 𝒞 (A → B) 𝒞⟨f⟩ = xs ∥→∥ ys 𝒞⟨g⟩ : 𝒞 (B → A) 𝒞⟨g⟩ = ys ∥→∥ xs p : 𝒞 (Σ[ fg ⦂ ((A → B) × (B → A)) ] (((fg .fst ∘ fg .snd) ≡ id) × ((fg .snd ∘ fg .fst) ≡ id))) p = ℰ!⇒ℬ ∘ filter-subobject (λ fg → isOfHLevelΣ 1 (Discrete→isSet (𝒞⇒Discrete (ys ∥→∥ ys)) _ _) λ _ → (Discrete→isSet (𝒞⇒Discrete (xs ∥→∥ xs)) _ _)) (λ { (f , g) → 𝒞⇒Discrete (ys ∥→∥ ys) (f ∘ g) id && 𝒞⇒Discrete (xs ∥→∥ xs) (g ∘ f) id}) ∘ ℬ⇒ℰ! ∥$∥ (𝒞⟨f⟩ ∥×∥ 𝒞⟨g⟩) form : (Σ[ fg ⦂ ((A → B) × (B → A)) ] (((fg .fst ∘ fg .snd) ≡ id) × ((fg .snd ∘ fg .fst) ≡ id))) ⇔ (A ⇔ B) form .fun ((f , g) , (leftInv , rightInv)) = iso f g (λ x i → leftInv i x) (λ x i → rightInv i x) form .inv (iso f g leftInv rightInv) = ((f , g) , ((λ i x → leftInv x i) , (λ i x → rightInv x i))) form .rightInv _ = refl form .leftInv _ = refl open import Relation.Binary open import Data.List.Relation.Binary.Permutation perm-ℬ : \end{code} %<*perm-bish> \begin{code} (xs ys : ℬ A) → xs .fst ↭ ys .fst \end{code} %</perm-bish> \begin{code} perm-ℬ xs ys x .fun _ = ys .snd x .fst perm-ℬ xs ys x .inv _ = xs .snd x .fst perm-ℬ xs ys x .rightInv = ys .snd x .snd perm-ℬ xs ys x .leftInv = xs .snd x .snd module _ {e r} {E : Type e} (totalOrder : TotalOrder E r) where open import Data.List.Sort totalOrder open import HITs.PropositionalTruncation using (rec→set) open import Data.Sigma.Properties open import Cardinality.Finite.ManifestBishop using (ℰ!⇒ℬ) open import Cardinality.Finite.ManifestEnumerable.Inductive open import Cardinality.Finite.ManifestEnumerable 𝒞⇒ℬ : 𝒞 E → ℬ E 𝒞⇒ℬ xs = (ℰ!⇒ℬ ∘ ℰ⇒ℰ! discreteE ∘ rec→set (isSet⟨ℰ⟩ (Discrete→isSet discreteE)) alg const-alg) xs where discreteE = 𝒞⇒Discrete xs alg : ℬ E → ℰ E alg xs .fst = sort (xs .fst) alg xs .snd x = ∣ sort-perm (xs .fst) x .inv (xs .snd x .fst) ∣ const-alg : (xs ys : ℬ E) → alg xs ≡ alg ys const-alg xs ys = ΣProp≡ (λ _ → hLevelPi 1 (λ _ → squash)) (perm-invar (xs .fst) (ys .fst) (perm-ℬ xs ys)) open import Cardinality.Finite.SplitEnumerable using (ℰ!⟨≡⟩) 𝒞⟨≡⟩ : (x y : A) → 𝒞 A → 𝒞 (x ≡ y) 𝒞⟨≡⟩ x y ca = ℰ!⇒ℬ ∘ ℰ!⟨≡⟩ x y ∘ ℬ⇒ℰ! ∥$∥ ca \end{code}