{-# OPTIONS --safe #-}
module Multiset.FiniteChoice where
open import Multiset.Util using (Π⊥≡elim ; isPropΠ⊥)
import Multiset.Util.SetTruncation as STExt
open STExt using (∣_∣₂∗)
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Transport
open import Cubical.Foundations.Isomorphism
using
( Iso
; isoToEquiv
; iso
)
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Function
using
( _∘_
; const
)
open import Cubical.Data.Empty as ⊥
using
( ⊥
)
import Cubical.Data.Sum as Sum
open import Cubical.Data.Nat as ℕ
using
( ℕ
; suc
; _+_
)
open import Cubical.Data.SumFin as Fin
open import Cubical.HITs.SetTruncation as ST
using
( ∥_∥₂
; ∣_∣₂
)
private
variable
ℓ ℓ' : Level
X X' : Type ℓ
n : ℕ
Y : Fin n → Type ℓ'
open Iso
private
_∷_ : {Y : Fin (suc n) → Type ℓ'}
→ (Y fzero)
→ ((k : Fin n) → Y (fsuc k))
→ ((k : Fin (suc n)) → Y k)
v₀ ∷ vₙ = Sum.elim (const v₀) vₙ
at : (k : Fin n) → (v : (k : Fin n) → Y k) → Y k
at k v = v k
module _ {Y : Fin (suc n) → Type ℓ'} where
box-cons
: ∥ Y fzero ∥₂
→ ∥ ((k : Fin n) → Y (fsuc k)) ∥₂
→ ∥ ((k : Fin (suc n)) → Y k) ∥₂
box-cons = STExt.map2 _∷_
box-cons-compute : {v : (k : Fin (suc n)) → Y k}
→ box-cons ∣ v fzero ∣₂ ∣ v ∘ fsuc ∣₂ ≡ ∣ v ∣₂
box-cons-compute = cong ∣_∣₂ (funExt (Sum.elim (λ _ → refl) (λ _ → refl)))
module _ where
box : ∀ {n} {Y : Fin n → Type ℓ'}
→ ((k : Fin n) → ∥ Y k ∥₂)
→ ∥ ((k : Fin n) → Y k) ∥₂
box {n = ℕ.zero} v = ∣ ⊥.elim ∣₂
box {n = suc n} {Y = Y} v = box-cons (v fzero) (box (v ∘ fsuc))
box-compute : ∀ {n} {Y : Fin n → Type ℓ'}
→ (v : (k : Fin n) → Y k)
→ box (∣ v ∣₂∗) ≡ ∣ v ∣₂
box-compute {n = 0} v = cong ∣_∣₂ (isPropΠ⊥ ⊥.elim v)
box-compute {n = suc n} {Y = Y} v = goal where
v₀ : Y fzero
v₀ = v fzero
vₙ : (k : Fin n) → Y (fsuc k)
vₙ = v ∘ fsuc
induction : box (∣_∣₂ ∘ vₙ) ≡ ∣ vₙ ∣₂
induction = box-compute vₙ
goal : box (∣_∣₂ ∘ v) ≡ ∣ v ∣₂
goal =
box-cons (∣ v₀ ∣₂) (box (∣_∣₂ ∘ vₙ))
≡⟨ cong (box-cons ∣ v₀ ∣₂) induction ⟩
box-cons ∣ v₀ ∣₂ ∣ vₙ ∣₂
≡⟨ box-cons-compute ⟩
∣ v ∣₂
∎
unbox : ∥ ((k : Fin n) → Y k) ∥₂
→ (k : Fin n) → ∥ Y k ∥₂
unbox ∣v∣ k = ST.map (at k) ∣v∣
unbox∘box : ∀ {n : ℕ} {Y : Fin n → Type ℓ'}
→ (v : (k : Fin n) → ∥ Y k ∥₂)
→ unbox (box v) ≡ v
unbox∘box {n = 0} v = isPropΠ⊥ _ v
unbox∘box {n = suc n} {Y = Y} v = funExt (Sum.elim (λ (_ : ⊤) → case₀) caseₙ) where
_ : (k : Fin (1 + n)) → ∥ Y k ∥₂
_ = v
v₀ : ∥ Y fzero ∥₂
v₀ = v fzero
vₙ : (k : Fin n) → ∥ Y (fsuc k) ∥₂
vₙ = v ∘ fsuc
unfold-once : ∀ k → unbox (box v) k ≡ STExt.map2 (λ y₀ yₙ → at {Y = Y} k (y₀ ∷ yₙ)) v₀ (box vₙ)
unfold-once k =
ST.map (at {Y = Y} k) (STExt.map2 _∷_ v₀ (box vₙ))
≡⟨
STExt.map∘map2 (at k) _ v₀ (box vₙ)
⟩
STExt.map2 (λ y₀ yₙ → at {Y = Y} k (y₀ ∷ yₙ)) v₀ (box vₙ)
∎
case₀ : unbox (box v) fzero ≡ v fzero
case₀ =
unbox (box v) fzero
≡⟨
unfold-once fzero
⟩
STExt.map2 (λ y₀ yₙ → at {Y = Y} fzero (y₀ ∷ yₙ)) v₀ (box vₙ)
≡⟨
STExt.map2IdRight v₀ (box vₙ)
⟩
v₀
∎
caseₙ : (k : Fin n) → unbox (box v) (fsuc k) ≡ v (fsuc k)
caseₙ k =
unbox (box v) (fsuc k)
≡⟨ unfold-once (fsuc k) ⟩
STExt.map2 (λ y₀ yₙ → at k yₙ) v₀ (box vₙ)
≡⟨
STExt.map2ConstLeft _ v₀ (box vₙ)
⟩
ST.map (at k) (box vₙ)
≡⟨ refl ⟩
unbox (box {Y = Y ∘ fsuc} vₙ) k
≡⟨
funExt⁻ (unbox∘box {n = n} vₙ) k
⟩
vₙ k
∎
unbox∘box-compute : ∀ {n : ℕ} {Y : Fin n → Type ℓ'} {v : (k : Fin n) → Y k}
→ unbox∘box ∣ v ∣₂∗ ≡ cong unbox (box-compute v)
unbox∘box-compute = isSetΠ (λ _ → ST.isSetSetTrunc) _ _ _ _
box∘unbox : (v : ∥ ((k : Fin n) → Y k) ∥₂)
→ box (unbox v) ≡ v
box∘unbox = ST.elim (λ _ → ST.isSetPathImplicit) box-compute
setFinChoice≅ : (Y : Fin n → Type ℓ')
→ Iso ((k : Fin n) → ∥ Y k ∥₂) ∥ ((k : Fin n) → Y k) ∥₂
setFinChoice≅ Y = go where
go : Iso _ _
go .fun = box
go .inv = unbox
go .rightInv = box∘unbox
go .leftInv = unbox∘box
setFinChoice≃ : (Y : Fin n → Type ℓ')
→ ((k : Fin n) → ∥ Y k ∥₂) ≃ ∥ ((k : Fin n) → Y k) ∥₂
setFinChoice≃ Y = isoToEquiv (setFinChoice≅ Y)
module _ {B : (Fin n → ∥ X ∥₂) → Type ℓ'}
(setB : ∀ ∣v∣ → isSet (B ∣v∣))
(choice : (v : Fin n → X) → B (λ k → ∣ v k ∣₂)) where
elimₙ′ : (v : Fin n → ∥ X ∥₂) → B (unbox (box v))
elimₙ′ v = ST.elim {B = B ∘ unbox} (setB ∘ unbox) choice (box v)
elimₙ : (v : Fin n → ∥ X ∥₂) → B v
elimₙ v = subst B (unbox∘box v) (elimₙ′ v)
elimₙ′-comp : (v : Fin n → X)
→ PathP (λ i → B (unbox (box-compute v i)))
(elimₙ′ ∣ v ∣₂∗)
(choice v)
elimₙ′-comp v = cong (ST.elim (setB ∘ unbox) choice) (box-compute v)
elimₙ′-comp′ : (v : Fin n → X)
→ PathP (λ i → B (unbox∘box ∣ v ∣₂∗ i))
(elimₙ′ ∣ v ∣₂∗)
(choice v)
elimₙ′-comp′ v = subst (λ p → PathP (λ i → B (p i)) (elimₙ′ ∣ v ∣₂∗) (choice v)) (sym unbox∘box-compute) (elimₙ′-comp v)
elimₙ-comp : (v : Fin n → X) → elimₙ ∣ v ∣₂∗ ≡ choice v
elimₙ-comp v =
subst B (unbox∘box ∣ v ∣₂∗) (ST.elim (setB ∘ unbox) choice (box (∣ v ∣₂∗)))
≡⟨ fromPathP (elimₙ′-comp′ v) ⟩
ST.elim (setB ∘ unbox) choice ∣ v ∣₂
≡⟨⟩
choice v
∎
elim2ₙ : {B : (v : Fin n → ∥ X ∥₂) (v : Fin n → ∥ X' ∥₂) → Type ℓ'}
→ (setB : ∀ ∣v∣ ∣w∣ → isSet (B ∣v∣ ∣w∣))
→ (choice : (v : Fin n → X) (w : Fin n → X') → B ∣ v ∣₂∗ ∣ w ∣₂∗)
→ (v : Fin n → ∥ X ∥₂) (w : Fin n → ∥ X' ∥₂) → B v w
elim2ₙ {n = n} {X' = X'} {B = B} setB choice =
elimₙ {B = λ v → (w : Fin n → ∥ X' ∥₂) → B v w}
(λ ∣v∣ → isSetΠ (λ ∣w∣ → setB ∣v∣ ∣w∣))
(λ v → elimₙ
(λ ∣w∣ → setB ∣ v ∣₂∗ ∣w∣)
(λ w → choice v w)
)
recₙ : {A : Type ℓ'}
→ (setA : isSet A)
→ (choice : (Fin n → X) → A)
→ (Fin n → ∥ X ∥₂) → A
recₙ setA = elimₙ (λ _ → setA)
rec2ₙ : {A : Type ℓ'}
→ (setA : isSet A)
→ (choice : (v w : Fin n → X) → A)
→ (v w : Fin n → ∥ X ∥₂) → A
rec2ₙ setA = elim2ₙ (λ _ _ → setA)
open import Cubical.HITs.PropositionalTruncation as PT
module _ {Y : Fin (suc n) → Type ℓ'} where
box-cons₁
: ∥ Y fzero ∥₁
→ ∥ ((k : Fin n) → Y (fsuc k)) ∥₁
→ ∥ ((k : Fin (suc n)) → Y k) ∥₁
box-cons₁ = PT.map2 _∷_
module _ where
box₁ : ∀ {n} {Y : Fin n → Type ℓ'}
→ ((k : Fin n) → ∥ Y k ∥₁)
→ ∥ ((k : Fin n) → Y k) ∥₁
box₁ {n = ℕ.zero} v = ∣ ⊥.elim ∣₁
box₁ {n = suc n} {Y = Y} v = box-cons₁ (v fzero) (box₁ (v ∘ fsuc))
unbox₁ : ∥ ((k : Fin n) → Y k) ∥₁
→ (k : Fin n) → ∥ Y k ∥₁
unbox₁ ∣v∣ k = PT.map (at k) ∣v∣