{-
Mathematical Foundations of Programming (G54FOP)
Nicolai Kraus
Lecture 6, 15 Feb 2018
-}
module lec6FOP where
{- We import everything we have done last week.
"open" means we can use all definitions directly -}
open import lec3FOP
{- Hint: middle mouse click or alt-.
[press alt/meta, then .]
jumps to the definition that the cursor is on -}
-- Reduce in one step
-- (these are the simplification rules)
data _→1_ : Expr → Expr → Set where
izz : iz z →1 t
izs : {e : Expr} → iz (s e) →1 f
ift : {e₂ e₃ : Expr} → (if t then e₂ else e₃) →1 e₂
iff : {e₂ e₃ : Expr} → (if f then e₂ else e₃) →1 e₃
ps : {e : Expr} → p (s e) →1 e
pz : p z →1 z
-- include structural rules
data _↝_ : Expr → Expr → Set where -- type: \leadsto
from→1 : {e₁ e₂ : Expr} → (e₁ →1 e₂) → (e₁ ↝ e₂)
inside-s : {e₁ e₂ : Expr} → (e₁ ↝ e₂) → (s e₁ ↝ s e₂)
inside-p : {e₁ e₂ : Expr} → (e₁ ↝ e₂) → (p e₁ ↝ p e₂)
inside-iz : ∀ {e₁} {e₂} → (e₁ ↝ e₂) → (iz e₁ ↝ iz e₂)
inside-ite1 : ∀ {e₁ e₁' e₂ e₃} → (e₁ ↝ e₁')
→ (if e₁ then e₂ else e₃) ↝ (if e₁' then e₂ else e₃)
inside-ite2 : ∀ {e₁ e₂ e₂' e₃} → (e₂ ↝ e₂')
→ (if e₁ then e₂ else e₃) ↝ (if e₁ then e₂' else e₃)
inside-ite3 : ∀ {e₁ e₂ e₃ e₃'} → (e₃ ↝ e₃')
→ (if e₁ then e₂ else e₃) ↝ (if e₁ then e₂ else e₃')
data _↝*_ : Expr → Expr → Set where
start : ∀ {e} → e ↝* e
step : ∀ {e₁ e₂ e₃} → (e₁ ↝ e₂) → (e₂ ↝* e₃)
→ (e₁ ↝* e₃)
-- compose two reduction sequences
compose : {e₁ e₂ e₃ : Expr} → (e₁ ↝* e₂)
→ (e₂ ↝* e₃)
→ (e₁ ↝* e₃)
compose start s₂ = s₂
compose (step x s₁) s₂ = step x (compose s₁ s₂)
open import Data.Empty renaming (⊥ to ∅) -- \emptyset
-- define what it means to be a normal form
is-normal : Expr → Set
is-normal e = (e₁ : Expr) → (e →1 e₁) → ∅
{- Exercises:
1. (easy) Show that the expression "t" is
in normal form. This means: fill the whole
(replace the question mark) in
t-nf : is-normal t
t-nf = ?
2. (medium) Show that, if "e" is a normal form,
then so is "s e".
3. (hard) Show that "is-normal" is a
decidable predicate on Expr.
This means writing a function
which takes an expression and tells us
whether the expression is a normal form
or not. The naive version would be
Expr → Bool
but we can do much better: we can take an
expression "e" and either return a *proof*
that "e" is a normal form, or return an
example of how it can be reduced.
Such an example would consist of an expression
"reduct" and a proof of "e ↝ reduct"; we
will learn later how this can be expressed,
but a good way of implementing it is as follows:
-}
record can-red (e : Expr) : Set where
field
reduct : Expr
redstep : e ↝ reduct
{- Ex 3, continued: We can import Data.Sum to get the
definition of ⊎ (type: \u+), a disjoint sum (it's
Either in Haskell). Check out how ⊎ is defined in
the library, it's really simple! -}
open import Data.Sum
{- Ex3, continued: Now, fill in the ? in the following
function; probably, you will want more auxiliary
lemma. Caveat: I have not done this myself.
decide-nf : (e : Expr) → (is-normal e) ⊎ can-red e
decide-nf e = {!!}
-}