module A201802.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.LR1
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
data Vals {g} : ∀ {n} → Terms g n → Set
where
instance
∙ : Vals ∙
_,_ : ∀ {n M} → {τ : Terms g n} → Vals τ → Val M → Vals (τ , M)
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
¬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}} ()
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
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 𝒟 ℰ ℱ) = ℱ
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
¬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 ())
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 _)
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′₁ ⁻¹
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′ 𝒟) ℰ ℱ
infix 3 _⤅_
data _⤅_ {g} : Term g → Term g → Set
where
done : ∀ {M} → M ⤅ M
step : ∀ {M M′ M″} → M ↦ M′ → M′ ⤅ M″
→ M ⤅ M″
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″)
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↦
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′₂)
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″ 𝒟)
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′)
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′)
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′)
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′)
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′)
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′)
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′)
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′)
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)
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)
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′)
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′)
infix 3 _⇓_
_⇓_ : ∀ {g} → Term g → Term g → Set
M ⇓ M′ = M ⤅ M′ × Val M′
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″
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″
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′₂
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′}}
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′
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′
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′}}
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′}}
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′
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′
_⇓ : ∀ {g} → Term g → Set
M ⇓ = Σ (Term _) (\ M′ → M ⇓ M′)
hpr↦ : ∀ {g} → {M M′ : Term g}
→ M ↦ M′ → M′ ⇓
→ M ⇓
hpr↦ M↦M′ (M″ , M′⇓M″) = M″ , big-step M↦M′ M′⇓M″
hp↦ : ∀ {g} → {M M′ : Term g}
→ M ↦ M′ → M ⇓
→ M′ ⇓
hp↦ M↦M′ (M″ , M′⇓M″) = M″ , big-unstep M↦M′ M′⇓M″
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′
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
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
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) | ()
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) | ()
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) | ()
halt-left : ∀ {g} → {M : Term g}
→ M ⇓
→ LEFT M ⇓
halt-left (M′ , M⇓M′) = LEFT M′ , big-red-left M⇓M′
halt-right : ∀ {g} → {M : Term g}
→ M ⇓
→ RIGHT M ⇓
halt-right (M′ , M⇓M′) = RIGHT M′ , big-red-right M⇓M′
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′
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′
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⇓