module BoolNatDemo where
data _==_ {A : Set} (x : A) : A → Set where
refl : x == x
cong : {a b : Set} {x y : a} (f : a -> b) -> x == y -> f x == f y
cong f refl = refl
data Empty : Set where
contradiction : {A : Set} → Empty → A
contradiction ()
data Exists (a : Set) (b : a -> Set) : Set where
Witness : (x : a) -> b x -> Exists a b
Not : Set → Set
Not A = A → Empty
data Nat : Set where
Zero : Nat
Succ : Nat -> Nat
data Either (a b : Set) : Set where
Left : a -> Either a b
Right : b -> Either a b
data Type : Set where
NAT : Type
BOOL : Type
data Term : Type -> Set where
true : Term BOOL
false : Term BOOL
if_then_else_ : forall {σ} -> (c : Term BOOL) -> (t e : Term σ) → Term σ
zero : Term NAT
succ : (n : Term NAT) -> Term NAT
iszero : (n : Term NAT) -> Term BOOL
data Value : Type -> Set where
vtrue : Value BOOL
vfalse : Value BOOL
vnat : Nat -> Value NAT
⌜_⌝ : forall {ty} -> Value ty → Term ty
⌜ vtrue ⌝ = true
⌜ vfalse ⌝ = false
⌜ vnat Zero ⌝ = zero
⌜ vnat (Succ x) ⌝ = succ ⌜ vnat x ⌝
⟦_⟧ : forall {ty} -> Term ty → Value ty
⟦ true ⟧ = vtrue
⟦ false ⟧ = vfalse
⟦ if t then t₁ else t₂ ⟧ with ⟦ t ⟧
⟦ if t then t₁ else t₂ ⟧ | vtrue = ⟦ t₁ ⟧
⟦ if t then t₁ else t₂ ⟧ | vfalse = ⟦ t₂ ⟧
⟦ zero ⟧ = vnat Zero
⟦ succ t ⟧ with ⟦ t ⟧
⟦ succ t ⟧ | vnat x = vnat (Succ x)
⟦ iszero t ⟧ with ⟦ t ⟧
⟦ iszero t ⟧ | vnat Zero = vtrue
⟦ iszero t ⟧ | vnat (Succ x) = vfalse
data IsValue : {ty : Type} -> Term ty -> Set where
V-True : IsValue true
V-False : IsValue false
V-Zero : IsValue zero
V-Succ : ∀ {x} -> IsValue x -> IsValue (succ x)
isValueComplete : forall {ty} -> (v : Value ty) -> IsValue ⌜ v ⌝
isValueComplete vtrue = V-True
isValueComplete vfalse = V-False
isValueComplete (vnat Zero) = V-Zero
isValueComplete (vnat (Succ x)) = V-Succ (isValueComplete (vnat x))
isValueSound : forall {ty} {t : Term ty} -> IsValue t -> Exists (Value ty) (\v -> ⌜ v ⌝ == t)
isValueSound V-True = Witness vtrue refl
isValueSound V-False = Witness vfalse refl
isValueSound V-Zero = Witness (vnat Zero) refl
isValueSound (V-Succ p) with isValueSound p
isValueSound (V-Succ p) | Witness (vnat k) q = Witness (vnat (Succ k) ) (cong succ q)
data Step : {ty : Type} -> Term ty → Term ty → Set where
E-If-True : forall {ty} {t1 t2 : Term ty} -> Step (if true then t1 else t2) t1
E-If-False : forall {ty} {t1 t2 : Term ty} -> Step (if false then t1 else t2) t2
E-If-If : forall {ty} {t1 t1' : Term BOOL} {t2 t3 : Term ty} -> Step t1 t1' ->
Step (if t1 then t2 else t3) (if t1' then t2 else t3)
E-Succ : forall {t t' : Term NAT} -> Step t t' -> Step (succ t) (succ t')
E-IsZeroZero : Step (iszero zero) true
E-IsZeroSucc : ∀ {t : Term NAT} -> IsValue t -> Step (iszero (succ t)) false
E-IsZero : forall {t t' : Term NAT} -> Step t t' -> Step (iszero t) (iszero t')
preservation : ∀ {ty} -> (t t' : Term ty) -> Step t t' -> ty == ty
preservation t t' step = refl
valuesDoNotStep : forall {ty} -> (t t' : Term ty) -> Step t t' -> IsValue t -> Empty
valuesDoNotStep .true t' () V-True
valuesDoNotStep .false t' () V-False
valuesDoNotStep .zero t' () V-Zero
valuesDoNotStep _ _ (E-Succ step) (V-Succ v) = valuesDoNotStep _ _ step v
data Red {ty : Type} (t : Term ty) : Set where
Reduces : {t' : Term ty} -> Step t t' -> Red t
NF : ∀ {ty} -> Term ty → Set
NF t = Red t -> Empty
toVal : forall {ty} -> (t : Term ty) -> IsValue t -> Value ty
toVal .true V-True = vtrue
toVal .false V-False = vfalse
toVal .zero V-Zero = vnat Zero
toVal _ (V-Succ v) with toVal _ v
toVal _ (V-Succ v) | vnat x₁ = vnat (Succ x₁)
mutual
if-reduces : ∀ {ty} (t₁ : Term BOOL) (t₂ : Term ty) (t₃ : Term ty) → Red (if t₁ then t₂ else t₃)
if-reduces true t2 t3 = Reduces E-If-True
if-reduces false t2 t3 = Reduces E-If-False
if-reduces (if t1 then t2 else t3) t4 t5 with if-reduces t1 t2 t3
if-reduces (if t1 then t2 else t3) t4 t5 | Reduces x = Reduces (E-If-If x)
if-reduces (iszero t1) t2 t3 with iszero-reduces t1
if-reduces (iszero t1) t2 t3 | Reduces x = Reduces (E-If-If x)
iszero-reduces : (t : Term NAT) -> Red (iszero t)
iszero-reduces (if t then t₁ else t₂) with if-reduces t t₁ t₂
iszero-reduces (if t then t₁ else t₂) | Reduces x = Reduces (E-IsZero x)
iszero-reduces zero = Reduces E-IsZeroZero
iszero-reduces (succ t) with progress t
iszero-reduces (succ t) | Left x = Reduces (E-IsZeroSucc (normal-forms-are-values _ x))
iszero-reduces (succ t) | Right (Reduces x) = Reduces (E-IsZero (E-Succ x))
succ-nf : (k : Term NAT) -> NF (succ k) -> Red k -> Empty
succ-nf _ nf (Reduces x) = nf (Reduces (E-Succ x))
normal-forms-are-values : ∀ {ty} (t : Term ty) → NF t → IsValue t
normal-forms-are-values true nf = V-True
normal-forms-are-values false nf = V-False
normal-forms-are-values (if t then t₁ else t₂) nf = contradiction (nf (if-reduces t t₁ t₂))
normal-forms-are-values zero nf = V-Zero
normal-forms-are-values (succ t) nf = V-Succ (normal-forms-are-values t (succ-nf t nf))
normal-forms-are-values (iszero t) nf = contradiction (nf (iszero-reduces t))
values-are-normal-forms : forall {ty} -> {t : Term ty} -> IsValue t -> NF t
values-are-normal-forms p (Reduces step) = valuesDoNotStep _ _ step p
lemma : (k : Term NAT) -> NF k -> NF (succ k)
lemma t nf (Reduces (E-Succ x)) = nf (Reduces x)
progress : {ty : Type} -> (t : Term ty) -> Either (NF t) (Red t)
progress true = Left (values-are-normal-forms V-True)
progress false = Left (values-are-normal-forms V-False)
progress (if t then t₁ else t₂) = Right (if-reduces _ _ _)
progress zero = Left (values-are-normal-forms V-Zero)
progress (succ t) with progress t
progress (succ t) | Left x = Left (lemma t x)
progress (succ t) | Right (Reduces step) = Right (Reduces (E-Succ step))
progress (iszero t) = Right (iszero-reduces _ )