module Data.FreshList.Sigma where
open import Level hiding (zero; suc)
open import Data.Unit.Polymorphic
open import Data.Product
open import Relation.Binary.PropositionalEquality
open import Relation.Binary.Isomorphism
open import Data.List
open import Data.List.Relation.Unary.All as L using ()
open import Data.FreshList.InductiveInductive
module _
{n m : Level}
{X : Set n}
{R : X → X → Set m}
where
All-fresh : List X → Set (n ⊔ m)
All-fresh [] = ⊤
All-fresh (x ∷ xs) = L.All (R x) xs × All-fresh xs
List#-ext : Set (n ⊔ m)
List#-ext = Σ[ xs ∈ List X ] All-fresh xs
externalise : (xs : List# R) → All-fresh (toList xs)
externalise [] = tt
externalise (cons x xs x#xs) = (toListAll (fresh→all x#xs) , externalise xs)
to : List# R → List#-ext
to xs = (toList xs , externalise xs)
from : (xs : List X) → All-fresh xs → List# R
internalise : {x : X} {xs : List X} → L.All (R x) xs → (pxs : All-fresh xs) → x # from xs pxs
from [] pxs = []
from (x ∷ xs) (rxxs , pxs) = cons x (from xs pxs) (internalise rxxs pxs)
internalise {y} {[]} rxxs pxs = []
internalise (ryx L.∷ ryxs) (_ , pxs) = ryx ∷ internalise ryxs pxs
from-to : (xs : List# R) → xs ≡ uncurry from (to xs)
internalise-externalise : ∀ {x} xs x#xs →
subst (x #_) (from-to xs) x#xs ≡ uncurry internalise (externalise (cons x xs x#xs))
from-to [] = refl
from-to (cons x xs x#xs) = dcong₂ (cons x) (from-to xs) (internalise-externalise xs x#xs)
internalise-externalise [] [] = refl
internalise-externalise {x = x} (cons y ys y#ys) (rxy ∷ x#ys) =
trans (subst-∷ (from-to ys) (internalise-externalise ys y#ys) rxy x#ys)
(cong (rxy ∷_) (internalise-externalise ys x#ys))
where
subst-∷ : {xs ys : List# R}{y#xs : y # xs}{y#ys : y # ys} →
(eq₀ : xs ≡ ys)(eq₁ : subst (y #_) eq₀ y#xs ≡ y#ys) →
(u : R x y)(v : x # xs) →
subst (x #_) (dcong₂ (cons y) eq₀ eq₁) (u ∷ v) ≡ u ∷ subst (x #_) eq₀ v
subst-∷ refl refl u v = refl
toList-from : (xs : List X) → (p : All-fresh xs) → xs ≡ toList (from xs p)
toList-from [] pxs = refl
toList-from (x ∷ xs) (rxxs , pxs) = cong (x ∷_) (toList-from xs pxs)
externalise-from : ∀ xs pxs → subst All-fresh (toList-from xs pxs) pxs ≡ externalise (from xs pxs)
externalise-from [] pxs = refl
externalise-from (x ∷ xs) (rxxs , pxs) = trans (sym (subst-∘ (toList-from xs pxs)))
(trans (subst-× {P = L.All (R x)} (toList-from xs pxs))
(cong₂ _,_ (lem₀ xs pxs rxxs) (externalise-from xs pxs)))
where
subst-× : ∀ {a b c}{A : Set a} → {P : A → Set b}{Q : A → Set c} → {x y : A} → (eq : x ≡ y) → {u : P x}{v : Q x} →
subst (λ z → P z × Q z) eq (u , v) ≡ (subst P eq u , subst Q eq v)
subst-× refl = refl
subst-∷ : ∀ {a b}{A : Set a} → {P : A → Set b} → {y : A}{xs ys : List A} → (eq : xs ≡ ys) → {u : P y}{v : L.All P xs} →
subst (λ z → L.All P (y ∷ z)) eq (u L.∷ v) ≡ (u L.∷ subst (L.All P) eq v)
subst-∷ refl = refl
lem₀ : ∀ {x} xs pxs rxxs → subst (L.All (R x)) (toList-from xs pxs) rxxs ≡ toListAll (fresh→all (internalise rxxs pxs))
lem₀ [] pxs L.[] = refl
lem₀ (x ∷ xs) (rxxs , pxs) (ryx L.∷ pxxs) = trans (sym (subst-∘ (toList-from xs pxs)))
(trans (subst-∷ (toList-from xs pxs)) (cong (ryx L.∷_) (lem₀ xs pxs pxxs)))
to-from : ∀ xs → xs ≡ to (uncurry from xs)
to-from (xs , pxs) = dcong₂ _,_ (toList-from xs pxs) (externalise-from xs pxs)
List#-ext-iso : List# R ≃ List#-ext
List#-ext-iso = MkIso to (uncurry from) from-to to-from