module lec2 where
open import Function using (_∘_)
open import Data.Unit using (⊤ ; tt)
open import Data.Empty using (⊥ ; ⊥-elim)
open import Data.Product using (Σ ; _,_ ; proj₁ ; proj₂ ; uncurry) renaming (_×_ to _‵×_)
open import Data.Sum using (_⊎_ ; inj₁ ; inj₂ ; [_,_])
infixl 6 _`,_
infix 5 _⊑_
infixr 10 _→̇_
data Ty : Set where
𝕓 𝟙 𝟘 : Ty
_×_ _+_ : Ty → Ty → Ty
variable
A B C D : Ty
data Ctx : Set where
[] : Ctx
_`,_ : Ctx → Ty → Ctx
variable
Γ Γ' Δ Δ' : Ctx
data Var : Ctx → Ty → Set where
zero : Var (Γ `, A) A
succ : (v : Var Γ A) → Var (Γ `, B) A
data _⊑_ : Ctx → Ctx → Set where
base : [] ⊑ []
drop : (w : Γ ⊑ Δ) → Γ ⊑ Δ `, A
keep : (w : Γ ⊑ Δ) → Γ `, A ⊑ Δ `, A
⊑-refl[_] : (Γ : Ctx) → Γ ⊑ Γ
⊑-refl[ [] ] = base
⊑-refl[ Γ `, _a ] = keep ⊑-refl[ Γ ]
fresh : Γ ⊑ Γ `, A
fresh = drop ⊑-refl[ _ ]
wkVar : Γ ⊑ Γ' → Var Γ A → Var Γ' A
wkVar (drop i) v = succ (wkVar i v)
wkVar (keep i) zero = zero
wkVar (keep i) (succ v) = succ (wkVar i v)
data _⊢_ : Ctx → Ty → Set where
var : Var Γ A
→ Γ ⊢ A
unit : Γ ⊢ 𝟙
abort : Γ ⊢ 𝟘
→ Γ ⊢ A
fst : Γ ⊢ (A × B)
→ Γ ⊢ A
snd : Γ ⊢ (A × B)
→ Γ ⊢ B
pair : Γ ⊢ A → Γ ⊢ B
→ Γ ⊢ (A × B)
inl : Γ ⊢ A
→ Γ ⊢ (A + B)
inr : Γ ⊢ B
→ Γ ⊢ (A + B)
case : Γ ⊢ (A + B) → (Γ `, A) ⊢ C → (Γ `, B) ⊢ C
→ Γ ⊢ C
wkTm : Γ ⊑ Γ' → Γ ⊢ A → Γ' ⊢ A
wkTm i (var x) = var (wkVar i x)
wkTm i unit = unit
wkTm i (abort t) = abort (wkTm i t)
wkTm i (fst t) = fst (wkTm i t)
wkTm i (snd t) = snd (wkTm i t)
wkTm i (pair t₁ t₂) = pair (wkTm i t₁) (wkTm i t₂)
wkTm i (inl t) = inl (wkTm i t)
wkTm i (inr t) = inr (wkTm i t)
wkTm i (case s t₁ t₂) = case (wkTm i s) (wkTm (keep i) t₁) (wkTm (keep i) t₂)
data _⊢Ne_ : Ctx → Ty → Set where
var : Var Γ A → Γ ⊢Ne A
fst : Γ ⊢Ne (A × B) → Γ ⊢Ne A
snd : Γ ⊢Ne (A × B) → Γ ⊢Ne B
data _⊢Nf_ : Ctx → Ty → Set where
up : Γ ⊢Ne 𝕓 → Γ ⊢Nf 𝕓
unit : Γ ⊢Nf 𝟙
abort : Γ ⊢Ne 𝟘 → Γ ⊢Nf A
pair : Γ ⊢Nf A → Γ ⊢Nf B → Γ ⊢Nf (A × B)
inl : Γ ⊢Nf A → Γ ⊢Nf (A + B)
inr : Γ ⊢Nf B → Γ ⊢Nf (A + B)
case : Γ ⊢Ne (A + B) → (Γ `, A) ⊢Nf C → (Γ `, B) ⊢Nf C → Γ ⊢Nf C
wkNe : Γ ⊑ Γ' → Γ ⊢Ne A → Γ' ⊢Ne A
wkNe i (var x) = var (wkVar i x)
wkNe i (fst n) = fst (wkNe i n)
wkNe i (snd n) = snd (wkNe i n)
wkNf : Γ ⊑ Γ' → Γ ⊢Nf A → Γ' ⊢Nf A
wkNf i (up x) = up (wkNe i x)
wkNf i unit = unit
wkNf i (abort x) = abort (wkNe i x)
wkNf i (pair n m) = pair (wkNf i n) (wkNf i m)
wkNf i (inl n) = inl (wkNf i n)
wkNf i (inr n) = inr (wkNf i n)
wkNf i (case n m1 m2) = case (wkNe i n) (wkNf (keep i) m1) (wkNf (keep i) m2)
emb : ∀ A → Γ ⊢Ne A → Γ ⊢Nf A
emb 𝕓 n = up n
emb 𝟙 n = unit
emb 𝟘 n = abort n
emb (A × B) n = pair (emb A (fst n)) (emb B (snd n))
emb (A + B) n = case n (inl (emb A (var zero))) (inr (emb B (var zero)))
data _⊢Env_ : Ctx → Ctx → Set where
nil : Δ ⊢Env []
cons : Δ ⊢Env Γ → Δ ⊢Ne A → Δ ⊢Env (Γ `, A)
wkEnv : Δ ⊑ Δ' → Δ ⊢Env Γ → Δ' ⊢Env Γ
wkEnv i nil = nil
wkEnv i (cons γ x) = cons (wkEnv i γ) (wkNe i x)
idEnv[_] : ∀ Δ → Δ ⊢Env Δ
idEnv[ [] ] = nil
idEnv[ Δ `, x ] = cons (wkEnv fresh (idEnv[ Δ ])) (var zero)
Fam : Set₁
Fam = Ctx → Set
Var' Tm' Ne' Nf' : Ty → Fam
Env' : Ctx → Fam
Var' a Γ = Var Γ a
Tm' a Γ = Γ ⊢ a
Ne' a Γ = Γ ⊢Ne a
Nf' a Γ = Γ ⊢Nf a
Env' Δ Γ = Γ ⊢Env Δ
private
variable
X Y : Ctx → Set
_→̇_ : Fam → Fam → Set
_→̇_ X Y = {Δ : Ctx} → X Δ → Y Δ
_×'_ : Fam → Fam → Fam
_×'_ X Y Γ = X Γ ‵× Y Γ
_⊎'_ : Fam → Fam → Fam
_⊎'_ X Y Γ = X Γ ⊎ Y Γ
⊤' : Fam
⊤' = λ Γ → ⊤
⊥' : Fam
⊥' = λ Γ → ⊥
module Model
(𝒯 : Fam → Fam)
(ret : {X : Fam} → X →̇ 𝒯 X)
(fmap : {X Y : Fam} → (X →̇ Y) → 𝒯 X →̇ 𝒯 Y)
(join : {X : Fam} → 𝒯 (𝒯 X) →̇ 𝒯 X)
(V𝕓 : Fam)
(locV𝕓 : 𝒯 V𝕓 →̇ V𝕓)
where
⟦_⟧ : Ty → Fam
⟦ 𝕓 ⟧ = V𝕓
⟦ 𝟙 ⟧ = ⊤'
⟦ 𝟘 ⟧ = 𝒯 ⊥'
⟦ A × B ⟧ = ⟦ A ⟧ ×' ⟦ B ⟧
⟦ A + B ⟧ = 𝒯 (⟦ A ⟧ ⊎' ⟦ B ⟧)
⟦_⟧ᶜ : Ctx → Fam
⟦ [] ⟧ᶜ Γ = ⊤
⟦ Δ `, a ⟧ᶜ Γ = ⟦ Δ ⟧ᶜ Γ ‵× ⟦ a ⟧ Γ
loc : ∀ A → 𝒯 ⟦ A ⟧ →̇ ⟦ A ⟧
loc 𝕓 m = locV𝕓 m
loc 𝟙 m = tt
loc 𝟘 m = join m
loc (A × B) m = loc A (fmap proj₁ m) , loc B (fmap proj₂ m)
loc (A + B) m = join m
lookup : Var Γ A → (⟦ Γ ⟧ᶜ →̇ ⟦ A ⟧)
lookup zero (_ , x) = x
lookup (succ x) (γ , _) = lookup x γ
module Interp (str[_] : (Γ : Ctx) {X : Fam} → ⟦ Γ ⟧ᶜ ×' 𝒯 X →̇ 𝒯 (⟦ Γ ⟧ᶜ ×' X)) where
⟦_⟧ᵗ : Γ ⊢ A → (⟦ Γ ⟧ᶜ →̇ ⟦ A ⟧)
⟦ var x ⟧ᵗ γ = lookup x γ
⟦ unit ⟧ᵗ γ = tt
⟦ abort {Γ} {A} t ⟧ᵗ γ = loc A (fmap ⊥-elim (⟦ t ⟧ᵗ γ))
⟦ fst t ⟧ᵗ γ = proj₁ (⟦ t ⟧ᵗ γ)
⟦ snd t ⟧ᵗ γ = proj₂ (⟦ t ⟧ᵗ γ)
⟦ pair t u ⟧ᵗ γ = ⟦ t ⟧ᵗ γ , ⟦ u ⟧ᵗ γ
⟦ inl t ⟧ᵗ γ = ret (inj₁ (⟦ t ⟧ᵗ γ))
⟦ inr t ⟧ᵗ γ = ret (inj₂ (⟦ t ⟧ᵗ γ))
⟦ case {Γ} {A} {B} {C} s t₁ t₂ ⟧ᵗ {Δ} γ = loc C (fmap match gvˢ)
where
vˢ : 𝒯 (⟦ A ⟧ ⊎' ⟦ B ⟧) Δ
vˢ = ⟦ s ⟧ᵗ γ
gvˢ : 𝒯 (⟦ Γ ⟧ᶜ ×' (⟦ A ⟧ ⊎' ⟦ B ⟧)) Δ
gvˢ = str[ Γ ] (γ , vˢ)
match : ⟦ Γ ⟧ᶜ ×' (⟦ A ⟧ ⊎' ⟦ B ⟧) →̇ ⟦ C ⟧
match (γ' , (inj₁ v₁)) = ⟦ t₁ ⟧ᵗ (γ' , v₁)
match (γ' , (inj₂ v₂)) = ⟦ t₂ ⟧ᵗ (γ' , v₂)
data 𝒞 (X : Fam) : Fam where
val : X Γ → 𝒞 X Γ
abort : Γ ⊢Ne 𝟘 → 𝒞 X Γ
case : Γ ⊢Ne (A + B) → 𝒞 X (Γ `, A) → 𝒞 X (Γ `, B) → 𝒞 X Γ
ret : X →̇ 𝒞 X
ret = val
fmap : (X →̇ Y) → 𝒞 X →̇ 𝒞 Y
fmap f (val a) = val (f a)
fmap f (abort n) = abort n
fmap f (case n m₁ m₂) = case n (fmap f m₁) (fmap f m₂)
join : 𝒞 (𝒞 X) →̇ 𝒞 X
join (val a) = a
join (abort n) = abort n
join (case n m₁ m₂) = case n (join m₁) (join m₂)
Weakens : Fam → Set
Weakens X = {Γ Γ' : Ctx} → Γ ⊑ Γ' → X Γ → X Γ'
module _ {X : Fam} (wkX : Weakens X) where
wk𝒞 : Weakens (𝒞 X)
wk𝒞 i (val x) = val (wkX i x)
wk𝒞 i (abort n) = abort (wkNe i n)
wk𝒞 i (case n m₁ m₂) = case (wkNe i n) (wk𝒞 (keep i) m₁) (wk𝒞 (keep i) m₂)
str : {Y : Fam} → X ×' 𝒞 Y →̇ 𝒞 (X ×' Y)
str (x , m) = go x m
where
go : ∀ {Y Γ} → X Γ → 𝒞 Y Γ → 𝒞 (X ×' Y) Γ
go a (val B) = val (a , B)
go a (abort n) = abort n
go a (case n m₁ m₂) = case n (go (wkX fresh a) m₁) (go (wkX fresh a) m₂)
locNf : 𝒞 (Nf' A) →̇ Nf' A
locNf (val n) = n
locNf (abort n) = abort n
locNf (case n c₁ c₂) = case n (locNf c₁) (locNf c₂)
open Model 𝒞 ret fmap join (Nf' 𝕓) locNf
wk⟦⟧ : ∀ A → Weakens ⟦ A ⟧
wk⟦⟧ 𝕓 i v = wkNf i v
wk⟦⟧ 𝟙 i v = tt
wk⟦⟧ 𝟘 i v = wk𝒞 (λ i' → ⊥-elim) i v
wk⟦⟧ (A × B) i v = wk⟦⟧ A i (proj₁ v) , wk⟦⟧ B i (proj₂ v)
wk⟦⟧ (A + B) i v = wk𝒞 (λ i' → [ inj₁ ∘ wk⟦⟧ A i' , inj₂ ∘ wk⟦⟧ B i' ]) i v
wk⟦⟧ᶜ : ∀ Γ → Weakens ⟦ Γ ⟧ᶜ
wk⟦⟧ᶜ [] i γ = tt
wk⟦⟧ᶜ (Γ `, a) i (γ , v) = (wk⟦⟧ᶜ Γ i γ) , wk⟦⟧ a i v
open Interp (str ∘ wk⟦⟧ᶜ)
reflect : ∀ A → Ne' A →̇ ⟦ A ⟧
reflect 𝕓 n = up n
reflect 𝟙 n = tt
reflect 𝟘 n = abort n
reflect (A × B) n = (reflect A (fst n) , reflect B (snd n))
reflect (A + B) n = case n
(val (inj₁ (reflect A (var zero))))
(val (inj₂ (reflect B (var zero))))
reify : ∀ A → ⟦ A ⟧ →̇ Nf' A
reify 𝕓 x = x
reify 𝟙 x = unit
reify 𝟘 m = locNf (fmap ⊥-elim m)
reify (A × B) p = pair (reify A (proj₁ p)) (reify B (proj₂ p))
reify (A + B) m = locNf (fmap [ inl ∘ reify A , inr ∘ reify B ] m)
reflectᵉ : Env' Γ →̇ ⟦ Γ ⟧ᶜ
reflectᵉ nil = tt
reflectᵉ (cons e n) = (reflectᵉ e) , reflect _ n
norm : Γ ⊢ A → Γ ⊢Nf A
norm {Γ} {A} t = reify A (⟦ t ⟧ᵗ (reflectᵉ idEnv[ Γ ]))