PLFA agda exercises
---
title     : "TypedDB: Typed DeBruijn representation"
permalink : /TypedDB
---

## Imports

\begin{code}
module TypedDB where
\end{code}

\begin{code}
import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; sym; trans; cong)
open import Data.Empty using (⊥; ⊥-elim)
open import Data.Nat using (ℕ; zero; suc; _+_; _∸_)
open import Data.Product using (_×_) renaming (_,_ to ⟨_,_⟩)
open import Data.Unit using (⊤; tt)
open import Function using (_∘_)
open import Function.Equivalence using (_⇔_; equivalence)
open import Relation.Nullary using (¬_; Dec; yes; no)
open import Relation.Nullary.Decidable using (map)
open import Relation.Nullary.Negation using (contraposition)
open import Relation.Nullary.Product using (_×-dec_)
\end{code}


## Syntax

\begin{code}
infixl 6 _,_
infix  4 _⊢_
infix  4 _∋_
infixr 5 _⇒_
infixl 5 _·_
infix  6 S_
infix  4 ƛ_
infix  4 μ_

data Type : Set where
  `ℕ  : Type
  _⇒_ : Type → Type → Type

data Env : Set where
  ε   : Env
  _,_ : Env → Type → Env

data _∋_ : Env → Type → Set where

  Z : ∀ {Γ} {A}
      ----------
    → Γ , A ∋ A

  S_ : ∀ {Γ} {A B}
    → Γ ∋ B
      ---------
    → Γ , A ∋ B

data _⊢_ : Env → Type → Set where

  ⌊_⌋ : ∀ {Γ} {A}
    → Γ ∋ A
      ------
    → Γ ⊢ A

  ƛ_  :  ∀ {Γ} {A B}
    → Γ , A ⊢ B
      ----------
    → Γ ⊢ A ⇒ B

  _·_ : ∀ {Γ} {A B}
    → Γ ⊢ A ⇒ B
    → Γ ⊢ A
      ----------
    → Γ ⊢ B

  `zero : ∀ {Γ}
      ----------
    → Γ ⊢ `ℕ

  `suc : ∀ {Γ}
    → Γ ⊢ `ℕ
      -------
    → Γ ⊢ `ℕ

  `caseℕ : ∀ {Γ A}
    → Γ ⊢ `ℕ
    → Γ ⊢ A
    → Γ , `ℕ ⊢ A
      -----------
    → Γ ⊢ A

  μ_ : ∀ {Γ A}
    → Γ , A ⊢ A
      ----------
    → Γ ⊢ A
\end{code}

Should modify the above to ensure that body of μ is a function.

## Test examples

\begin{code}
two : ∀ {Γ} → Γ ⊢ `ℕ
two = `suc (`suc `zero)

four : ∀ {Γ} → Γ ⊢ `ℕ
four = `suc (`suc (`suc (`suc `zero)))

plus : ∀ {Γ} → Γ ⊢ `ℕ ⇒ `ℕ ⇒ `ℕ
plus = μ ƛ ƛ `caseℕ ⌊ S Z ⌋ ⌊ Z ⌋ (`suc (⌊ S S S Z ⌋ · ⌊ Z ⌋ · ⌊ S Z ⌋))

Ch : Type → Type
Ch A  =  (A ⇒ A) ⇒ A ⇒ A

plusCh : ∀ {Γ A} → Γ ⊢ Ch A ⇒ Ch A ⇒ Ch A
plusCh = ƛ ƛ ƛ ƛ ⌊ S S S Z ⌋ · ⌊ S Z ⌋ · (⌊ S S Z ⌋ · ⌊ S Z ⌋ · ⌊ Z ⌋)

twoCh : ∀ {Γ A} → Γ ⊢ Ch A
twoCh = ƛ ƛ ⌊ S Z ⌋ · (⌊ S Z ⌋ · ⌊ Z ⌋)

fourCh : ∀ {Γ A} → Γ ⊢ Ch A
fourCh = ƛ ƛ ⌊ S Z ⌋ · (⌊ S Z ⌋ · (⌊ S Z ⌋ · (⌊ S Z ⌋ · ⌊ Z ⌋)))

fourCh′ : ∀ {Γ A} → Γ ⊢ Ch A
fourCh′ = plusCh · twoCh · twoCh

inc : ∀ {Γ} → Γ ⊢ `ℕ ⇒ `ℕ
inc = ƛ `suc ⌊ Z ⌋

fromCh : ε ⊢ Ch `ℕ ⇒ `ℕ
fromCh = ƛ ⌊ Z ⌋ · inc · `zero
\end{code}

## Operational semantics

Simultaneous substitution, a la McBride

## Renaming

