An improved version of this note is at ObjectClassifiers.
open import 1Lab.Type
open import 1Lab.Type.Sigma
open import 1Lab.Type.Pointed
open import 1Lab.Path
open import 1Lab.HLevel
open import 1Lab.HLevel.Closure
open import 1Lab.Equiv
module ObjectClassifier where
Bundle : ∀ ℓ → Type (lsuc ℓ)
Bundle ℓ
  = Σ (Type ℓ) λ A
  → Σ (Type ℓ) λ B
  → A → B
record Pullback {ℓ ℓ'} {B : Type ℓ} {C D : Type ℓ'} (s : B → D) (q : C → D) : Type (ℓ ⊔ ℓ') where
  constructor pb
  field
    pb₁ : B
    pb₂ : C
    pbeq : s pb₁ ≡ q pb₂
open Pullback
pb-path : ∀ {ℓ ℓ'} {B : Type ℓ} {C D : Type ℓ'} {s : B → D} {q : C → D} → {a b : Pullback s q}
        → (p1 : a .pb₁ ≡ b .pb₁) → (p2 : a .pb₂ ≡ b .pb₂) → PathP (λ i → s (p1 i) ≡ q (p2 i)) (a .pbeq) (b .pbeq)
        → a ≡ b
pb-path p1 p2 pe i = pb (p1 i) (p2 i) (pe i)
_⇒_ : ∀ {ℓ} {ℓ'} → Bundle ℓ → Bundle ℓ' → Type (ℓ ⊔ ℓ')
(A , B , p) ⇒ (C , D , q)
  = Σ (B → D) λ s
  → Σ (A ≃ Pullback s q) λ e
  → p ≡ pb₁ ∘ e .fst
is-classifier : ∀ {ℓ} → Bundle (lsuc ℓ) → Type (lsuc ℓ)
is-classifier {ℓ} u = ∀ (p : Bundle ℓ) → is-contr (p ⇒ u)
Type↓ : ∀ ℓ → Bundle (lsuc ℓ)
Type↓ ℓ = Type∙ ℓ , Type ℓ , fst
Type↓-fibre : ∀ {ℓ} (A : Type ℓ) → A ≃ Pullback {B = Lift ℓ ⊤} {C = Type∙ ℓ} (λ _ → A) fst
Type↓-fibre A = Iso→Equiv λ where
  .fst a → pb _ (A , a) refl
  .snd .is-iso.from (pb _ (A' , a) eq) → transport (sym eq) a
  .snd .is-iso.linv → transport-refl
  .snd .is-iso.rinv (pb _ (A' , a) eq) → pb-path refl (sym (Σ-path (sym eq) refl)) λ i j → eq (i ∧ j)
postulate
  
  
  Type↓-is-classifier : ∀ {ℓ} → is-classifier (Type↓ ℓ)
! : ∀ {ℓ} → Type ℓ → Bundle ℓ
! A = A , Lift _ ⊤ , _
lemma : ∀ {ℓ} (A : Type ℓ) → (! A ⇒ Type↓ ℓ) ≃ Σ (Type ℓ) (λ B → A ≃ B)
lemma {ℓ} A = Iso→Equiv λ where
  .fst (ty , e , _) → ty _ , e ∙e Type↓-fibre (ty _) e⁻¹
  .snd .is-iso.from (B , e) → (λ _ → B) , e ∙e Type↓-fibre B , refl
  .snd .is-iso.linv (ty , e , _) → Σ-pathp refl (Σ-pathp (Σ-prop-path is-equiv-is-prop
    (funext λ _ → Equiv.ε (Type↓-fibre (ty _)) _)) refl)
  .snd .is-iso.rinv (B , e) → Σ-pathp refl (Σ-prop-path is-equiv-is-prop
    (funext λ _ → Equiv.η (Type↓-fibre B) _))
univalence : ∀ {ℓ} (A : Type ℓ) → is-contr (Σ (Type ℓ) λ B → A ≃ B)
univalence {ℓ} A = Equiv→is-hlevel 0 (lemma A e⁻¹) (Type↓-is-classifier (! A))