PLFA agda exercises
\begin{code}
module CPP where

open import Data.List hiding ([_])
open import Function

data Type : Set where
  base : Type
  arr  : Type → Type → Type

Cx' = List Type
Model' = Type → Cx' → Set

infixr 8 _⇒_
_⇒_ : (Cx' → Set) → (Cx' → Set) → Cx' → Set
(f ⇒ g) Γ = f Γ → g Γ

[_]' : (Cx' → Set) → Set
[ P ]' = ∀ {x} → P x

infix 9 _⊢_
_⊢_ : Type → (Cx' → Set) → Cx' → Set
(σ ⊢ T) Γ = T (σ ∷ Γ)


data Var : Model' where
  ze : ∀ {σ} → [ σ ⊢ Var σ ]'
  su : ∀ {σ τ} → [ Var σ ⇒ τ ⊢ Var σ ]'

□ : (Cx' → Set) → (Cx' → Set)
□ P Γ = ∀ {Δ} → (∀ {σ} → Var σ Γ → Var σ Δ) → P Δ


data Tm : Model' where
  `var : ∀ {σ} → [ Var σ ⇒ Tm σ ]'
  _`$_ : ∀ {σ τ} → [ Tm (arr σ τ) ⇒ Tm σ ⇒ Tm τ ]'
  `λ   : ∀ {σ τ} → [ σ ⊢ Tm τ ⇒ Tm (arr σ τ) ]'
\end{code}
%<*ren>
\begin{code}
ren : {Γ Δ : List Type} → (∀ {σ} → Var σ Γ → Var σ Δ) → (∀ {σ} → Tm σ Γ → Tm σ Δ)
ren ρ (`var v)  = `var (ρ v)
ren ρ (f `$ t)  = ren ρ f `$ ren ρ t
ren ρ (`λ b)    = `λ (ren ((su ∘ ρ) -, ze) b)
\end{code}
%</ren>
\begin{code}
  where

  _-,_ : ∀ {Γ σ Δ} → (∀ {τ} → Var τ Γ → Var τ Δ) → Var σ Δ → ∀ {τ} → Var τ (σ ∷ Γ) → Var τ Δ
  (ρ -, v) ze     = v
  (ρ -, v) (su k) = ρ k
\end{code}
%<*sub>
\begin{code}
sub : {Γ Δ : List Type} → (∀ {σ} → Var σ Γ → Tm σ Δ) → (∀ {σ} → Tm σ Γ → Tm σ Δ)
sub ρ (`var v)  = ρ v
sub ρ (f `$ t)  = sub ρ f `$ sub ρ t
sub ρ (`λ b)    = `λ (sub ((ren su ∘ ρ) -, `var ze) b)
\end{code}
%</sub>
\begin{code}
  where

  _-,_ :  ∀ {Γ σ Δ} → (∀ {τ} → Var τ Γ → Tm τ Δ) → Tm σ Δ → ∀ {τ} → Var τ (σ ∷ Γ) → Tm τ Δ
  (ρ -, v) ze     = v
  (ρ -, v) (su k) = ρ k

record Kit (◆ : Model') : Set where
  field
    var : ∀ {σ} → [ ◆ σ ⇒ Tm σ ]'
    zro : ∀ {σ} → [ σ ⊢ ◆ σ ]'
    wkn : ∀ {σ τ} → [ ◆ τ ⇒ σ ⊢ ◆ τ ]'

module kitkit {◆ : Model'} (κ : Kit ◆) where
\end{code}
%<*kit>
\begin{code}
 kit : {Γ Δ : List Type} → (∀ {σ} → Var σ Γ → ◆ σ Δ) → (∀ {σ} → Tm σ Γ → Tm σ Δ)
 kit ρ (`var v)  = Kit.var κ (ρ v)
 kit ρ (f `$ t)  = kit ρ f `$ kit ρ t
 kit ρ (`λ b)    = `λ (kit ((Kit.wkn κ ∘ ρ) -, Kit.zro κ) b)
\end{code}
%</kit>
\begin{code}
    where

    _-,_ :  ∀ {Γ σ Δ} → (∀ {τ} → Var τ Γ → ◆ τ Δ) → ◆ σ Δ → ∀ {τ} → Var τ (σ ∷ Γ) → ◆ τ Δ
    (ρ -, v) ze    = v
    (ρ -, v) (su k) = ρ k

Val : Model'
Val base      Γ = Tm base Γ
Val (arr σ τ) Γ = ∀ {Δ} → (∀ {ν} → Var ν Γ → Var ν Δ) → Val σ Δ → Val τ Δ

wk : ∀ {Γ Δ} → (∀ {σ} → Var σ Γ → Var σ Δ) → ∀ {σ} → Val σ Γ → Val σ Δ
wk ρ {base}    v = ren ρ v
wk ρ {arr σ τ} v = λ ρ′ → v (ρ′ ∘ ρ)

APP : ∀ {σ τ Γ} → Val (arr σ τ) Γ →  Val σ Γ → Val τ Γ
APP f t = f id t

LAM : ∀ {Γ σ τ} → Val (arr σ τ) Γ → Val (arr σ τ) Γ
LAM = id
\end{code}
%<*nbe>
\begin{code}
nbe : {Γ Δ : List Type} → (∀ {σ} → Var σ Γ → Val σ Δ) → (∀ {σ} → Tm σ Γ → Val σ Δ)
nbe ρ (`var v)    = ρ v
nbe ρ (f `$ t)  = APP (nbe ρ f) (nbe ρ t)
nbe ρ (`λ t)    = LAM (λ re v → nbe ((wk re ∘ ρ) -, v) t)
\end{code}
%</nbe>
\begin{code}
  where

  _-,_ : ∀ {Γ σ Δ} → (∀ {τ} → Var τ Γ → Val τ Δ) → Val σ Δ → ∀ {τ} → Var τ (σ ∷ Γ) → Val τ Δ
  (ρ -, v) ze     = v
  (ρ -, v) (su k) = ρ k
\end{code}