\begin{code}
ext : ∀ {Γ Δ} → (∀ {A} → Γ ∋ A → Δ ∋ A) → (∀ {A B} → Γ , A ∋ B → Δ , A ∋ B)
ext σ Z      =  Z
ext σ (S x)  =  S (σ x)

rename : ∀ {Γ Δ} → (∀ {A} → Γ ∋ A → Δ ∋ A) → (∀ {A} → Γ ⊢ A → Δ ⊢ A)
rename σ (⌊ n ⌋)         =  ⌊ σ n ⌋
rename σ (ƛ N)           =  ƛ (rename (ext σ) N)
rename σ (L · M)         =  (rename σ L) · (rename σ M)
rename σ (`zero)         =  `zero
rename σ (`suc M)        =  `suc (rename σ M)
rename σ (`caseℕ L M N)  =  `caseℕ (rename σ L) (rename σ M) (rename (ext σ) N)
rename σ (μ N)           =  μ (rename (ext σ) N)
\end{code}

## Substitution

\begin{code}
exts : ∀ {Γ Δ} → (∀ {A} → Γ ∋ A → Δ ⊢ A) → (∀ {A B} → Γ , A ∋ B → Δ , A ⊢ B)
exts ρ Z      =  ⌊ Z ⌋
exts ρ (S x)  =  rename S_ (ρ x)

subst : ∀ {Γ Δ} → (∀ {C} → Γ ∋ C → Δ ⊢ C) → (∀ {C} → Γ ⊢ C → Δ ⊢ C)
subst ρ (⌊ k ⌋)         =  ρ k
subst ρ (ƛ N)           =  ƛ (subst (exts ρ) N)
subst ρ (L · M)         =  (subst ρ L) · (subst ρ M)
subst ρ (`zero)         =  `zero
subst ρ (`suc M)        =  `suc (subst ρ M)
subst ρ (`caseℕ L M N)  =  `caseℕ (subst ρ L) (subst ρ M) (subst (exts ρ) N)
subst ρ (μ N)           =  μ (subst (exts ρ) N)

_[_] : ∀ {Γ A B} → Γ , A ⊢ B → Γ ⊢ A → Γ ⊢ B
_[_] {Γ} {A} N M =  subst {Γ , A} {Γ} ρ N
  where
  ρ : ∀ {B} → Γ , A ∋ B → Γ ⊢ B
  ρ Z      =  M
  ρ (S x)  =  ⌊ x ⌋
\end{code}

## Value

\begin{code}
data Value : ∀ {Γ A} → Γ ⊢ A → Set where

  Zero : ∀ {Γ} →
      -----------------
      Value (`zero {Γ})

  Suc : ∀ {Γ} {V : Γ ⊢ `ℕ}
    → Value V
      --------------
    → Value (`suc V)

  Fun : ∀ {Γ A B} {N : Γ , A ⊢ B}
      ---------------------------
    → Value (ƛ N)
\end{code}

Here `` `zero `` requires an implicit parameter to aid inference
(much in the same way that `[]` did in [Lists](Lists)).

## Reduction step

\begin{code}
infix 2 _⟶_

data _⟶_ : ∀ {Γ A} → (Γ ⊢ A) → (Γ ⊢ A) → Set where

  ξ-⇒₁ : ∀ {Γ A B} {L L′ : Γ ⊢ A ⇒ B} {M : Γ ⊢ A}
    → L ⟶ L′
      -----------------
    → L · M ⟶ L′ · M

  ξ-⇒₂ : ∀ {Γ A B} {V : Γ ⊢ A ⇒ B} {M M′ : Γ ⊢ A}
    → Value V
    → M ⟶ M′
      -----------------
    → V · M ⟶ V · M′

  β-⇒ : ∀ {Γ A B} {N : Γ , A ⊢ B} {W : Γ ⊢ A}
    → Value W
      ---------------------
    → (ƛ N) · W ⟶ N [ W ]

  ξ-ℕ : ∀ {Γ} {M M′ : Γ ⊢ `ℕ}
    → M ⟶ M′
      -------------------
    → `suc M ⟶ `suc M′

  ξ-caseℕ : ∀ {Γ A} {L L′ : Γ ⊢ `ℕ} {M : Γ ⊢ A} {N : Γ , `ℕ ⊢ A}
    → L ⟶ L′
      -------------------------------
    → `caseℕ L M N ⟶ `caseℕ L′ M N

  β-ℕ₁ :  ∀ {Γ A} {M : Γ ⊢ A} {N : Γ , `ℕ ⊢ A}
      -----------------------
    → `caseℕ `zero M N ⟶ M

  β-ℕ₂ : ∀ {Γ A} {V : Γ ⊢ `ℕ} {M : Γ ⊢ A} {N : Γ , `ℕ ⊢ A}
    → Value V
      --------------------------------
    → `caseℕ (`suc V) M N ⟶ N [ V ]

  β-μ : ∀ {Γ A} {N : Γ , A ⊢ A}
      ------------------
    → μ N ⟶ N [ μ N ]
\end{code}

## Reflexive and transitive closure

\begin{code}
infix  2 _⟶*_
infix 1 begin_
infixr 2 _⟶⟨_⟩_
infix 3 _∎

data _⟶*_ : ∀ {Γ A} → (Γ ⊢ A) → (Γ ⊢ A) → Set where

  _∎ : ∀ {Γ A} (M : Γ ⊢ A)
      --------
    → M ⟶* M

  _⟶⟨_⟩_ : ∀ {Γ A} (L : Γ ⊢ A) {M N : Γ ⊢ A}
    → L ⟶ M
    → M ⟶* N
      ---------
    → L ⟶* N

begin_ : ∀ {Γ} {A} {M N : Γ ⊢ A} → (M ⟶* N) → (M ⟶* N)
begin M⟶*N = M⟶*N
\end{code}


## Example reduction sequences

\begin{code}
id : ∀ (A : Type) → ε ⊢ A ⇒ A
id A = ƛ ⌊ Z ⌋

_ : ∀ {A} → id (A ⇒ A) · id A  ⟶* id A
_ =
  begin
    (ƛ ⌊ Z ⌋) · (ƛ ⌊ Z ⌋)
  ⟶⟨ β-⇒ Fun ⟩
    ƛ ⌊ Z ⌋
  ∎

_ : plus {ε} · two · two ⟶* four
_ =
    plus · two · two
  ⟶⟨ ξ-⇒₁ (ξ-⇒₁ β-μ) ⟩
    (ƛ ƛ `caseℕ ⌊ S Z ⌋ ⌊ Z ⌋ (`suc (plus · ⌊ Z ⌋ · ⌊ S Z ⌋))) · two · two
  ⟶⟨ ξ-⇒₁ (β-⇒ (Suc (Suc Zero))) ⟩
    (ƛ `caseℕ two ⌊ Z ⌋ (`suc (plus · ⌊ Z ⌋ · ⌊ S Z ⌋))) · two
  ⟶⟨ β-⇒ (Suc (Suc Zero)) ⟩
    `caseℕ two two (`suc (plus · ⌊ Z ⌋ · two))
  ⟶⟨ β-ℕ₂ (Suc Zero) ⟩
    `suc (plus · `suc `zero · two)
  ⟶⟨ ξ-ℕ (ξ-⇒₁ (ξ-⇒₁ β-μ)) ⟩
    `suc ((ƛ ƛ `caseℕ ⌊ S Z ⌋ ⌊ Z ⌋ (`suc (plus · ⌊ Z ⌋ · ⌊ S Z ⌋)))
      · `suc `zero · two)
  ⟶⟨ ξ-ℕ (ξ-⇒₁ (β-⇒ (Suc Zero))) ⟩
    `suc ((ƛ `caseℕ (`suc `zero) ⌊ Z ⌋ (`suc (plus · ⌊ Z ⌋ · ⌊ S Z ⌋))) · two)
  ⟶⟨ ξ-ℕ (β-⇒ (Suc (Suc Zero))) ⟩
    `suc (`caseℕ (`suc `zero) (two) (`suc (plus · ⌊ Z ⌋ · two)))
  ⟶⟨ ξ-ℕ (β-ℕ₂ Zero) ⟩
    `suc (`suc (plus · `zero · two))
  ⟶⟨ ξ-ℕ (ξ-ℕ (ξ-⇒₁ (ξ-⇒₁ β-μ))) ⟩
    `suc (`suc ((ƛ ƛ `caseℕ ⌊ S Z ⌋ ⌊ Z ⌋ (`suc (plus · ⌊ Z ⌋ · ⌊ S Z ⌋)))
      · `zero · two))
  ⟶⟨ ξ-ℕ (ξ-ℕ (ξ-⇒₁ (β-⇒ Zero))) ⟩
    `suc (`suc ((ƛ `caseℕ `zero ⌊ Z ⌋ (`suc (plus · ⌊ Z ⌋ · ⌊ S Z ⌋))) · two))
  ⟶⟨ ξ-ℕ (ξ-ℕ (β-⇒ (Suc (Suc Zero)))) ⟩
    `suc (`suc (`caseℕ `zero (two) (`suc (plus · ⌊ Z ⌋ · two))))
  ⟶⟨ ξ-ℕ (ξ-ℕ β-ℕ₁) ⟩
   `suc (`suc (`suc (`suc `zero)))
  ∎

_ : fromCh · (plusCh · twoCh · twoCh) ⟶* four
_ =
  begin
    fromCh · (plusCh · twoCh · twoCh)
  ⟶⟨ ξ-⇒₂ Fun (ξ-⇒₁ (β-⇒ Fun)) ⟩
    fromCh · ((ƛ ƛ ƛ twoCh · ⌊ S Z ⌋ · (⌊ S (S Z) ⌋ · ⌊ S Z ⌋ · ⌊ Z ⌋)) · twoCh)
  ⟶⟨ ξ-⇒₂ Fun (β-⇒ Fun) ⟩
    fromCh · (ƛ ƛ twoCh · ⌊ S Z ⌋ · (twoCh · ⌊ S Z ⌋ · ⌊ Z ⌋))
  ⟶⟨ β-⇒ Fun ⟩
    (ƛ ƛ twoCh · ⌊ S Z ⌋ · (twoCh · ⌊ S Z ⌋ · ⌊ Z ⌋)) · inc · `zero
  ⟶⟨ ξ-⇒₁ (β-⇒ Fun) ⟩
    (ƛ twoCh · inc · (twoCh · inc · ⌊ Z ⌋)) · `zero
  ⟶⟨ β-⇒ Zero ⟩
    twoCh · inc · (twoCh · inc · `zero)
  ⟶⟨ ξ-⇒₁ (β-⇒ Fun) ⟩
    (ƛ inc · (inc · ⌊ Z ⌋)) · (twoCh · inc · `zero)
  ⟶⟨ ξ-⇒₂ Fun (ξ-⇒₁ (β-⇒ Fun)) ⟩
    (ƛ inc · (inc · ⌊ Z ⌋)) · ((ƛ inc · (inc · ⌊ Z ⌋)) · `zero)
  ⟶⟨ ξ-⇒₂ Fun (β-⇒ Zero) ⟩
    (ƛ inc · (inc · ⌊ Z ⌋)) · (inc · (inc · `zero))
  ⟶⟨ ξ-⇒₂ Fun (ξ-⇒₂ Fun (β-⇒ Zero)) ⟩
    (ƛ inc · (inc · ⌊ Z ⌋)) · (inc · `suc `zero)
  ⟶⟨ ξ-⇒₂ Fun (β-⇒ (Suc Zero)) ⟩
    (ƛ inc · (inc · ⌊ Z ⌋)) · `suc (`suc `zero)
  ⟶⟨ β-⇒ (Suc (Suc Zero)) ⟩
    inc · (inc · `suc (`suc `zero))
  ⟶⟨ ξ-⇒₂ Fun (β-⇒ (Suc (Suc Zero))) ⟩
    inc · `suc (`suc (`suc `zero))
  ⟶⟨ β-⇒ (Suc (Suc (Suc Zero))) ⟩
    `suc (`suc (`suc (`suc `zero)))
  ∎
\end{code}


## Progress

\begin{code}
data Progress {A} (M : ε ⊢ A) : Set where
  step : ∀ {N : ε ⊢ A}
    → M ⟶ N
      -------------
    → Progress M
  done :
      Value M
      ----------
    → Progress M

progress : ∀ {A} → (M : ε ⊢ A) → Progress M
progress ⌊ () ⌋
progress (ƛ N)                       =  done Fun
progress (L · M) with progress L
...    | step L⟶L′                 =  step (ξ-⇒₁ L⟶L′)
...    | done Fun with progress M
...        | step M⟶M′             =  step (ξ-⇒₂ Fun M⟶M′)
...        | done VM                 =  step (β-⇒ VM)
progress (`zero)                     =  done Zero
progress (`suc M) with progress M
...    | step M⟶M′                 =  step (ξ-ℕ M⟶M′)
...    | done VM                     =  done (Suc VM)
progress (`caseℕ L M N) with progress L
...    | step L⟶L′                       =  step (ξ-caseℕ L⟶L′)
...    | done Zero                         =  step (β-ℕ₁)
...    | done (Suc VL)                     =  step (β-ℕ₂ VL)
progress (μ N)                             =  step (β-μ)
\end{code}


## Normalise

\begin{code}
Gas : Set
Gas = ℕ

data Normalise {A} (M : ε ⊢ A) : Set where
  normal : ∀ {N : ε ⊢ A}
    → Gas
    → M ⟶* N
      -----------
    → Normalise M

normalise : ∀ {A} → ℕ → (L : ε ⊢ A) → Normalise L
normalise zero    L                         =  normal zero (L ∎)
normalise (suc g) L with progress L
...    | done VL                            =  normal (suc zero) (L ∎)
...    | step {M} L⟶M with normalise g M
...        | normal h M⟶*N                =  normal (suc h) (L ⟶⟨ L⟶M ⟩ M⟶*N)
\end{code}