module BoolDemo where
data _==_ {A : Set} (x : A) : A → Set where
refl : x == x
data Empty : Set where
contradiction : {A : Set} → Empty → A
contradiction ()
Not : Set → Set
Not A = A → Empty
data Term : Set where
true : Term
false : Term
if_then_else_ : (t₁ t₂ t₃ : Term) → Term
data Value : Set where
vtrue : Value
vfalse : Value
⌜_⌝ : Value → Term
⌜ vtrue ⌝ = true
⌜ vfalse ⌝ = false
ex : Term
ex = if true then false else true
⟦_⟧ : Term → Value
⟦ true ⟧ = vtrue
⟦ false ⟧ = vfalse
⟦ if t then t₁ else t₂ ⟧ = cond ⟦ t ⟧ ⟦ t₁ ⟧ ⟦ t₂ ⟧
where
cond : Value -> Value -> Value -> Value
cond vtrue t e = t
cond vfalse t e = e
data Step : Term → Term → Set where
E-If-True : forall {t1 t2} -> Step (if true then t1 else t2) t1
E-If-False : forall {t1 t2} -> Step (if false then t1 else t2) t2
E-If-If : forall {t1 t1' t2 t3} -> Step t1 t1' -> Step (if t1 then t2 else t3) (if t1' then t2 else t3)
exampleStep : Step ex false
exampleStep = E-If-True
deterministic : ∀ {t t₁ t₂} → Step t t₁ → Step t t₂ → t₁ == t₂
deterministic E-If-True E-If-True = refl
deterministic E-If-True (E-If-If ())
deterministic E-If-False E-If-False = refl
deterministic E-If-False (E-If-If ())
deterministic (E-If-If ()) E-If-True
deterministic (E-If-If ()) E-If-False
deterministic (E-If-If step1) (E-If-If step2) with deterministic step1 step2
deterministic (E-If-If step1) (E-If-If step2) | refl = refl
data Red (t : Term) : Set where
Reduces : {t' : Term} -> Step t t' -> Red t
NF : Term → Set
NF t = Red t -> Empty
data Is-value : Term → Set where
vtrue : Is-value true
vfalse : Is-value false
if-reduces : ∀ t₁ t₂ t₃ → 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)
normal-forms-are-values : ∀ t → NF t → Is-value t
normal-forms-are-values true nft = vtrue
normal-forms-are-values false nft = vfalse
normal-forms-are-values (if t then t₁ else t₂) nft = contradiction (nft (if-reduces t t₁ t₂))
data Steps : Term → Term → Set where
Nil : forall {t} -> Steps t t
Cons : forall {t1 t2 t3} -> Step t1 t2 -> Steps t2 t3 -> Steps t1 t3
[_] : ∀ {t₁ t₂} -> Step t₁ t₂ -> Steps t₁ t₂
[_] x = Cons x Nil
_++_ : ∀ {t₁ t₂ t₃} → Steps t₁ t₂ → Steps t₂ t₃ → Steps t₁ t₃
Nil ++ steps2 = steps2
Cons x steps1 ++ steps2 = Cons x (steps1 ++ steps2)
infixr 5 _++_
E-If-Steps : ∀ {t₁ t₁′ t₂ t₃} →
Steps t₁ t₁′ →
Steps (if t₁ then t₂ else t₃) (if t₁′ then t₂ else t₃)
E-If-Steps Nil = Nil
E-If-Steps (Cons x steps) = Cons (E-If-If x) (E-If-Steps steps)
uniqueness-of-normal-forms :
∀ {t t₁ t₂} →
Steps t t₁ → Steps t t₂ → NF t₁ → NF t₂ → t₁ == t₂
uniqueness-of-normal-forms Nil Nil nf1 nf2 = refl
uniqueness-of-normal-forms Nil (Cons x s2) nf1 nf2 = contradiction (nf1 (Reduces x))
uniqueness-of-normal-forms (Cons x s1) Nil nf1 nf2 = contradiction (nf2 (Reduces x))
uniqueness-of-normal-forms (Cons x s1) (Cons x₁ s2) nf1 nf2 with deterministic x x₁
uniqueness-of-normal-forms (Cons x s1) (Cons x₁ s2) nf1 nf2 | refl = uniqueness-of-normal-forms s1 s2 nf1 nf2
exSteps : Steps (if ex then ex else ex) false
exSteps = Cons (E-If-If E-If-True) (Cons E-If-False (Cons E-If-True Nil))
data _⇓_ : Term → Value → Set where
EvalTrue : true ⇓ vtrue
EvalFalse : false ⇓ vfalse
EvalIfTrue : forall {c t e v} -> c ⇓ vtrue -> t ⇓ v -> (if c then t else e) ⇓ v
EvalIfFalse : forall {c t e v} -> c ⇓ vfalse -> e ⇓ v -> (if c then t else e) ⇓ v
ex⇓ : (if ex then ex else ex) ⇓ vfalse
ex⇓ = EvalIfFalse (EvalIfTrue EvalTrue EvalFalse) (EvalIfTrue EvalTrue EvalFalse)
big-to-small : ∀ {t v} → t ⇓ v → Steps t ⌜ v ⌝
big-to-small EvalTrue = Nil
big-to-small EvalFalse = Nil
big-to-small (EvalIfTrue p p₁) = E-If-Steps (big-to-small p) ++ ([ E-If-True ] ++ big-to-small p₁)
big-to-small (EvalIfFalse p p₁) = E-If-Steps (big-to-small p) ++ Cons E-If-False Nil ++ big-to-small p₁
lemma : (v : Value) -> ⌜ v ⌝ ⇓ v
lemma vtrue = EvalTrue
lemma vfalse = EvalFalse
lemma2 : forall {t t' v} -> Step t t' -> t' ⇓ v -> t ⇓ v
lemma2 E-If-True p = EvalIfTrue EvalTrue p
lemma2 E-If-False p = EvalIfFalse EvalFalse p
lemma2 (E-If-If step) (EvalIfTrue p p₁) = EvalIfTrue (lemma2 step p) p₁
lemma2 (E-If-If step) (EvalIfFalse p p₁) = EvalIfFalse (lemma2 step p) p₁
small-to-big : (t : Term) -> (v : Value) → Steps t ⌜ v ⌝ → t ⇓ v
small-to-big .(⌜ v ⌝) v Nil = lemma v
small-to-big _ v (Cons step steps) = lemma2 step (small-to-big _ _ steps)
⇓-complete : ∀ t → t ⇓ ⟦ t ⟧
⇓-complete true = EvalTrue
⇓-complete false = EvalFalse
⇓-complete (if t then t₁ else t₂) with ⇓-complete t
⇓-complete (if .true then t₁ else t₂) | EvalTrue = EvalIfTrue EvalTrue (⇓-complete t₁)
⇓-complete (if .false then t₁ else t₂) | EvalFalse = EvalIfFalse EvalFalse (⇓-complete t₂)
⇓-complete (if _ then t₁ else t₂) | EvalIfTrue p p₁ = {!!}
⇓-complete (if _ then t₁ else t₂) | EvalIfFalse p p₁ = {!!}
⇓-sound : ∀ t v → t ⇓ v → v == ⟦ t ⟧
⇓-sound .true .vtrue EvalTrue = refl
⇓-sound .false .vfalse EvalFalse = refl
⇓-sound _ v (EvalIfTrue {c} p p₁) with ⟦ c ⟧ | ⇓-sound _ _ p
⇓-sound _ v (EvalIfTrue p p₁) | .vtrue | refl = ⇓-sound _ _ p₁
⇓-sound _ v (EvalIfFalse {c} p p₁) with ⟦ c ⟧ | ⇓-sound _ _ p
⇓-sound _ v (EvalIfFalse p p₁) | .vfalse | refl = ⇓-sound _ _ p₁
data _⇓ (t : Term) : Set where
terminates : ∀ v → Steps t (⌜ v ⌝) → t ⇓
prepend-steps : ∀ {t₁ t₂} → Steps t₁ t₂ → t₂ ⇓ → t₁ ⇓
prepend-steps steps (terminates v x) = terminates v (steps ++ x)
termination : ∀ t → t ⇓
termination true = terminates vtrue Nil
termination false = terminates vfalse Nil
termination (if t then t₁ else t₂) with termination t
termination (if t then t₁ else t₂) | terminates vtrue x with termination t₁
termination (if t then t₁ else t₂) | terminates vtrue x₁ | terminates v x = terminates v (E-If-Steps x₁ ++ (Cons E-If-True Nil ++ x))
termination (if t then t₁ else t₂) | terminates vfalse x = {!!}