---
title : "Quantitative: Counting Resources in Types"
permalink : /Quantitative/
---
In previous chapters, we introduced the lambda calculus, with [a formalisation based on named variables][plfa.Lambda] and [an inherently-typed version][plfa.DeBruijn]. This chapter presents a refinement of those approaches, in which we not only care about the types of variables, but also about *how often they're used*.
# Imports & Module declaration
\begin{code}
open import Relation.Nullary using (Dec)
open import Relation.Binary.PropositionalEquality as Eq using (_≡_)
open import Algebra.Structures using (module IsSemiring; IsSemiring)
\end{code}
\begin{code}
module qtt.Quantitative
{Mult : Set}
(_+_ _*_ : Mult → Mult → Mult)
(0# 1# : Mult)
(*-+-isSemiring : IsSemiring _≡_ _+_ _*_ 0# 1#)
where
\end{code}
\begin{code}
open import Function using (_∘_; _|>_)
open Eq using (refl; sym; trans; cong)
open Eq.≡-Reasoning using (begin_; _≡⟨_⟩_; _≡⟨⟩_; _∎)
open IsSemiring *-+-isSemiring hiding (refl; sym; trans)
\end{code}
# Syntax
\begin{code}
infix 1 _⊢_
infix 1 _∋_
infixl 5 _,_
infixl 5 _,_∙_
infixr 6 [_∙_]⊸_
infixl 7 _+̇_
infixl 8 _*̇_
infixl 8 _*⟩_
\end{code}
# Types
\begin{code}
data Type : Set where
`0 : Type
[_∙_]⊸_ : Mult → Type → Type → Type
`1 : Type
_⊗_ : Type → Type → Type
_⊕_ : Type → Type → Type
\end{code}
\begin{code}
_⊸_ : Type → Type → Type
A ⊸ B = [ 1# ∙ A ]⊸ B
\end{code}
# Precontexts
\begin{code}
data Precontext : Set where
∅ : Precontext
_,_ : Precontext → Type → Precontext
variable γ δ : Precontext
\end{code}
\begin{code}
_ : Precontext
_ = ∅ , `0 ⊸ `0 , `0
\end{code}
# Variables and the lookup judgment
\begin{code}
data _∋_ : Precontext → Type → Set where
Z : ∀ {γ} {A}
---------
→ γ , A ∋ A
S_ : ∀ {γ} {A B}
→ γ ∋ A
---------
→ γ , B ∋ A
\end{code}
# Contexts
\begin{code}
data Context : Precontext → Set where
∅ : Context ∅
_,_∙_ : ∀ {Γ} → Context Γ → Mult → (A : Type) → Context (Γ , A)
variable Γ Δ Θ : Context γ
\end{code}
\begin{code}
_ : Context (∅ , `0 ⊸ `0 , `0)
_ = ∅ , 1# ∙ `0 ⊸ `0 , 0# ∙ `0
\end{code}
# Resources and linear algebra
Scaling.
\begin{code}
_*̇_ : ∀ {γ} → Mult → Context γ → Context γ
π *̇ ∅ = ∅
π *̇ (Γ , ρ ∙ A) = π *̇ Γ , π * ρ ∙ A
\end{code}
The 0-vector.
\begin{code}
0s : ∀ {γ} → Context γ
0s {∅} = ∅
0s {γ , A} = 0s , 0# ∙ A
\end{code}
Vector addition.
\begin{code}
_+̇_ : ∀ {γ} → Context γ → Context γ → Context γ
∅ +̇ ∅ = ∅
(Γ₁ , π₁ ∙ A) +̇ (Γ₂ , π₂ ∙ .A) = Γ₁ +̇ Γ₂ , π₁ + π₂ ∙ A
\end{code}
Matrices.
See [this sidenote][plfa.Quantitative.LinAlg].
\begin{code}
Matrix : Precontext → Precontext → Set
Matrix γ δ = ∀ {A} → γ ∋ A → Context δ
variable Ξ : Matrix γ δ
\end{code}
The identity matrix.
"x" "y" "z"
"x" 1 ∙ A , 0 ∙ B , 0 ∙ C
"y" 0 ∙ A , 1 ∙ B , 0 ∙ C
"z" 0 ∙ A , 0 ∙ B , 1 ∙ C
\begin{code}
identity : ∀ {γ} → Matrix γ γ
identity {γ , A} Z = 0s , 1# ∙ A
identity {γ , B} (S x) = identity x , 0# ∙ B
\end{code}
# Terms and the typing judgment
\begin{code}
data _⊢_ : ∀ {γ} (Γ : Context γ) (A : Type) → Set where
`_ : ∀ {γ} {A}
→ (x : γ ∋ A)
--------------
→ identity x ⊢ A
ƛ_ : ∀ {γ} {Γ : Context γ} {A B} {π}
→ Γ , π ∙ A ⊢ B
----------------
→ Γ ⊢ [ π ∙ A ]⊸ B
_·_ : ∀ {γ} {Γ Δ : Context γ} {A B} {π}
→ Γ ⊢ [ π ∙ A ]⊸ B
→ Δ ⊢ A
----------------
→ Γ +̇ π *̇ Δ ⊢ B
⟨⟩ : ∀ {γ}
-----------
→ 0s {γ} ⊢ `1
case1 : ∀ {γ} {Γ Δ : Context γ} {A}
→ Γ ⊢ `1
→ Δ ⊢ A
---------
→ Γ +̇ Δ ⊢ A
⟨_,_⟩ : ∀ {γ} {Γ Δ : Context γ} {A B}
→ Γ ⊢ A
→ Δ ⊢ B
-------------
→ Γ +̇ Δ ⊢ A ⊗ B
case⊗ : ∀ {γ} {Γ Δ : Context γ} {A B C}
→ Γ ⊢ A ⊗ B
→ Δ , 1# ∙ A , 1# ∙ B ⊢ C
-----------------------
→ Γ +̇ Δ ⊢ C
inj₁ : ∀ {γ} {Γ : Context γ} {A B}
→ Γ ⊢ A
---------
→ Γ ⊢ A ⊕ B
inj₂ : ∀ {γ} {Γ : Context γ} {A B}
→ Γ ⊢ B
---------
→ Γ ⊢ A ⊕ B
case⊕ : ∀ {γ} {Γ Δ : Context γ} {A B C}
→ Γ ⊢ A ⊕ B
→ Δ , 1# ∙ A ⊢ C
→ Δ , 1# ∙ B ⊢ C
--------------
→ Γ +̇ Δ ⊢ C
\end{code}
# Properties of vector operations
Unit scaling does nothing.
\begin{code}
*̇-identityˡ : ∀ {γ} (Γ : Context γ)
-----------
→ 1# *̇ Γ ≡ Γ
*̇-identityˡ ∅ = refl
*̇-identityˡ (Γ , π ∙ A) =
begin
1# *̇ Γ , 1# * π ∙ A
≡⟨ *-identityˡ π |> cong (1# *̇ Γ ,_∙ A) ⟩
1# *̇ Γ , π ∙ A
≡⟨ *̇-identityˡ Γ |> cong (_, π ∙ A) ⟩
Γ , π ∙ A
∎
\end{code}
Scaling by a product is the composition of scalings.
\begin{code}
*̇-assoc : ∀ {γ} (Γ : Context γ) {π π′}
------------------------------
→ (π * π′) *̇ Γ ≡ π *̇ (π′ *̇ Γ)
*̇-assoc ∅ = refl
*̇-assoc (Γ , π″ ∙ A) {π} {π′} =
begin
(π * π′) *̇ Γ , (π * π′) * π″ ∙ A
≡⟨ *-assoc π π′ π″ |> cong ((π * π′) *̇ Γ ,_∙ A) ⟩
(π * π′) *̇ Γ , π * (π′ * π″) ∙ A
≡⟨ *̇-assoc Γ |> cong (_, π * (π′ * π″) ∙ A) ⟩
π *̇ (π′ *̇ Γ) , π * (π′ * π″) ∙ A
∎
\end{code}
Scaling the 0-vector gives the 0-vector.
\begin{code}
*̇-zeroʳ : ∀ {γ} π
----------------
→ 0s {γ} ≡ π *̇ 0s
*̇-zeroʳ {∅} π = refl
*̇-zeroʳ {γ , A} π =
begin
0s , 0# ∙ A
≡⟨ zeroʳ π |> sym ∘ cong (0s ,_∙ A) ⟩
0s , π * 0# ∙ A
≡⟨ *̇-zeroʳ π |> cong (_, π * 0# ∙ A) ⟩
π *̇ 0s , π * 0# ∙ A
∎
\end{code}
Scaling by 0 gives the 0-vector.
\begin{code}
*̇-zeroˡ : ∀ {γ} (Γ : Context γ)
------------
→ 0# *̇ Γ ≡ 0s
*̇-zeroˡ ∅ = refl
*̇-zeroˡ (Γ , π ∙ A) =
begin
0# *̇ Γ , 0# * π ∙ A
≡⟨ zeroˡ π |> cong (0# *̇ Γ ,_∙ A) ⟩
0# *̇ Γ , 0# ∙ A
≡⟨ *̇-zeroˡ Γ |> cong (_, 0# ∙ A) ⟩
0s , 0# ∙ A
∎
\end{code}
Adding the 0-vector does nothing.
\begin{code}
+̇-identityˡ : ∀ {γ} (Γ : Context γ)
----------
→ 0s +̇ Γ ≡ Γ
+̇-identityˡ ∅ = refl
+̇-identityˡ (Γ , π ∙ A) =
begin
0s +̇ Γ , 0# + π ∙ A
≡⟨ +-identityˡ π |> cong (0s +̇ Γ ,_∙ A) ⟩
0s +̇ Γ , π ∙ A
≡⟨ +̇-identityˡ Γ |> cong (_, π ∙ A) ⟩
Γ , π ∙ A
∎
\end{code}
\begin{code}
+̇-identityʳ : ∀ {γ} (Γ : Context γ)
----------
→ Γ +̇ 0s ≡ Γ
+̇-identityʳ ∅ = refl
+̇-identityʳ (Γ , π ∙ A) =
begin
Γ +̇ 0s , π + 0# ∙ A
≡⟨ +-identityʳ π |> cong (Γ +̇ 0s ,_∙ A) ⟩
Γ +̇ 0s , π ∙ A
≡⟨ +̇-identityʳ Γ |> cong (_, π ∙ A) ⟩
Γ , π ∙ A
∎
\end{code}
Vector addition is commutative.
\begin{code}
+̇-comm : ∀ {γ} (Γ₁ Γ₂ : Context γ)
-----------------
→ Γ₁ +̇ Γ₂ ≡ Γ₂ +̇ Γ₁
+̇-comm ∅ ∅ = refl
+̇-comm (Γ₁ , π₁ ∙ A) (Γ₂ , π₂ ∙ .A) =
begin
Γ₁ +̇ Γ₂ , π₁ + π₂ ∙ A
≡⟨ +-comm π₁ π₂ |> cong (Γ₁ +̇ Γ₂ ,_∙ A) ⟩
Γ₁ +̇ Γ₂ , π₂ + π₁ ∙ A
≡⟨ +̇-comm Γ₁ Γ₂ |> cong (_, π₂ + π₁ ∙ A) ⟩
Γ₂ +̇ Γ₁ , π₂ + π₁ ∙ A
∎
\end{code}
Vector addition is associative.
\begin{code}
+̇-assoc : ∀ {γ} (Γ₁ Γ₂ Γ₃ : Context γ)
-------------------------------------
→ (Γ₁ +̇ Γ₂) +̇ Γ₃ ≡ Γ₁ +̇ (Γ₂ +̇ Γ₃)
+̇-assoc ∅ ∅ ∅ = refl
+̇-assoc (Γ₁ , π₁ ∙ A) (Γ₂ , π₂ ∙ .A) (Γ₃ , π₃ ∙ .A) =
begin
(Γ₁ +̇ Γ₂) +̇ Γ₃ , (π₁ + π₂) + π₃ ∙ A
≡⟨ +-assoc π₁ π₂ π₃ |> cong ((Γ₁ +̇ Γ₂) +̇ Γ₃ ,_∙ A) ⟩
(Γ₁ +̇ Γ₂) +̇ Γ₃ , π₁ + (π₂ + π₃) ∙ A
≡⟨ +̇-assoc Γ₁ Γ₂ Γ₃ |> cong (_, π₁ + (π₂ + π₃) ∙ A) ⟩
Γ₁ +̇ (Γ₂ +̇ Γ₃) , π₁ + (π₂ + π₃) ∙ A
∎
\end{code}
Scaling by a sum gives the sum of the scalings.
\begin{code}
*̇-distribʳ-+̇ : ∀ {γ} (Γ : Context γ) (π₁ π₂ : Mult)
-----------------------------------
→ (π₁ + π₂) *̇ Γ ≡ π₁ *̇ Γ +̇ π₂ *̇ Γ
*̇-distribʳ-+̇ ∅ π₁ π₂ = refl
*̇-distribʳ-+̇ (Γ , π ∙ A) π₁ π₂ =
begin
(π₁ + π₂) *̇ Γ , (π₁ + π₂) * π ∙ A
≡⟨ distribʳ π π₁ π₂ |> cong ((π₁ + π₂) *̇ Γ ,_∙ A) ⟩
(π₁ + π₂) *̇ Γ , (π₁ * π) + (π₂ * π) ∙ A
≡⟨ *̇-distribʳ-+̇ Γ π₁ π₂ |> cong (_, (π₁ * π) + (π₂ * π) ∙ A) ⟩
π₁ *̇ Γ +̇ π₂ *̇ Γ , (π₁ * π) + (π₂ * π) ∙ A
∎
\end{code}
Scaling a sum gives the sum of the scalings.
\begin{code}
*̇-distribˡ-+̇ : ∀ {γ} (Γ₁ Γ₂ : Context γ) (π : Mult)
--------------------------------------
→ π *̇ (Γ₁ +̇ Γ₂) ≡ π *̇ Γ₁ +̇ π *̇ Γ₂
*̇-distribˡ-+̇ ∅ ∅ π = refl
*̇-distribˡ-+̇ (Γ₁ , π₁ ∙ A) (Γ₂ , π₂ ∙ .A) π =
begin
π *̇ (Γ₁ +̇ Γ₂) , π * (π₁ + π₂) ∙ A
≡⟨ distribˡ π π₁ π₂ |> cong (π *̇ (Γ₁ +̇ Γ₂) ,_∙ A) ⟩
π *̇ (Γ₁ +̇ Γ₂) , (π * π₁) + (π * π₂) ∙ A
≡⟨ *̇-distribˡ-+̇ Γ₁ Γ₂ π |> cong (_, (π * π₁) + (π * π₂) ∙ A) ⟩
π *̇ Γ₁ +̇ π *̇ Γ₂ , (π * π₁) + (π * π₂) ∙ A
∎
\end{code}
# Vector-matrix multiplication
Vector-matrix multiplication.
\begin{code}
_*⟩_ : ∀ {γ δ} → Context γ → Matrix γ δ → Context δ
∅ *⟩ Ξ = 0s
(Γ , π ∙ A) *⟩ Ξ = (π *̇ Ξ Z) +̇ Γ *⟩ (Ξ ∘ S_)
\end{code}
Linear maps preserve the 0-vector.
\begin{code}
*⟩-zeroˡ : ∀ {γ δ} (Ξ : Matrix γ δ)
--------------
→ 0s *⟩ Ξ ≡ 0s
*⟩-zeroˡ {∅} {δ} Ξ = refl
*⟩-zeroˡ {γ , A} {δ} Ξ =
begin
0s *⟩ Ξ
≡⟨⟩
0# *̇ Ξ Z +̇ 0s *⟩ (Ξ ∘ S_)
≡⟨ *⟩-zeroˡ (Ξ ∘ S_) |> cong (0# *̇ Ξ Z +̇_) ⟩
0# *̇ Ξ Z +̇ 0s
≡⟨ *̇-zeroˡ (Ξ Z) |> cong (_+̇ 0s) ⟩
0s +̇ 0s
≡⟨ +̇-identityʳ 0s ⟩
0s
∎
\end{code}
Adding a row of 0s to the end of the matrix and then multiplying by a vector produces a vector with a 0 at the bottom.
\begin{code}
*⟩-zeroʳ : ∀ {γ δ} (Γ : Context γ) (Ξ : Matrix γ δ) {B}
---------------------------------------------
→ Γ *⟩ (λ x → Ξ x , 0# ∙ B) ≡ Γ *⟩ Ξ , 0# ∙ B
*⟩-zeroʳ {γ} {δ} ∅ Ξ {B} = refl
*⟩-zeroʳ {γ} {δ} (Γ , π ∙ C) Ξ {B} =
begin
(π *̇ Ξ Z , π * 0# ∙ B) +̇ (Γ *⟩ (λ x → Ξ (S x) , 0# ∙ B))
≡⟨ *⟩-zeroʳ Γ (Ξ ∘ S_) |> cong ((π *̇ Ξ Z , π * 0# ∙ B) +̇_) ⟩
(π *̇ Ξ Z , π * 0# ∙ B) +̇ (Γ *⟩ (λ x → Ξ (S x)) , 0# ∙ B)
≡⟨⟩
(π *̇ Ξ Z , π * 0# ∙ B) +̇ (Γ *⟩ (Ξ ∘ S_) , 0# ∙ B)
≡⟨⟩
(π *̇ Ξ Z +̇ Γ *⟩ (Ξ ∘ S_)) , (π * 0#) + 0# ∙ B
≡⟨ +-identityʳ (π * 0#) |> cong ((π *̇ Ξ Z +̇ Γ *⟩ (Ξ ∘ S_)) ,_∙ B) ⟩
(π *̇ Ξ Z +̇ Γ *⟩ (Ξ ∘ S_)) , π * 0# ∙ B
≡⟨ zeroʳ π |> cong ((π *̇ Ξ Z +̇ Γ *⟩ (Ξ ∘ S_)) ,_∙ B) ⟩
(π *̇ Ξ Z +̇ Γ *⟩ (Ξ ∘ S_)) , 0# ∙ B
∎
\end{code}
Linear maps preserve scaling.
\begin{code}
*⟩-assoc : ∀ {γ δ} (Γ : Context γ) (Ξ : Matrix γ δ) (π : Mult)
-----------------------------------
→ (π *̇ Γ) *⟩ Ξ ≡ π *̇ (Γ *⟩ Ξ)
*⟩-assoc {γ} {δ} ∅ Ξ π =
begin
0s
≡⟨ *̇-zeroʳ π ⟩
π *̇ 0s
∎
*⟩-assoc {γ} {δ} (Γ , π′ ∙ A) Ξ π =
begin
((π * π′) *̇ Ξ Z) +̇ ((π *̇ Γ) *⟩ (Ξ ∘ S_))
≡⟨ *⟩-assoc Γ (Ξ ∘ S_) π |> cong ((π * π′) *̇ Ξ Z +̇_) ⟩
((π * π′) *̇ Ξ Z) +̇ (π *̇ (Γ *⟩ (Ξ ∘ S_)))
≡⟨ *̇-assoc (Ξ Z) |> cong (_+̇ (π *̇ (Γ *⟩ (Ξ ∘ S_)))) ⟩
(π *̇ (π′ *̇ Ξ Z)) +̇ (π *̇ (Γ *⟩ (Ξ ∘ S_)))
≡⟨ *̇-distribˡ-+̇ (π′ *̇ Ξ Z) (Γ *⟩ (Ξ ∘ S_)) π |> sym ⟩
π *̇ (π′ *̇ Ξ Z +̇ Γ *⟩ (Ξ ∘ S_))
∎
\end{code}
Linear maps distribute over sums.
\begin{code}
*⟩-distribʳ-+̇ : ∀ {γ} {δ} (Γ₁ Γ₂ : Context γ) (Ξ : Matrix γ δ)
----------------------------------
→ (Γ₁ +̇ Γ₂) *⟩ Ξ ≡ Γ₁ *⟩ Ξ +̇ Γ₂ *⟩ Ξ
*⟩-distribʳ-+̇ ∅ ∅ Ξ =
begin
0s
≡⟨ sym (+̇-identityʳ 0s) ⟩
0s +̇ 0s
∎
*⟩-distribʳ-+̇ (Γ₁ , π₁ ∙ A) (Γ₂ , π₂ ∙ .A) Ξ =
begin
(π₁ + π₂) *̇ Ξ Z +̇ (Γ₁ +̇ Γ₂) *⟩ (Ξ ∘ S_)
≡⟨ *⟩-distribʳ-+̇ Γ₁ Γ₂ (Ξ ∘ S_) |> cong ((π₁ + π₂) *̇ Ξ Z +̇_) ⟩
(π₁ + π₂) *̇ Ξ Z +̇ (Γ₁ *⟩ (Ξ ∘ S_) +̇ Γ₂ *⟩ (Ξ ∘ S_))
≡⟨ *̇-distribʳ-+̇ (Ξ Z) π₁ π₂ |> cong (_+̇ (Γ₁ *⟩ (Ξ ∘ S_) +̇ Γ₂ *⟩ (Ξ ∘ S_))) ⟩
(π₁ *̇ Ξ Z +̇ π₂ *̇ Ξ Z) +̇ (Γ₁ *⟩ (Ξ ∘ S_) +̇ Γ₂ *⟩ (Ξ ∘ S_))
≡⟨ +̇-assoc (π₁ *̇ Ξ Z +̇ π₂ *̇ Ξ Z) (Γ₁ *⟩ (Ξ ∘ S_)) (Γ₂ *⟩ (Ξ ∘ S_)) |> sym ⟩
((π₁ *̇ Ξ Z +̇ π₂ *̇ Ξ Z) +̇ Γ₁ *⟩ (Ξ ∘ S_)) +̇ Γ₂ *⟩ (Ξ ∘ S_)
≡⟨ +̇-assoc (π₁ *̇ Ξ Z) (π₂ *̇ Ξ Z) (Γ₁ *⟩ (Ξ ∘ S_)) |> cong (_+̇ Γ₂ *⟩ (Ξ ∘ S_)) ⟩
(π₁ *̇ Ξ Z +̇ (π₂ *̇ Ξ Z +̇ Γ₁ *⟩ (Ξ ∘ S_))) +̇ Γ₂ *⟩ (Ξ ∘ S_)
≡⟨ +̇-comm (π₂ *̇ Ξ Z) (Γ₁ *⟩ (Ξ ∘ S_)) |> cong ((_+̇ Γ₂ *⟩ (Ξ ∘ S_)) ∘ (π₁ *̇ Ξ Z +̇_)) ⟩
(π₁ *̇ Ξ Z +̇ (Γ₁ *⟩ (Ξ ∘ S_) +̇ π₂ *̇ Ξ Z)) +̇ Γ₂ *⟩ (Ξ ∘ S_)
≡⟨ +̇-assoc (π₁ *̇ Ξ Z) (Γ₁ *⟩ (Ξ ∘ S_)) (π₂ *̇ Ξ Z) |> sym ∘ cong (_+̇ Γ₂ *⟩ (Ξ ∘ S_)) ⟩
((π₁ *̇ Ξ Z +̇ Γ₁ *⟩ (Ξ ∘ S_)) +̇ π₂ *̇ Ξ Z) +̇ Γ₂ *⟩ (Ξ ∘ S_)
≡⟨ +̇-assoc (π₁ *̇ Ξ Z +̇ Γ₁ *⟩ (Ξ ∘ S_)) (π₂ *̇ Ξ Z) (Γ₂ *⟩ (Ξ ∘ S_)) ⟩
(π₁ *̇ Ξ Z +̇ Γ₁ *⟩ (Ξ ∘ S_)) +̇ (π₂ *̇ Ξ Z +̇ Γ₂ *⟩ (Ξ ∘ S_))
∎
\end{code}
Multiplying by a standard basis vector projects out the corresponding column of the matrix.
\begin{code}
*⟩-identityˡ : ∀ {γ δ} {A} (Ξ : Matrix γ δ)
→ (x : γ ∋ A)
-----------------------
→ identity x *⟩ Ξ ≡ Ξ x
*⟩-identityˡ {γ , A} {δ} {A} Ξ Z =
begin
identity Z *⟩ Ξ
≡⟨⟩
1# *̇ Ξ Z +̇ 0s *⟩ (Ξ ∘ S_)
≡⟨ *⟩-zeroˡ (Ξ ∘ S_) |> cong ((1# *̇ Ξ Z) +̇_) ⟩
1# *̇ Ξ Z +̇ 0s
≡⟨ +̇-identityʳ (1# *̇ Ξ Z) ⟩
1# *̇ Ξ Z
≡⟨ *̇-identityˡ (Ξ Z) ⟩
Ξ Z
∎
*⟩-identityˡ {γ , B} {δ} {A} Ξ (S x) =
begin
identity (S x) *⟩ Ξ
≡⟨⟩
0# *̇ Ξ Z +̇ identity x *⟩ (Ξ ∘ S_)
≡⟨ *⟩-identityˡ (Ξ ∘ S_) x |> cong (0# *̇ Ξ Z +̇_) ⟩
0# *̇ Ξ Z +̇ Ξ (S x)
≡⟨ *̇-zeroˡ (Ξ Z) |> cong (_+̇ Ξ (S x)) ⟩
0s +̇ Ξ (S x)
≡⟨ +̇-identityˡ (Ξ (S x)) ⟩
Ξ (S x)
∎
\end{code}
The standard basis vectors put together give the identity matrix.
\begin{code}
*⟩-identityʳ : ∀ {γ} (Γ : Context γ)
-------------------
→ Γ *⟩ identity ≡ Γ
*⟩-identityʳ {γ} ∅ = refl
*⟩-identityʳ {γ , .A} (Γ , π ∙ A) =
begin
(π *̇ 0s , π * 1# ∙ A) +̇ (Γ *⟩ (λ x → identity x , 0# ∙ A))
≡⟨ *⟩-zeroʳ Γ identity |> cong ((π *̇ 0s , π * 1# ∙ A) +̇_) ⟩
(π *̇ 0s , π * 1# ∙ A) +̇ (Γ *⟩ identity , 0# ∙ A)
≡⟨ *⟩-identityʳ Γ |> cong (((π *̇ 0s , π * 1# ∙ A) +̇_) ∘ (_, 0# ∙ A)) ⟩
(π *̇ 0s , π * 1# ∙ A) +̇ (Γ , 0# ∙ A)
≡⟨⟩
π *̇ 0s +̇ Γ , (π * 1#) + 0# ∙ A
≡⟨ +-identityʳ (π * 1#) |> cong ((π *̇ 0s +̇ Γ) ,_∙ A) ⟩
π *̇ 0s +̇ Γ , π * 1# ∙ A
≡⟨ *-identityʳ π |> cong ((π *̇ 0s +̇ Γ) ,_∙ A) ⟩
π *̇ 0s +̇ Γ , π ∙ A
≡⟨ *̇-zeroʳ π |> cong ((_, π ∙ A) ∘ (_+̇ Γ)) ∘ sym ⟩
0s +̇ Γ , π ∙ A
≡⟨ +̇-identityˡ Γ |> cong (_, π ∙ A) ⟩
Γ , π ∙ A
∎
\end{code}
# Renaming
\begin{code}
ext : ∀ {γ δ}
→ (∀ {A} → γ ∋ A → δ ∋ A)
---------------------------------
→ (∀ {A B} → γ , B ∋ A → δ , B ∋ A)
ext ρ Z = Z
ext ρ (S x) = S (ρ x)
\end{code}
\begin{code}
lem-` : ∀ {γ δ} {A} {Ξ : Matrix γ δ} (x : γ ∋ A) → _
lem-` {γ} {δ} {A} {Ξ} x =
begin
Ξ x
≡⟨ *⟩-identityˡ Ξ x |> sym ⟩
identity x *⟩ Ξ
∎
\end{code}
\begin{code}
lem-ƛ : ∀ {γ δ} (Γ : Context γ) {A} {π} {Ξ : Matrix γ δ} → _
lem-ƛ {γ} {δ} Γ {A} {π} {Ξ} =
begin
(π *̇ 0s , π * 1# ∙ A) +̇ (Γ *⟩ (λ x → Ξ x , 0# ∙ A))
≡⟨ *⟩-zeroʳ Γ Ξ |> cong ((π *̇ 0s , π * 1# ∙ A) +̇_) ⟩
(π *̇ 0s , π * 1# ∙ A) +̇ (Γ *⟩ Ξ , 0# ∙ A)
≡⟨⟩
π *̇ 0s +̇ Γ *⟩ Ξ , (π * 1#) + 0# ∙ A
≡⟨ *̇-zeroʳ π |> cong ((_, (π * 1#) + 0# ∙ A) ∘ (_+̇ Γ *⟩ Ξ)) ∘ sym ⟩
0s +̇ Γ *⟩ Ξ , (π * 1#) + 0# ∙ A
≡⟨ +̇-identityˡ (Γ *⟩ Ξ) |> cong (_, (π * 1#) + 0# ∙ A) ⟩
Γ *⟩ Ξ , (π * 1#) + 0# ∙ A
≡⟨ +-identityʳ (π * 1#) |> cong (Γ *⟩ Ξ ,_∙ A) ⟩
Γ *⟩ Ξ , π * 1# ∙ A
≡⟨ *-identityʳ π |> cong (Γ *⟩ Ξ ,_∙ A) ⟩
Γ *⟩ Ξ , π ∙ A
∎
\end{code}
\begin{code}
lem-· : ∀ {γ δ} (Γ Δ : Context γ) {π} {Ξ : Matrix γ δ} → _
lem-· {γ} {δ} Γ Δ {π} {Ξ} =
begin
Γ *⟩ Ξ +̇ π *̇ (Δ *⟩ Ξ)
≡⟨ *⟩-assoc Δ Ξ π |> cong (Γ *⟩ Ξ +̇_) ∘ sym ⟩
Γ *⟩ Ξ +̇ (π *̇ Δ) *⟩ Ξ
≡⟨ *⟩-distribʳ-+̇ Γ (π *̇ Δ) Ξ |> sym ⟩
(Γ +̇ π *̇ Δ) *⟩ Ξ ∎
\end{code}
\begin{code}
lem-, : ∀ {γ δ} (Γ Δ : Context γ) {Ξ : Matrix γ δ} → _
lem-, {γ} {δ} Γ Δ {Ξ} =
begin
Γ *⟩ Ξ +̇ Δ *⟩ Ξ
≡⟨ *⟩-distribʳ-+̇ Γ Δ Ξ |> sym ⟩
(Γ +̇ Δ) *⟩ Ξ
∎
\end{code}
\begin{code}
lem-case⊗ : ∀ {γ δ} (Γ : Context γ) {A B} {Ξ : Matrix γ δ} → _
lem-case⊗ {γ} {δ} Γ {A} {B} {Ξ} =
let
lem1 : ∀ {γ} (Γ : Context γ) → _
lem1 {γ} Γ =
begin
(1# *̇ 0s) +̇ Γ
≡⟨ *̇-identityˡ 0s |> cong (_+̇ Γ) ⟩
0s +̇ Γ
≡⟨ +̇-identityˡ Γ ⟩
Γ
∎
in
begin
(1# *̇ 0s , 1# * 0# ∙ A , 1# * 1# ∙ B) +̇ ((1# *̇ 0s , 1# * 1# ∙ A , 1# * 0# ∙ B) +̇ Γ *⟩ (λ x → Ξ x , 0# ∙ A , 0# ∙ B))
-- Step 1. Move the three occurrences of A and B to the top-level.
≡⟨ trans (*⟩-zeroʳ Γ (λ x → Ξ x , 0# ∙ A)) (*⟩-zeroʳ Γ Ξ |> cong (_, 0# ∙ B))
|> cong (((1# *̇ 0s , 1# * 0# ∙ A , 1# * 1# ∙ B) +̇_) ∘ ((1# *̇ 0s , 1# * 1# ∙ A , 1# * 0# ∙ B) +̇_)) ⟩
(1# *̇ 0s) +̇ ((1# *̇ 0s) +̇ (Γ *⟩ Ξ)) , (1# * 0#) + ((1# * 1#) + 0#) ∙ A , (1# * 1#) + ((1# * 0#) + 0#) ∙ B
-- Step 2. Remove the empty environments (1# *̇ 0s).
≡⟨ trans (lem1 (Γ *⟩ Ξ) |> cong (1# *̇ 0s +̇_)) (lem1 (Γ *⟩ Ξ))
|> cong ((_, (1# * 1#) + ((1# * 0#) + 0#) ∙ B) ∘ (_, (1# * 0#) + ((1# * 1#) + 0#) ∙ A)) ⟩
Γ *⟩ Ξ , (1# * 0#) + ((1# * 1#) + 0#) ∙ A , (1# * 1#) + ((1# * 0#) + 0#) ∙ B
-- Step 3. Reduce the complex sum for the usage of B to 1#.
≡⟨ trans (trans (+-identityʳ (1# * 0#)) (*-identityˡ 0#) |> cong ((1# * 1#) +_)) (trans (+-identityʳ (1# * 1#)) (*-identityˡ 1#))
|> cong (Γ *⟩ Ξ , (1# * 0#) + ((1# * 1#) + 0#) ∙ A ,_∙ B) ⟩
Γ *⟩ Ξ , (1# * 0#) + ((1# * 1#) + 0#) ∙ A , 1# ∙ B
-- Step 4. Reduce the complex sum for the usage of A to 1#.
≡⟨ trans (*-identityˡ 0# |> cong (_+ ((1# * 1#) + 0#))) (trans (+-identityˡ ((1# * 1#) + 0#)) (trans (+-identityʳ (1# * 1#)) (*-identityʳ 1#)))
|> cong ((_, 1# ∙ B) ∘ (Γ *⟩ Ξ ,_∙ A)) ⟩
Γ *⟩ Ξ , 1# ∙ A , 1# ∙ B
∎
\end{code}
\begin{code}
lem-⟨⟩ : ∀ {γ δ} {Ξ : Matrix δ γ} → _
lem-⟨⟩ {γ} {δ} {Ξ} =
begin
0s {γ}
≡⟨ *⟩-zeroˡ Ξ |> sym ⟩
0s {δ} *⟩ Ξ
∎
\end{code}
\begin{code}
lem-case⊕ : ∀ {γ δ} (Γ : Context γ) {A : Type} {Ξ : Matrix γ δ} → _
lem-case⊕ {γ} {δ} Γ {A} {Ξ} =
begin
(1# *̇ 0s , 1# * 1# ∙ A) +̇ Γ *⟩ (λ x → Ξ x , 0# ∙ A)
≡⟨ *̇-identityˡ 0s |> cong ((_+̇ Γ *⟩ (λ x → Ξ x , 0# ∙ A)) ∘ (_, 1# * 1# ∙ A)) ⟩
(0s , 1# * 1# ∙ A) +̇ Γ *⟩ (λ x → Ξ x , 0# ∙ A)
≡⟨ *-identityˡ 1# |> cong ((_+̇ Γ *⟩ (λ x → Ξ x , 0# ∙ A)) ∘ (0s ,_∙ A)) ⟩
(0s , 1# ∙ A) +̇ Γ *⟩ (λ x → Ξ x , 0# ∙ A)
≡⟨ *⟩-zeroʳ Γ Ξ |> cong (( 0s , 1# ∙ A) +̇_) ⟩
(0s , 1# ∙ A) +̇ (Γ *⟩ Ξ , 0# ∙ A)
≡⟨⟩
(0s +̇ Γ *⟩ Ξ) , 1# + 0# ∙ A
≡⟨ +̇-identityˡ (Γ *⟩ Ξ) |> cong (_, 1# + 0# ∙ A) ⟩
Γ *⟩ Ξ , 1# + 0# ∙ A
≡⟨ +-identityʳ 1# |> cong (Γ *⟩ Ξ ,_∙ A) ⟩
Γ *⟩ Ξ , 1# ∙ A
∎
\end{code}
\begin{code}
rename : ∀ {γ δ} {Γ : Context γ} {B}
→ (ρ : ∀ {A} → γ ∋ A → δ ∋ A)
→ Γ ⊢ B
---------------------------
→ Γ *⟩ (identity ∘ ρ) ⊢ B
rename ρ (` x) =
Eq.subst (_⊢ _) (lem-` x) (` ρ x)
rename ρ (ƛ_ {Γ = Γ} N) =
ƛ (Eq.subst (_⊢ _) (lem-ƛ Γ) (rename (ext ρ) N))
rename ρ (_·_ {Γ = Γ} {Δ = Δ} L M) =
Eq.subst (_⊢ _) (lem-· Γ Δ) (rename ρ L · rename ρ M)
rename ρ ⟨⟩ =
Eq.subst (_⊢ _) (lem-⟨⟩ {Ξ = identity ∘ ρ}) ⟨⟩
rename ρ (case1 {Γ = Γ} {Δ = Δ} L N) =
Eq.subst (_⊢ _) (lem-, Γ Δ) (case1 (rename ρ L) (rename ρ N))
rename ρ (⟨_,_⟩ {Γ = Γ} {Δ = Δ} L M) =
Eq.subst (_⊢ _) (lem-, Γ Δ) ⟨ rename ρ L , rename ρ M ⟩
rename ρ (case⊗ {Γ = Γ} {Δ = Δ} L N) =
Eq.subst (_⊢ _) (lem-, Γ Δ) (case⊗ (rename ρ L) (Eq.subst (_⊢ _) (lem-case⊗ Δ) (rename (ext (ext ρ)) N)))
rename ρ (inj₁ {Γ = Γ} L) =
inj₁ (rename ρ L)
rename ρ (inj₂ {Γ = Γ} L) =
inj₂ (rename ρ L)
rename ρ (case⊕ {Γ = Γ} {Δ = Δ} L M N) =
Eq.subst (_⊢ _) (lem-, Γ Δ) (case⊕ (rename ρ L) (Eq.subst (_⊢ _) (lem-case⊕ Δ) (rename (ext ρ) M)) (Eq.subst (_⊢ _) (lem-case⊕ Δ) (rename (ext ρ) N)))
\end{code}
# Simultaneous Substitution
Extend a matrix as the identity matrix -- add a zero to the end of every row, and add a new row with a 1 and the rest 0s.
\begin{code}
extm : ∀ {γ δ}
→ Matrix γ δ
--------------------------------
→ (∀ {B} → Matrix (γ , B) (δ , B))
extm Ξ {B} {A} Z = identity Z
extm Ξ {B} {A} (S x) = Ξ x , 0# ∙ B
\end{code}
\begin{code}
exts : ∀ {γ δ} {Ξ : Matrix γ δ}
→ (∀ {A} → (x : γ ∋ A) → Ξ x ⊢ A)
------------------------------------------
→ (∀ {A B} → (x : γ , B ∋ A) → extm Ξ x ⊢ A)
exts {Ξ = Ξ} σ {A} {B} Z = ` Z
exts {Ξ = Ξ} σ {A} {B} (S x) = Eq.subst (_⊢ A) lem (rename S_ (σ x))
where
lem =
begin
Ξ x *⟩ (identity ∘ S_)
≡⟨⟩
Ξ x *⟩ (λ x → identity x , 0# ∙ B)
≡⟨ *⟩-zeroʳ (Ξ x) identity ⟩
(Ξ x *⟩ identity) , 0# ∙ B
≡⟨ *⟩-identityʳ (Ξ x) |> cong (_, 0# ∙ B) ⟩
Ξ x , 0# ∙ B
∎
\end{code}
\begin{code}
subst : ∀ {γ δ} {Γ : Context γ} {Ξ : Matrix γ δ} {B}
→ (σ : ∀ {A} → (x : γ ∋ A) → Ξ x ⊢ A)
→ Γ ⊢ B
--------------------------------------
→ Γ *⟩ Ξ ⊢ B
subst {Ξ = Ξ} σ (` x) =
Eq.subst (_⊢ _) (lem-` x) (σ x)
subst {Ξ = Ξ} σ (ƛ_ {Γ = Γ} N) =
ƛ (Eq.subst (_⊢ _) (lem-ƛ Γ) (subst (exts σ) N))
subst {Ξ = Ξ} σ (_·_ {Γ = Γ} {Δ = Δ} L M) =
Eq.subst (_⊢ _) (lem-· Γ Δ)(subst σ L · subst σ M)
subst {Ξ = Ξ} σ ⟨⟩ =
Eq.subst (_⊢ _) (lem-⟨⟩ {Ξ = Ξ}) ⟨⟩
subst {Ξ = Ξ} σ (case1 {Γ = Γ} {Δ = Δ} L N) =
Eq.subst (_⊢ _) (lem-, Γ Δ) (case1 (subst σ L) (subst σ N))
subst {Ξ = Ξ} σ (⟨_,_⟩ {Γ = Γ} {Δ = Δ} L M) =
Eq.subst (_⊢ _) (lem-, Γ Δ) ⟨ subst σ L , subst σ M ⟩
subst {Ξ = Ξ} σ (case⊗ {Γ = Γ} {Δ = Δ} L N) =
Eq.subst (_⊢ _) (lem-, Γ Δ) (case⊗ (subst σ L) (Eq.subst (_⊢ _) (lem-case⊗ Δ) (subst (exts (exts σ)) N)))
subst {Ξ = Ξ} σ (inj₁ {Γ = Γ} L) =
inj₁ (subst σ L)
subst {Ξ = Ξ} σ (inj₂ {Γ = Γ} L) =
inj₂ (subst σ L)
subst {Ξ = Ξ} σ (case⊕ {Γ = Γ} {Δ = Δ} L M N) =
Eq.subst (_⊢ _) (lem-, Γ Δ) (case⊕ (subst σ L) (Eq.subst (_⊢ _) (lem-case⊕ Δ) (subst (exts σ) M)) (Eq.subst (_⊢ _) (lem-case⊕ Δ) (subst (exts σ) N)))
\end{code}
# Values
\begin{code}
data Value : ∀ {γ} {Γ : Context γ} {A} → Γ ⊢ A → Set where
V-ƛ : ∀ {γ} {Γ : Context γ} {A B} {π} {N : Γ , π ∙ A ⊢ B}
-----------
→ Value (ƛ N)
V-⟨⟩ : ∀ {γ}
--------------
→ Value (⟨⟩ {γ})
V-, : ∀ {γ} {Γ Δ : Context γ} {A B} {L : Γ ⊢ A} {M : Δ ⊢ B}
→ Value L
→ Value M
---------------
→ Value ⟨ L , M ⟩
V-inj₁ : ∀ {γ} {Γ : Context γ} {A B} {L : Γ ⊢ A}
→ Value L
--------------
→ Value (inj₁ {B = B} L)
V-inj₂ : ∀ {γ} {Γ : Context γ} {A B} {L : Γ ⊢ B}
→ Value L
--------------
→ Value (inj₂ {A = A} L)
\end{code}
# Single Substitution
\begin{code}
_⊸[_] : ∀ {γ} {Γ Δ : Context γ} {A B} {π}
→ Γ , π ∙ B ⊢ A
→ Δ ⊢ B
--------------
→ Γ +̇ π *̇ Δ ⊢ A
_⊸[_] {γ} {Γ} {Δ} {A} {B} {π} N M = Eq.subst (_⊢ _) lem (subst σ′ N)
where
Ξ′ : Matrix (γ , B) γ
Ξ′ Z = Δ
Ξ′ (S x) = identity x
σ′ : ∀ {A} → (x : γ , B ∋ A) → Ξ′ x ⊢ A
σ′ Z = M
σ′ (S x) = ` x
lem =
begin
π *̇ Δ +̇ Γ *⟩ identity
≡⟨ +̇-comm (π *̇ Δ) (Γ *⟩ identity) ⟩
Γ *⟩ identity +̇ π *̇ Δ
≡⟨ *⟩-identityʳ Γ |> cong (_+̇ π *̇ Δ) ⟩
Γ +̇ π *̇ Δ
∎
\end{code}
\begin{code}
_1[_] : ∀ {γ} {Γ Δ : Context γ} {A} {V : Γ ⊢ `1}
→ Δ ⊢ A
→ Value V
---------
→ Γ +̇ Δ ⊢ A
_1[_] {Δ = Δ} N V-⟨⟩ = Eq.subst (_⊢ _) lem N
where
lem =
begin
Δ
≡⟨ +̇-identityˡ Δ |> sym ⟩
0s +̇ Δ
∎
\end{code}
\begin{code}
_⊗[_][_] : ∀ {γ} {Γ Δ Θ : Context γ} {A B C}
→ Θ , 1# ∙ A , 1# ∙ B ⊢ C
→ Γ ⊢ A
→ Δ ⊢ B
---------------
→ Γ +̇ Δ +̇ Θ ⊢ C
_⊗[_][_] {γ} {Γ} {Δ} {Θ} {A} {B} {C} N L M = Eq.subst (_⊢ _) lem (subst σ′ N)
where
Ξ′ : Matrix (γ , A , B) γ
Ξ′ Z = Δ
Ξ′ (S Z) = Γ
Ξ′ (S (S x)) = identity x
σ′ : ∀ {D} → (x : γ , A , B ∋ D) → Ξ′ x ⊢ D
σ′ Z = M
σ′ (S Z) = L
σ′ (S (S x)) = ` x
lem =
begin
1# *̇ Δ +̇ (1# *̇ Γ +̇ Θ *⟩ identity)
≡⟨ *⟩-identityʳ Θ |> cong ((1# *̇ Δ +̇_) ∘ (1# *̇ Γ +̇_)) ⟩
1# *̇ Δ +̇ (1# *̇ Γ +̇ Θ)
≡⟨ *̇-identityˡ Γ |> cong ((1# *̇ Δ +̇_) ∘ (_+̇ Θ)) ⟩
1# *̇ Δ +̇ (Γ +̇ Θ)
≡⟨ *̇-identityˡ Δ |> cong (_+̇ (Γ +̇ Θ)) ⟩
Δ +̇ (Γ +̇ Θ)
≡⟨ +̇-assoc Δ Γ Θ |> sym ⟩
(Δ +̇ Γ) +̇ Θ
≡⟨ +̇-comm Δ Γ |> cong (_+̇ Θ) ⟩
(Γ +̇ Δ) +̇ Θ
∎
\end{code}
\begin{code}
_⊕[_] : ∀ {γ} {Γ Δ : Context γ} {A B}
→ Δ , 1# ∙ B ⊢ A
→ Γ ⊢ B
--------------
→ Γ +̇ Δ ⊢ A
_⊕[_] {γ} {Γ} {Δ} {A} {B} N M = Eq.subst (_⊢ _) lem (N ⊸[ M ])
where
lem =
begin
Δ +̇ 1# *̇ Γ
≡⟨ *̇-identityˡ Γ |> cong (Δ +̇_) ⟩
Δ +̇ Γ
≡⟨ +̇-comm Δ Γ ⟩
Γ +̇ Δ
∎
\end{code}
# Reduction
\begin{code}
infix 2 _—→_
data _—→_ : ∀ {γ} {Γ : Context γ} {A} → (Γ ⊢ A) → (Γ ⊢ A) → Set where
ξ-·₁ : ∀ {γ} {Γ Δ : Context γ} {A B} {π} {L L′ : Γ ⊢ [ π ∙ A ]⊸ B} {M : Δ ⊢ A}
→ L —→ L′
-----------------
→ L · M —→ L′ · M
ξ-·₂ : ∀ {γ} {Γ Δ : Context γ} {A B} {π} {V : Γ ⊢ [ π ∙ A ]⊸ B} {M M′ : Δ ⊢ A}
→ Value V
→ M —→ M′
--------------
→ V · M —→ V · M′
ξ-case1 : ∀ {γ} {Γ Δ : Context γ} {A} {L L′ : Γ ⊢ `1} {M : Δ ⊢ A}
→ L —→ L′
-----------------------
→ case1 L M —→ case1 L′ M
ξ-,₁ : ∀ {γ} {Γ Δ : Context γ} {A B} {L L′ : Γ ⊢ A} {M : Δ ⊢ B}
→ L —→ L′
-----------------------
→ ⟨ L , M ⟩ —→ ⟨ L′ , M ⟩
ξ-,₂ : ∀ {γ} {Γ Δ : Context γ} {A B} {V : Γ ⊢ A} {M M′ : Δ ⊢ B}
→ Value V
→ M —→ M′
-----------------------
→ ⟨ V , M ⟩ —→ ⟨ V , M′ ⟩
ξ-case⊗ : ∀ {γ} {Γ Δ : Context γ} {A B C} {L L′ : Γ ⊢ A ⊗ B} {N : Δ , 1# ∙ A , 1# ∙ B ⊢ C}
→ L —→ L′
------------------------
→ case⊗ L N —→ case⊗ L′ N
ξ-inj₁ : ∀ {γ} {Γ : Context γ} {A B} {L L′ : Γ ⊢ A}
→ L —→ L′
---------------------------------
→ inj₁ {B = B} L —→ inj₁ {B = B} L′
ξ-inj₂ : ∀ {γ} {Γ : Context γ} {A B} {L L′ : Γ ⊢ B}
→ L —→ L′
---------------------------------
→ inj₂ {A = A} L —→ inj₂ {A = A} L′
ξ-case⊕ : ∀ {γ} {Γ Δ : Context γ} {A B C} {L L′ : Γ ⊢ A ⊕ B} {M : Δ , 1# ∙ A ⊢ C} {N : Δ , 1# ∙ B ⊢ C}
→ L —→ L′
---------------------------
→ case⊕ L M N —→ case⊕ L′ M N
β-⊸ : ∀ {γ} {Γ Δ : Context γ} {A B} {π} {N : Γ , π ∙ A ⊢ B} {W : Δ ⊢ A}
→ (VW : Value W)
--------------------
→ (ƛ N) · W —→ N ⊸[ W ]
β-1 : ∀ {γ} {Γ Δ : Context γ} {A} {V : Γ ⊢ `1} {N : Δ ⊢ A}
→ (VV : Value V)
----------------------
→ case1 V N —→ N 1[ VV ]
β-⊗ : ∀ {γ} {Γ Δ Θ : Context γ} {A B C} {V : Γ ⊢ A} {W : Δ ⊢ B} {N : Θ , 1# ∙ A , 1# ∙ B ⊢ C}
→ (VV : Value V)
→ (VW : Value W)
---------------------------------
→ case⊗ ⟨ V , W ⟩ N —→ N ⊗[ V ][ W ]
β-⊕₁ : ∀ {γ} {Γ Δ : Context γ} {A B C} {V : Γ ⊢ A} {M : Δ , 1# ∙ A ⊢ C} {N : Δ , 1# ∙ B ⊢ C}
→ (VV : Value V)
-----------------------------
→ case⊕ (inj₁ V) M N —→ M ⊕[ V ]
β-⊕₂ : ∀ {γ} {Γ Δ : Context γ} {A B C} {V : Γ ⊢ B} {M : Δ , 1# ∙ A ⊢ C} {N : Δ , 1# ∙ B ⊢ C}
→ (VV : Value V)
-----------------------------
→ case⊕ (inj₂ V) M N —→ N ⊕[ V ]
\end{code}
# Progress
\begin{code}
data Progress {γ} {Γ : Context γ} {A} (M : Γ ⊢ A) : Set where
step : {N : Γ ⊢ A}
→ M —→ N
----------
→ Progress M
done :
Value M
----------
→ Progress M
\end{code}
\begin{code}
progress : ∀ {A} → (M : ∅ ⊢ A) → Progress M
progress M = go refl M
where
go : ∀ {γ} {Γ : Context γ} {A} → γ ≡ ∅ → (M : Γ ⊢ A) → Progress M
go refl (` ())
go refl (ƛ N) = done V-ƛ
go refl (L · M) with go refl L
... | step L—→L′ = step (ξ-·₁ L—→L′)
... | done V-ƛ with go refl M
... | step M—→M′ = step (ξ-·₂ V-ƛ M—→M′)
... | done V-M = step (β-⊸ V-M)
go refl ⟨⟩ = done V-⟨⟩
go refl (case1 L N) with go refl L
... | step L—→L′ = step (ξ-case1 L—→L′)
... | done V-L = step (β-1 V-L)
go refl ⟨ L , M ⟩ with go refl L
... | step L—→L′ = step (ξ-,₁ L—→L′)
... | done V-L with go refl M
... | step M—→M′ = step (ξ-,₂ V-L M—→M′)
... | done V-M = done (V-, V-L V-M)
go refl (case⊗ L N) with go refl L
... | step L—→L′ = step (ξ-case⊗ L—→L′)
... | done (V-, V-L V-M) = step (β-⊗ V-L V-M)
go refl (inj₁ L) with go refl L
... | step L—→L′ = step (ξ-inj₁ L—→L′)
... | done V-L = done (V-inj₁ V-L)
go refl (inj₂ L) with go refl L
... | step L—→L′ = step (ξ-inj₂ L—→L′)
... | done V-L = done (V-inj₂ V-L)
go refl (case⊕ L M N) with go refl L
... | step L—→L′ = step (ξ-case⊕ L—→L′)
... | done (V-inj₁ V-L) = step (β-⊕₁ V-L)
... | done (V-inj₂ V-L) = step (β-⊕₂ V-L)
\end{code}