{- 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 = {!!} -}