In chapter "DeBruijn: Intrinsically-typed de Bruijn representation", there is a formalisation of variables #_ via de Bruijn indices:
lookup : Context → ℕ → Type
lookup (Γ , A) zero = A
lookup (Γ , _) (suc n) = lookup Γ n
lookup ∅ _ = ⊥-elim impossible
where postulate impossible : ⊥
count : ∀ {Γ} → (n : ℕ) → Γ ∋ lookup Γ n
count {Γ , _} zero = Z
count {Γ , _} (suc n) = S (count n)
count {∅} _ = ⊥-elim impossible
where postulate impossible : ⊥
#_ : ∀ {Γ} → (n : ℕ) → Γ ⊢ lookup Γ n
# n = ` count n
This formalisation relies on postulates to avoid handling the case when a de Bruijn index is out of context bounds. In my view, usage of postulates should be discouraged in the book as postulates in general open room for inconsistency.
Instead, I propose an alternative definition of the three functions above, lookup', count' and #'_, respectively, that uses no postulates, yet the alternative functions guarantee that a de Bruijn index is within the bounds. This development should require no further modifications to the formalisation in the rest of the chapter. At first I was planning to propose to make Context indexed by its size, but I gave up on that approach as it would require quite a few changes in the chapter.
Here is what is different compared to the formalisation from the book:
open import Data.Empty using (⊥)
open import Data.Nat as Nat using (ℕ; zero; suc; _<_; s≤s; z≤n)
open import Data.Nat.Properties using (≤-pred)
open import Data.Unit using (⊤; tt)
length : Context → ℕ
length ∅ = zero
length (Γ , _) = suc (length Γ)
lookup' : (Γ : Context) → (n : ℕ) → (n < length Γ) → Type
lookup' (_ , A) zero _ = A
lookup' (Γ , _) (suc n) ≤-suc = lookup' Γ n (≤-pred ≤-suc)
count' : ∀ {Γ} → (n : ℕ) → (s : n < length Γ) → Γ ∋ lookup' Γ n s
count' {_ , _} zero _ = Z
count' {Γ , A} (suc n) ≤-suc = S (count' n (≤-pred ≤-suc))
_≤?_ : ∀ (m n : ℕ) → Set
zero ≤? n = ⊤
suc m ≤? zero = ⊥
suc m ≤? suc n = m ≤? n
soundness-< : ∀(m n : ℕ) → suc m ≤? n → m < n
soundness-< zero (suc n) tt = s≤s z≤n
soundness-< (suc m) (suc n) m≤?n = s≤s (soundness-< m n m≤?n)
#'_ : ∀ {Γ}
→ (n : ℕ)
→ {s : suc n ≤? length Γ}
--------------------------------------------
→ Γ ⊢ lookup' Γ n (soundness-< n (length Γ) s)
#'_ {Γ} n {s} = ` count' n (soundness-< n (length Γ) s)
-- Church numeral two
_ : ∅ ⊢ (`ℕ ⇒ `ℕ) ⇒ `ℕ ⇒ `ℕ
_ = ƛ ƛ (#' 1 · (#' 1 · #' 0))
In chapter "DeBruijn: Intrinsically-typed de Bruijn representation", there is a formalisation of variables
#_via de Bruijn indices:This formalisation relies on postulates to avoid handling the case when a de Bruijn index is out of context bounds. In my view, usage of postulates should be discouraged in the book as postulates in general open room for inconsistency.
Instead, I propose an alternative definition of the three functions above,
lookup',count'and#'_, respectively, that uses no postulates, yet the alternative functions guarantee that a de Bruijn index is within the bounds. This development should require no further modifications to the formalisation in the rest of the chapter. At first I was planning to propose to makeContextindexed by its size, but I gave up on that approach as it would require quite a few changes in the chapter.Here is what is different compared to the formalisation from the book: