module A201802.WIP.LR2 where open import A201801.Prelude open import A201801.Category open import A201801.Fin open import A201801.FinLemmas open import A201801.Vec open import A201801.VecLemmas open import A201801.AllVec open import A201802.LR0 open import A201802.LR0Lemmas open import A201802.LR1 -------------------------------------------------------------------------------- -- `Val M` says that the term `M` is a value. data Val {g} : Term g → Set where instance val-lam : ∀ {M} → Val (LAM M) val-pair : ∀ {M N} → {{_ : Val M}} {{_ : Val N}} → Val (PAIR M N) val-unit : Val UNIT val-left : ∀ {M} → {{_ : Val M}} → Val (LEFT M) val-right : ∀ {M} → {{_ : Val M}} → Val (RIGHT M) val-true : Val TRUE val-false : Val FALSE -- `Vals τ` says that all terms `τ` are values. data Vals {g} : ∀ {n} → Terms g n → Set where instance ∙ : Vals ∙ _,_ : ∀ {n M} → {τ : Terms g n} → Vals τ → Val M → Vals (τ , M) hm : (M : Term 0) (VM : Val M) → ¬ (∙ ⊢ M ⦂ 𝟘) hm (VAR I) () hm (LAM M) val-lam = λ () hm (APP M N) () hm (PAIR M N) (val-pair) = λ () hm (FST M) () hm (SND M) () hm UNIT val-unit = λ () hm (ABORT M) () hm (LEFT M) (val-left {{VM}}) = λ () hm (RIGHT M) (val-right {{VN}}) = λ () hm (CASE M N O) () hm TRUE val-true = λ () hm FALSE val-false = λ () hm (IF M N O) () -- -------------------------------------------------------------------------------- -- -- `_⤠_` is the CBV computation relation. -- infix 3 _⤠_ -- data _⤠_ {g} : Term g → Term g → Set -- where -- app-lam : ∀ {M N} → {{_ : Val N}} → APP (LAM M) N ⤠ CUT N M -- fst-pair : ∀ {M N} → {{_ : Val M}} {{_ : Val N}} → FST (PAIR M N) ⤠ M -- snd-pair : ∀ {M N} → {{_ : Val M}} {{_ : Val N}} → SND (PAIR M N) ⤠ N -- case-left : ∀ {M N O} → {{_ : Val M}} → CASE (LEFT M) N O ⤠ CUT M N -- case-right : ∀ {M N O} → {{_ : Val M}} → CASE (RIGHT M) N O ⤠ CUT M O -- if-true : ∀ {N O} → IF TRUE N O ⤠ N -- if-false : ∀ {N O} → IF FALSE N O ⤠ O -- -- Values do not compute. -- ¬val⤠ : ∀ {g} → {M M′ : Term g} → {{_ : Val M}} -- → ¬ (M ⤠ M′) -- ¬val⤠ {{val-lam}} () -- ¬val⤠ {{val-pair}} () -- ¬val⤠ {{val-unit}} () -- ¬val⤠ {{val-left}} () -- ¬val⤠ {{val-right}} () -- ¬val⤠ {{val-true}} () -- ¬val⤠ {{val-false}} () -- -- Computation is deterministic. -- det⤠ : ∀ {g} → {M M′₁ M′₂ : Term g} -- → M ⤠ M′₁ → M ⤠ M′₂ -- → M′₁ ≡ M′₂ -- det⤠ app-lam app-lam = refl -- det⤠ fst-pair fst-pair = refl -- det⤠ snd-pair snd-pair = refl -- det⤠ case-left case-left = refl -- det⤠ case-right case-right = refl -- det⤠ if-true if-true = refl -- det⤠ if-false if-false = refl -- -- Computation is type-preserving. -- tp⤠ : ∀ {g M M′ A} → {Γ : Types g} -- → M ⤠ M′ → Γ ⊢ M ⦂ A -- → Γ ⊢ M′ ⦂ A -- tp⤠ app-lam (app (lam 𝒟) ℰ) = cut ℰ 𝒟 -- tp⤠ fst-pair (fst (pair 𝒟 ℰ)) = 𝒟 -- tp⤠ snd-pair (snd (pair 𝒟 ℰ)) = ℰ -- tp⤠ case-left (case (left 𝒟) ℰ ℱ) = cut 𝒟 ℰ -- tp⤠ case-right (case (right 𝒟) ℰ ℱ) = cut 𝒟 ℱ -- tp⤠ if-true (if 𝒟 ℰ ℱ) = ℰ -- tp⤠ if-false (if 𝒟 ℰ ℱ) = ℱ -- -------------------------------------------------------------------------------- -- -- `_↦_` is the CBV small-step reduction relation. -- infix 3 _↦_ -- data _↦_ {g} : Term g → Term g → Set -- where -- red : ∀ {M M′} → M ⤠ M′ -- → M ↦ M′ -- cong-app₁ : ∀ {M M′ N} → M ↦ M′ -- → APP M N ↦ APP M′ N -- cong-app₂ : ∀ {M N N′} → {{_ : Val M}} -- → N ↦ N′ -- → APP M N ↦ APP M N′ -- cong-pair₁ : ∀ {M M′ N} → M ↦ M′ -- → PAIR M N ↦ PAIR M′ N -- cong-pair₂ : ∀ {M N N′} → {{_ : Val M}} -- → N ↦ N′ -- → PAIR M N ↦ PAIR M N′ -- cong-fst : ∀ {M M′} → M ↦ M′ -- → FST M ↦ FST M′ -- cong-snd : ∀ {M M′} → M ↦ M′ -- → SND M ↦ SND M′ -- cong-abort : ∀ {M M′} → M ↦ M′ -- → ABORT M ↦ ABORT M′ -- cong-left : ∀ {M M′} → M ↦ M′ -- → LEFT M ↦ LEFT M′ -- cong-right : ∀ {M M′} → M ↦ M′ -- → RIGHT M ↦ RIGHT M′ -- cong-case : ∀ {M M′ N O} → M ↦ M′ -- → CASE M N O ↦ CASE M′ N O -- cong-if : ∀ {M M′ N O} → M ↦ M′ -- → IF M N O ↦ IF M′ N O -- -- Values do not reduce. -- ¬val↦ : ∀ {g} → {M M′ : Term g} → {{_ : Val M}} -- → ¬ (M ↦ M′) -- ¬val↦ {{val-lam}} (red ()) -- ¬val↦ {{val-pair}} (red ()) -- ¬val↦ {{val-pair}} (cong-pair₁ M↦M′) = M↦M′ ↯ ¬val↦ -- ¬val↦ {{val-pair}} (cong-pair₂ N↦N′) = N↦N′ ↯ ¬val↦ -- ¬val↦ {{val-unit}} (red ()) -- ¬val↦ {{val-left}} (red ()) -- ¬val↦ {{val-left}} (cong-left M↦M′) = M↦M′ ↯ ¬val↦ -- ¬val↦ {{val-right}} (red ()) -- ¬val↦ {{val-right}} (cong-right M↦M′) = M↦M′ ↯ ¬val↦ -- ¬val↦ {{val-true}} (red ()) -- ¬val↦ {{val-false}} (red ()) -- -- Computation determines small-step reduction. -- red-det↦ : ∀ {g} → {M M′₁ M′₂ : Term g} -- → M ⤠ M′₁ → M ↦ M′₂ -- → M′₁ ≡ M′₂ -- red-det↦ M⤠M′₁ (red M⤠M′₂) = det⤠ M⤠M′₁ M⤠M′₂ -- red-det↦ app-lam (cong-app₁ M↦M′₂) = M↦M′₂ ↯ ¬val↦ -- red-det↦ app-lam (cong-app₂ M↦M′₂) = M↦M′₂ ↯ ¬val↦ -- red-det↦ fst-pair (cong-fst M↦M′₂) = M↦M′₂ ↯ ¬val↦ -- red-det↦ snd-pair (cong-snd M↦M′₂) = M↦M′₂ ↯ ¬val↦ -- red-det↦ case-left (cong-case M↦M′₂) = M↦M′₂ ↯ ¬val↦ -- red-det↦ case-right (cong-case M↦M′₂) = M↦M′₂ ↯ ¬val↦ -- red-det↦ if-true (cong-if M↦M′₂) = M↦M′₂ ↯ ¬val↦ -- red-det↦ if-false (cong-if M↦M′₂) = M↦M′₂ ↯ ¬val↦ -- red-det↦ () (cong-pair₁ _) -- red-det↦ () (cong-pair₂ _) -- red-det↦ () (cong-abort _) -- red-det↦ () (cong-left _) -- red-det↦ () (cong-right _) -- -- Small-step reduction is deterministic. -- det↦ : ∀ {g} → {M M′₁ M′₂ : Term g} -- → M ↦ M′₁ → M ↦ M′₂ -- → M′₁ ≡ M′₂ -- det↦ (red M⤠M′₁) M↦M′₂ = red-det↦ M⤠M′₁ M↦M′₂ -- det↦ (cong-app₁ M↦M′₁) (cong-app₁ M↦M′₂) = (\ M′ → APP M′ _) & det↦ M↦M′₁ M↦M′₂ -- det↦ (cong-app₁ M↦M′₁) (cong-app₂ _) = M↦M′₁ ↯ ¬val↦ -- det↦ (cong-app₂ _) (cong-app₁ M↦M′₂) = M↦M′₂ ↯ ¬val↦ -- det↦ (cong-app₂ N↦N′₁) (cong-app₂ N↦N′₂) = (\ N′ → APP _ N′) & det↦ N↦N′₁ N↦N′₂ -- det↦ (cong-pair₁ M↦M′₁) (cong-pair₁ M↦M′₂) = (\ M′ → PAIR M′ _) & det↦ M↦M′₁ M↦M′₂ -- det↦ (cong-pair₁ M↦M′₁) (cong-pair₂ _) = M↦M′₁ ↯ ¬val↦ -- det↦ (cong-pair₂ _) (cong-pair₁ M↦M′₂) = M↦M′₂ ↯ ¬val↦ -- det↦ (cong-pair₂ N↦N′₁) (cong-pair₂ N↦N′₂) = (\ N′ → PAIR _ N′) & det↦ N↦N′₁ N↦N′₂ -- det↦ (cong-fst M↦M′₁) (cong-fst M↦M′₂) = FST & det↦ M↦M′₁ M↦M′₂ -- det↦ (cong-snd M↦M′₁) (cong-snd M↦M′₂) = SND & det↦ M↦M′₁ M↦M′₂ -- det↦ (cong-abort M↦M′₁) (cong-abort M↦M′₂) = ABORT & det↦ M↦M′₁ M↦M′₂ -- det↦ (cong-left M↦M′₁) (cong-left M↦M′₂) = LEFT & det↦ M↦M′₁ M↦M′₂ -- det↦ (cong-right M↦M′₁) (cong-right M↦M′₂) = RIGHT & det↦ M↦M′₁ M↦M′₂ -- det↦ (cong-case M↦M′₁) (cong-case M↦M′₂) = (\ M′ → CASE M′ _ _) & det↦ M↦M′₁ M↦M′₂ -- det↦ (cong-if M↦M′₁) (cong-if M↦M′₂) = (\ M′ → IF M′ _ _) & det↦ M↦M′₁ M↦M′₂ -- det↦ M↦M′₁ (red M⤠M′₂) = red-det↦ M⤠M′₂ M↦M′₁ ⁻¹ -- -- Small-step reduction is type-preserving. -- tp↦ : ∀ {g M M′ A} → {Γ : Types g} -- → M ↦ M′ → Γ ⊢ M ⦂ A -- → Γ ⊢ M′ ⦂ A -- tp↦ (red M⤠M′) 𝒟 = tp⤠ M⤠M′ 𝒟 -- tp↦ (cong-app₁ M↦M′) (app 𝒟 ℰ) = app (tp↦ M↦M′ 𝒟) ℰ -- tp↦ (cong-app₂ M↦M′) (app 𝒟 ℰ) = app 𝒟 (tp↦ M↦M′ ℰ) -- tp↦ (cong-pair₁ M↦M′) (pair 𝒟 ℰ) = pair (tp↦ M↦M′ 𝒟) ℰ -- tp↦ (cong-pair₂ N↦N′) (pair 𝒟 ℰ) = pair 𝒟 (tp↦ N↦N′ ℰ) -- tp↦ (cong-fst M↦M′) (fst 𝒟) = fst (tp↦ M↦M′ 𝒟) -- tp↦ (cong-snd M↦M′) (snd 𝒟) = snd (tp↦ M↦M′ 𝒟) -- tp↦ (cong-abort M↦M′) (abort 𝒟) = abort (tp↦ M↦M′ 𝒟) -- tp↦ (cong-left M↦M′) (left 𝒟) = left (tp↦ M↦M′ 𝒟) -- tp↦ (cong-right M↦M′) (right 𝒟) = right (tp↦ M↦M′ 𝒟) -- tp↦ (cong-case M↦M′) (case 𝒟 ℰ ℱ) = case (tp↦ M↦M′ 𝒟) ℰ ℱ -- tp↦ (cong-if M↦M′) (if 𝒟 ℰ ℱ) = if (tp↦ M↦M′ 𝒟) ℰ ℱ -- -------------------------------------------------------------------------------- -- -- `_⤅_` is the iterated small-step reduction relation. -- infix 3 _⤅_ -- data _⤅_ {g} : Term g → Term g → Set -- where -- -- Iterated small-step reduction is reflexive. -- done : ∀ {M} → M ⤅ M -- -- Small-step reduction IN REVERSE preserves iterated small-step reduction. -- step : ∀ {M M′ M″} → M ↦ M′ → M′ ⤅ M″ -- → M ⤅ M″ -- -- Iterated small-step reduction is transitive. -- -- Iterated small-step reduction IN REVERSE preserves iterated small-step reduction. -- steps : ∀ {g} → {M M′ M″ : Term g} -- → M ⤅ M′ → M′ ⤅ M″ -- → M ⤅ M″ -- steps done M⤅M″ = M⤅M″ -- steps (step M↦M‴ M‴⤅M′) M′⤅M″ = step M↦M‴ (steps M‴⤅M′ M′⤅M″) -- -- When reducing down to a value, the initial small step determines the subsequent small steps. -- -- Small-step reduction preserves iterated small-step reduction down to a value. -- unstep : ∀ {g} → {M M′ M″ : Term g} → {{_ : Val M″}} -- → M ↦ M′ → M ⤅ M″ -- → M′ ⤅ M″ -- unstep M↦M′₁ (step M↦M′₂ M′₂⤅M″) with det↦ M↦M′₁ M↦M′₂ -- unstep M↦M′ (step _ M′⤅M″) | refl = M′⤅M″ -- unstep M↦M′ done = M↦M′ ↯ ¬val↦ -- -- When reducing down to a value, iterated small-step reduction is deterministic. -- det⤅ : ∀ {g} → {M M′₁ M′₂ : Term g} → {{_ : Val M′₁}} {{_ : Val M′₂}} -- → M ⤅ M′₁ → M ⤅ M′₂ -- → M′₁ ≡ M′₂ -- det⤅ done done = refl -- det⤅ done (step M↦M″ M″⤅M′) = M↦M″ ↯ ¬val↦ -- det⤅ (step M↦M″₁ M″₁⤅M′₁) M⤅M′₂ = det⤅ M″₁⤅M′₁ (unstep M↦M″₁ M⤅M′₂) -- -- Iterated small-step reduction is type-preserving. -- tp⤅ : ∀ {g M M′ A} → {Γ : Types g} -- → M ⤅ M′ → Γ ⊢ M ⦂ A -- → Γ ⊢ M′ ⦂ A -- tp⤅ done 𝒟 = 𝒟 -- tp⤅ (step M↦M″ M″⤅M′) 𝒟 = tp⤅ M″⤅M′ (tp↦ M↦M″ 𝒟) -- -- If `M` reduces to `M′`, then `APP M N` reduces to `APP M′ N`. -- congs-app₁ : ∀ {g} → {M M′ N : Term g} -- → M ⤅ M′ -- → APP M N ⤅ APP M′ N -- congs-app₁ done = done -- congs-app₁ (step M↦M″ M″⤅M′) = step (cong-app₁ M↦M″) (congs-app₁ M″⤅M′) -- -- If `N` reduces to `N′`, then `APP (LAM M) N` reduces to `APP (LAM M) N′`. -- congs-app₂ : ∀ {g} → {M : Term (suc g)} {N N′ : Term g} -- → N ⤅ N′ -- → APP (LAM M) N ⤅ APP (LAM M) N′ -- congs-app₂ done = done -- congs-app₂ (step M↦M″ M″⤅M′) = step (cong-app₂ M↦M″) (congs-app₂ M″⤅M′) -- -- If `M` reduces to `M′` and `N` reduces to `N′`, then `PAIR M N` reduces to `PAIR M′ N′`. -- congs-pair : ∀ {g} → {M M′ N N′ : Term g} → {{_ : Val M′}} {{_ : Val N′}} -- → M ⤅ M′ → N ⤅ N′ -- → PAIR M N ⤅ PAIR M′ N′ -- congs-pair done done = done -- congs-pair done (step N↦N″ N″⤅N′) = step (cong-pair₂ N↦N″) (congs-pair done N″⤅N′) -- congs-pair (step M↦M″ M″⤅M′) N⤅N′ = step (cong-pair₁ M↦M″) (congs-pair M″⤅M′ N⤅N′) -- -- If `M` reduces to `M′`, then `FST M` reduces to `FST M′`. -- congs-fst : ∀ {g} → {M M′ : Term g} -- → M ⤅ M′ -- → FST M ⤅ FST M′ -- congs-fst done = done -- congs-fst (step M↦M″ M″⤅M′) = step (cong-fst M↦M″) (congs-fst M″⤅M′) -- -- If `M` reduces to `M′`, then `SND M` reduces to `SND M′`. -- congs-snd : ∀ {g} → {M M′ : Term g} -- → M ⤅ M′ -- → SND M ⤅ SND M′ -- congs-snd done = done -- congs-snd (step M↦M″ M″⤅M′) = step (cong-snd M↦M″) (congs-snd M″⤅M′) -- -- If `M` reduces to `M′`, then `LEFT M` reduces to `LEFT M′`. -- congs-left : ∀ {g} → {M M′ : Term g} → {{_ : Val M′}} -- → M ⤅ M′ -- → LEFT M ⤅ LEFT M′ -- congs-left done = done -- congs-left (step M↦M″ M″⤅M′) = step (cong-left M↦M″) (congs-left M″⤅M′) -- -- If `M` reduces to `M′`, then `RIGHT M` reduces to `RIGHT M′`. -- congs-right : ∀ {g} → {M M′ : Term g} → {{_ : Val M′}} -- → M ⤅ M′ -- → RIGHT M ⤅ RIGHT M′ -- congs-right done = done -- congs-right (step M↦M″ M″⤅M′) = step (cong-right M↦M″) (congs-right M″⤅M′) -- -- If `M` reduces to `M′`, then `CASE M N O` reduces to `CASE M′ N O`. -- congs-case : ∀ {g} → {M M′ : Term g} {N O : Term (suc g)} -- → M ⤅ M′ -- → CASE M N O ⤅ CASE M′ N O -- congs-case done = done -- congs-case (step M↦M″ M″⤅M′) = step (cong-case M↦M″) (congs-case M″⤅M′) -- -- If `M` reduces to `M′`, then `IF M N O` reduces to `IF M′ N O`. -- congs-if : ∀ {g} → {M M′ N O : Term g} -- → M ⤅ M′ -- → IF M N O ⤅ IF M′ N O -- congs-if done = done -- congs-if (step M↦M″ M″⤅M′) = step (cong-if M↦M″) (congs-if M″⤅M′) -- -- If `M` reduces to `PAIR M′ N′`, then `FST M` reduces to `M′`. -- reds-fst-pair : ∀ {g} → {M M′ N′ : Term g} → {{_ : Val M′}} {{_ : Val N′}} -- → M ⤅ PAIR M′ N′ -- → FST M ⤅ M′ -- reds-fst-pair M⤅PAIR = steps (congs-fst M⤅PAIR) (step (red fst-pair) done) -- -- If `M` reduces to `PAIR M′ N′`, then `SND M` reduces to `N′`. -- reds-snd-pair : ∀ {g} → {M M′ N′ : Term g} → {{_ : Val M′}} {{_ : Val N′}} -- → M ⤅ PAIR M′ N′ -- → SND M ⤅ N′ -- reds-snd-pair M⤅PAIR = steps (congs-snd M⤅PAIR) (step (red snd-pair) done) -- -- If `M` reduces to `TRUE` and `N` reduces to `N′`, then `IF M N O` reduces to `N′`. -- reds-if-true : ∀ {g} → {M N N′ O : Term g} -- → M ⤅ TRUE → N ⤅ N′ -- → IF M N O ⤅ N′ -- reds-if-true M⤅TRUE N⤅N′ = steps (congs-if M⤅TRUE) (step (red if-true) N⤅N′) -- -- If `M` reduces to `FALSE` and `O` reduces to `O′`, then `IF M N O` reduces to `O′`. -- reds-if-false : ∀ {g} → {M N O O′ : Term g} -- → M ⤅ FALSE → O ⤅ O′ -- → IF M N O ⤅ O′ -- reds-if-false M⤅FALSE N⤅N′ = steps (congs-if M⤅FALSE) (step (red if-false) N⤅N′) -- -------------------------------------------------------------------------------- -- -- `_⇓_` is the big-step reduction relation. -- infix 3 _⇓_ -- _⇓_ : ∀ {g} → Term g → Term g → Set -- M ⇓ M′ = M ⤅ M′ × Val M′ -- -- A big step can be extended with an initial small step. -- -- Small-step reduction IN REVERSE preserves big-step reduction. -- big-step : ∀ {g} → {M M′ M″ : Term g} -- → M ↦ M′ → M′ ⇓ M″ -- → M ⇓ M″ -- big-step M↦M′ (M′⤅M″ , VM″) = step M↦M′ M′⤅M″ , VM″ -- -- The initial small step determines the subsequent big step. -- -- Small-step reduction preserves big-step reduction. -- big-unstep : ∀ {g} → {M M′ M″ : Term g} -- → M ↦ M′ → M ⇓ M″ -- → M′ ⇓ M″ -- big-unstep M↦M′ (M′⤅M″ , VM″) = unstep {{VM″}} M↦M′ M′⤅M″ , VM″ -- -- Big-step reduction is deterministic. -- det⇓ : ∀ {g} → {M M′₁ M′₂ : Term g} -- → M ⇓ M′₁ → M ⇓ M′₂ -- → M′₁ ≡ M′₂ -- det⇓ (M⤅M′₁ , VM′₁) (M⤅M′₂ , VM′₂) = det⤅ {{VM′₁}} {{VM′₂}} M⤅M′₁ M⤅M′₂ -- -- If `M` reduces to `M′` and `N` reduces to `N′`, then `PAIR M N` reduces to `PAIR M′ N′`. -- big-red-pair : ∀ {g} → {M M′ N N′ : Term g} -- → M ⇓ M′ → N ⇓ N′ -- → PAIR M N ⇓ PAIR M′ N′ -- big-red-pair (M⤅M′ , VM′) (N⤅N′ , VN′) = congs-pair {{VM′}} {{VN′}} M⤅M′ N⤅N′ , val-pair {{VM′}} {{VN′}} -- -- If `M` reduces to `PAIR M′ N′`, then `FST M` reduces to `M′`. -- big-red-fst-pair : ∀ {g} → {M M′ N′ : Term g} → {{_ : Val M′}} {{_ : Val N′}} -- → M ⤅ PAIR M′ N′ -- → FST M ⇓ M′ -- big-red-fst-pair {{VM′}} M⤅PAIR = reds-fst-pair M⤅PAIR , VM′ -- -- If `M` reduces to `PAIR M′ N′`, then `SND M` reduces to `N′`. -- big-red-snd-pair : ∀ {g} → {M M′ N′ : Term g} → {{_ : Val M′}} {{_ : Val N′}} -- → M ⤅ PAIR M′ N′ -- → SND M ⇓ N′ -- big-red-snd-pair {{_}} {{VN′}} M⤅PAIR = reds-snd-pair M⤅PAIR , VN′ -- -- If `M` reduces to `M′`, then `LEFT M` reduces to `LEFT M′`. -- big-red-left : ∀ {g} → {M M′ : Term g} -- → M ⇓ M′ -- → LEFT M ⇓ LEFT M′ -- big-red-left (M⤅M′ , VM′) = congs-left {{VM′}} M⤅M′ , val-left {{VM′}} -- -- If `M` reduces to `M′`, then `RIGHT M` reduces to `RIGHT M′`. -- big-red-right : ∀ {g} → {M M′ : Term g} -- → M ⇓ M′ -- → RIGHT M ⇓ RIGHT M′ -- big-red-right (M⤅M′ , VM′) = congs-right {{VM′}} M⤅M′ , val-right {{VM′}} -- -- If `M` reduces to `TRUE` and `N` reduces to `N′`, then `IF M N O` reduces to `N′`. -- big-red-if-true : ∀ {g} → {M N N′ O : Term g} -- → M ⤅ TRUE → N ⇓ N′ -- → IF M N O ⇓ N′ -- big-red-if-true M⤅TRUE (N⤅N′ , VN′) = reds-if-true M⤅TRUE N⤅N′ , VN′ -- -- If `M` reduces to `FALSE` and `O` reduces to `O′`, then `IF M N O` reduces to `O′`. -- big-red-if-false : ∀ {g} → {M N O O′ : Term g} -- → M ⤅ FALSE → O ⇓ O′ -- → IF M N O ⇓ O′ -- big-red-if-false M⤅FALSE (O⤅O′ , VO′) = reds-if-false M⤅FALSE O⤅O′ , VO′ -- -------------------------------------------------------------------------------- -- -- `_⇓` is the CBV termination relation. -- _⇓ : ∀ {g} → Term g → Set -- M ⇓ = Σ (Term _) (\ M′ → M ⇓ M′) -- -- Small-step reduction IN REVERSE preserves termination. -- -- Reversed small-step reduction is halt-preserving. -- hpr↦ : ∀ {g} → {M M′ : Term g} -- → M ↦ M′ → M′ ⇓ -- → M ⇓ -- hpr↦ M↦M′ (M″ , M′⇓M″) = M″ , big-step M↦M′ M′⇓M″ -- -- Small-step reduction preserves termination. -- -- Small-step reduction is halt-preserving. -- hp↦ : ∀ {g} → {M M′ : Term g} -- → M ↦ M′ → M ⇓ -- → M′ ⇓ -- hp↦ M↦M′ (M″ , M′⇓M″) = M″ , big-unstep M↦M′ M′⇓M″ -- -- If `M` terminates and `N` terminates, then `PAIR M N` terminates. -- halt-pair : ∀ {g} → {M N : Term g} -- → M ⇓ → N ⇓ -- → PAIR M N ⇓ -- halt-pair (M′ , M⇓M′) (N′ , N⇓N′) = PAIR M′ N′ , big-red-pair M⇓M′ N⇓N′ -- -- If `M` reduces to `PAIR M′ N′`, then `FST M` terminates. -- halt-fst-pair : ∀ {g} → {M M′ N′ : Term g} → {{_ : Val M′}} {{_ : Val N′}} -- → M ⤅ PAIR M′ N′ -- → FST M ⇓ -- halt-fst-pair {M′ = M′} M⤅PAIR = M′ , big-red-fst-pair M⤅PAIR -- -- If `M` reduces to `PAIR M′ N′`, then `SND M` terminates. -- halt-snd-pair : ∀ {g} → {M M′ N′ : Term g} → {{_ : Val M′}} {{_ : Val N′}} -- → M ⤅ PAIR M′ N′ -- → SND M ⇓ -- halt-snd-pair {N′ = N′} M⤅PAIR = N′ , big-red-snd-pair M⤅PAIR -- -- If `M` terminates, then `FST M` terminates. -- halt-fst : ∀ {g M A B} → {Γ : Types g} -- → Γ ⊢ M ⦂ A ∧ B → M ⇓ -- → FST M ⇓ -- halt-fst 𝒟 (M′ , M⤅M′ , VM′) with tp⤅ M⤅M′ 𝒟 -- halt-fst 𝒟 (LAM _ , _ , val-lam) | () -- halt-fst 𝒟 (PAIR _ _ , M⤅PAIR , val-pair) | pair _ _ = halt-fst-pair M⤅PAIR -- halt-fst 𝒟 (UNIT , _ , val-unit) | () -- halt-fst 𝒟 (LEFT _ , _ , val-left) | () -- halt-fst 𝒟 (RIGHT _ , _ , val-right) | () -- halt-fst 𝒟 (TRUE , _ , val-true) | () -- halt-fst 𝒟 (FALSE , _ , val-false) | () -- -- If `M` terminates, then `SND M` terminates. -- halt-snd : ∀ {g M A B} → {Γ : Types g} -- → Γ ⊢ M ⦂ A ∧ B → M ⇓ -- → SND M ⇓ -- halt-snd 𝒟 (M′ , M⤅M′ , VM′) with tp⤅ M⤅M′ 𝒟 -- halt-snd 𝒟 (LAM _ , _ , val-lam) | () -- halt-snd 𝒟 (PAIR _ _ , M⤅PAIR , val-pair) | pair _ _ = halt-snd-pair M⤅PAIR -- halt-snd 𝒟 (UNIT , _ , val-unit) | () -- halt-snd 𝒟 (LEFT _ , _ , val-left) | () -- halt-snd 𝒟 (RIGHT _ , _ , val-right) | () -- halt-snd 𝒟 (TRUE , _ , val-true) | () -- halt-snd 𝒟 (FALSE , _ , val-false) | () -- -- If `M` terminates, then `ABORT M` terminates. -- halt-abort : ∀ {g M} → {Γ : Types g} -- → Γ ⊢ M ⦂ 𝟘 → M ⇓ -- → ABORT M ⇓ -- halt-abort 𝒟 (M′ , M⤅M′ , VM′) with tp⤅ M⤅M′ 𝒟 -- halt-abort 𝒟 (LAM _ , _ , val-lam) | () -- halt-abort 𝒟 (PAIR _ _ , _ , val-pair) | () -- halt-abort 𝒟 (UNIT , _ , val-unit) | () -- halt-abort 𝒟 (LEFT _ , _ , val-left) | () -- halt-abort 𝒟 (RIGHT _ , _ , val-right) | () -- halt-abort 𝒟 (TRUE , _ , val-true) | () -- halt-abort 𝒟 (FALSE , _ , val-false) | () -- -- If `M` terminates, then `LEFT M` terminates. -- halt-left : ∀ {g} → {M : Term g} -- → M ⇓ -- → LEFT M ⇓ -- halt-left (M′ , M⇓M′) = LEFT M′ , big-red-left M⇓M′ -- -- If `M` terminates, then `RIGHT M` terminates. -- halt-right : ∀ {g} → {M : Term g} -- → M ⇓ -- → RIGHT M ⇓ -- halt-right (M′ , M⇓M′) = RIGHT M′ , big-red-right M⇓M′ -- -- If `M` reduces to `TRUE` and `N` terminates, then `IF M N O` terminates. -- halt-if-true : ∀ {g} → {M N O : Term g} -- → M ⤅ TRUE → N ⇓ -- → IF M N O ⇓ -- halt-if-true M⤅TRUE (N′ , N⇓N′) = N′ , big-red-if-true M⤅TRUE N⇓N′ -- -- If `M` reduces to `FALSE` and `O` terminates, then `IF M N O` terminates. -- halt-if-false : ∀ {g} → {M N O : Term g} -- → M ⤅ FALSE → O ⇓ -- → IF M N O ⇓ -- halt-if-false M⤅FALSE (O′ , O⇓O′) = O′ , big-red-if-false M⤅FALSE O⇓O′ -- -- If `M` terminates and `N` terminates and `O` terminates, then `IF M N O` terminates. -- halt-if : ∀ {g M N O} → {Γ : Types g} -- → Γ ⊢ M ⦂ 𝔹 → M ⇓ → N ⇓ → O ⇓ -- → IF M N O ⇓ -- halt-if 𝒟 (M′ , M⤅M′ , VM′) N⇓ O⇓ with tp⤅ M⤅M′ 𝒟 -- halt-if 𝒟 (LAM _ , _ , val-lam) N⇓ O⇓ | () -- halt-if 𝒟 (PAIR _ _ , _ , val-pair) N⇓ O⇓ | () -- halt-if 𝒟 (UNIT , _ , val-unit) N⇓ O⇓ | () -- halt-if 𝒟 (LEFT _ , _ , val-left) N⇓ O⇓ | () -- halt-if 𝒟 (RIGHT _ , _ , val-right) N⇓ O⇓ | () -- halt-if 𝒟 (TRUE , M⤅TRUE , val-true) N⇓ O⇓ | true = halt-if-true M⤅TRUE N⇓ -- halt-if 𝒟 (FALSE , M⤅FALSE , val-false) N⇓ O⇓ | false = halt-if-false M⤅FALSE O⇓ -- -- Every well-typed term terminates. -- -- Impossible without a stronger induction hypothesis. -- {- -- halt : ∀ {M A} → ∙ ⊢ M ⦂ A -- → M ⇓ -- halt (var ()) -- halt (lam 𝒟) = LAM _ , done , val-lam -- halt (app 𝒟 ℰ) = {!!} -- halt (pair 𝒟 ℰ) = halt-pair (halt 𝒟) (halt ℰ) -- halt (fst 𝒟) = halt-fst 𝒟 (halt 𝒟) -- halt (snd 𝒟) = halt-snd 𝒟 (halt 𝒟) -- halt unit = UNIT , done , val-unit -- halt (abort 𝒟) = halt-abort 𝒟 (halt 𝒟) -- halt (left 𝒟) = halt-left (halt 𝒟) -- halt (right 𝒟) = halt-right (halt 𝒟) -- halt (case 𝒟 ℰ ℱ) = {!!} -- halt true = TRUE , done , val-true -- halt false = FALSE , done , val-false -- halt (if 𝒟 ℰ ℱ) = halt-if 𝒟 (halt 𝒟) (halt ℰ) (halt ℱ) -- -} -- -------------------------------------------------------------------------------- -- red-app-lam : ∀ {g n M N} → {τ : Terms g n} → {{_ : Val N}} -- → APP (LAM (SUB (LIFTS τ) M)) N ↦ SUB (τ , N) M -- red-app-lam {M = M} {N} {τ} rewrite simp-CUT-SUB N τ M ⁻¹ = red app-lam -- big-red-app-lam : ∀ {g n M M′ N} → {τ : Terms g n} → {{_ : Val N}} -- → SUB (τ , N) M ⇓ M′ -- → APP (LAM (SUB (LIFTS τ) M)) N ⇓ M′ -- big-red-app-lam {M = M} (SUB⤅M′ , VM′) = step (red-app-lam {M = M}) SUB⤅M′ , VM′ -- halt-app-lam : ∀ {g n M N} → {τ : Terms g n} → {{_ : Val N}} -- → SUB (τ , N) M ⇓ -- → APP (LAM (SUB (LIFTS τ) M)) N ⇓ -- halt-app-lam {M = M} (M′ , SUB⇓M′) = M′ , big-red-app-lam {M = M} SUB⇓M′ -- -------------------------------------------------------------------------------- -- red-case-left : ∀ {g n M N O} → {τ : Terms g n} → {{_ : Val M}} -- → CASE (LEFT M) (SUB (LIFTS τ) N) (SUB (LIFTS τ) O) ↦ SUB (τ , M) N -- red-case-left {M = M} {N} {τ = τ} rewrite simp-CUT-SUB M τ N ⁻¹ = red case-left -- big-red-case-left : ∀ {g n M N N′ O} → {τ : Terms g n} → {{_ : Val M}} -- → SUB (τ , M) N ⇓ N′ -- → CASE (LEFT M) (SUB (LIFTS τ) N) (SUB (LIFTS τ) O) ⇓ N′ -- big-red-case-left {N = N} {O = O} (SUB⤅N′ , VN′) = step (red-case-left {N = N} {O}) SUB⤅N′ , VN′ -- halt-case-left : ∀ {g n M N O} → {τ : Terms g n} → {{_ : Val M}} -- → SUB (τ , M) N ⇓ -- → CASE (LEFT M) (SUB (LIFTS τ) N) (SUB (LIFTS τ) O) ⇓ -- halt-case-left {N = N} {O} (N′ , SUB⇓N′) = N′ , big-red-case-left {N = N} {O = O} SUB⇓N′ -- -------------------------------------------------------------------------------- -- red-case-right : ∀ {g n M N O} → {τ : Terms g n} → {{_ : Val M}} -- → CASE (RIGHT M) (SUB (LIFTS τ) N) (SUB (LIFTS τ) O) ↦ SUB (τ , M) O -- red-case-right {M = M} {O = O} {τ} rewrite simp-CUT-SUB M τ O ⁻¹ = red case-right -- big-red-case-right : ∀ {g n M N O O′} → {τ : Terms g n} → {{_ : Val M}} -- → SUB (τ , M) O ⇓ O′ -- → CASE (RIGHT M) (SUB (LIFTS τ) N) (SUB (LIFTS τ) O) ⇓ O′ -- big-red-case-right {N = N} {O} (SUB⤅O′ , VO′) = step (red-case-right {N = N} {O}) SUB⤅O′ , VO′ -- halt-case-right : ∀ {g n M N O} → {τ : Terms g n} → {{_ : Val M}} -- → SUB (τ , M) O ⇓ -- → CASE (RIGHT M) (SUB (LIFTS τ) N) (SUB (LIFTS τ) O) ⇓ -- halt-case-right {N = N} {O} (O′ , SUB⇓O′) = O′ , big-red-case-right {N = N} {O} SUB⇓O′ -- --------------------------------------------------------------------------------