module Talk where
open import Data.Nat hiding (_<_)
data Ty : Set where
nat : Ty
_⇒_ : Ty → Ty → Ty
data Con : Set where
ε : Con
_<_ : Con → Ty → Con
data Var : Con → Ty → Set where
zero : ∀{Γ σ} → Var (Γ < σ) σ
suc : ∀{Γ σ τ} → Var Γ σ → Var (Γ < τ) σ
data Tm : Con → Ty → Set where
var : ∀{Γ σ} → Var Γ σ → Tm Γ σ
lam : ∀{Γ σ τ} → Tm (Γ < σ) τ → Tm Γ (σ ⇒ τ)
app : ∀{Γ σ τ} → Tm Γ (σ ⇒ τ) → Tm Γ σ → Tm Γ τ
zero : ∀{Γ} → Tm Γ nat
suc : ∀{Γ} → Tm Γ nat → Tm Γ nat
prim : ∀{Γ σ} → Tm Γ nat → Tm Γ σ → Tm Γ (σ ⇒ σ) → Tm Γ σ
Val : Ty → Set
Val nat = ℕ
Val (σ ⇒ σ₁) = Val σ → Val σ₁
Env : Con → Set
Env Γ = {σ : _} → Var Γ σ → Val σ
_<'_ : ∀{Γ σ} → Env Γ → Val σ → Env (Γ < σ)
(γ <' v) zero = v
(γ <' v) (suc x) = γ x
vprim : {X : Set} → ℕ → X → (X → X) → X
vprim zero z f = z
vprim (suc n) z f = f (vprim n z f)
⟦_⟧ : ∀{Γ σ} → Tm Γ σ → (Env Γ → Val σ)
⟦ var x ⟧ γ = γ x
⟦ lam t ⟧ γ = λ v → ⟦ t ⟧ (γ <' v)
⟦ app t u ⟧ γ = ⟦ t ⟧ γ (⟦ u ⟧ γ)
⟦ zero ⟧ γ = 0
⟦ suc t ⟧ γ = 1 + (⟦ t ⟧ γ)
⟦ prim t z f ⟧ γ = vprim (⟦ t ⟧ γ) (⟦ z ⟧ γ) (⟦ f ⟧ γ)
two : ∀{Γ} → Tm Γ nat
two = suc (suc zero)
plus : ∀{Γ} → Tm Γ (nat ⇒ (nat ⇒ nat))
plus = lam (lam (prim (var (suc zero)) (var zero) (lam (suc (var zero)))))
example : ∀{Γ} → Tm Γ nat
example = app (app plus two) two
empty : Env ε
empty ()
test : ℕ
test = ⟦ example ⟧ empty