{-# OPTIONS --no-termination-check #-}
open import Relation.Binary.PropositionalEquality
module HuttonsRazor
(ext : forall {a b : Set} {f g : a -> b} ->
(forall x -> f x ≡ g x) -> f ≡ g)
where
open import Data.Star
open import Data.Star.Nat
open import Data.Star.Decoration
open import Data.Star.Properties
open import Data.Star.Vec
open ≡-Reasoning
open import Derivation
data Expr : Set where
val : ℕ -> Expr
_⊕_ : Expr -> Expr -> Expr
⟦_⟧ : Expr -> ℕ
⟦ val n ⟧ = n
⟦ e₁ ⊕ e₂ ⟧ = ⟦ e₁ ⟧ + ⟦ e₂ ⟧
module Direct where
Stack : ℕ -> Set
Stack = Vec ℕ
data Op : ℕ -> ℕ -> Set where
push : forall {n} -> ℕ -> Op n (1# + n)
add : forall {n} -> Op (2# + n) (1# + n)
Code : ℕ -> ℕ -> Set
Code = Star Op
⟪_⟫ : forall {m n} -> Code m n -> Stack m -> Stack n
⟪ ε ⟫ s = s
⟪ push n ◅ ops ⟫ s = ⟪ ops ⟫ (↦ n ◅ s)
⟪ add ◅ ops ⟫ (↦ m ◅ ↦ n ◅ s) = ⟪ ops ⟫ (↦ (n + m) ◅ s)
comp : forall {n} -> (e : Expr) -> Code n (1# + n)
comp (val n) = push n ◅ ε
comp (e₁ ⊕ e₂) = comp e₁ ◅◅ comp e₂ ◅◅ add ◅ ε
distrib : forall {i j k}
(s : Stack i) (c₁ : Code i j) (c₂ : Code j k) ->
⟪ c₁ ◅◅ c₂ ⟫ s ≡ ⟪ c₂ ⟫ (⟪ c₁ ⟫ s)
distrib s ε c₂ = refl
distrib s (push n ◅ c₁) c₂ = distrib (↦ n ◅ s) c₁ c₂
distrib (↦ m ◅ ↦ n ◅ s) (add ◅ c₁) c₂ =
distrib (↦ (n + m) ◅ s) c₁ c₂
thm1 : forall {n} (s : Stack n) e -> ⟪ comp e ⟫ s ≡ ↦ ⟦ e ⟧ ◅ s
thm1 s (val n) = refl
thm1 s (e₁ ⊕ e₂) = begin
⟪ comp (e₁ ⊕ e₂) ⟫ s
≡⟨ distrib s (comp e₁) (comp e₂ ◅◅ add ◅ ε) ⟩
⟪ comp e₂ ◅◅ add ◅ ε ⟫ (⟪ comp e₁ ⟫ s)
≡⟨ cong ⟪ comp e₂ ◅◅ add ◅ ε ⟫ (thm1 s e₁) ⟩
⟪ comp e₂ ◅◅ add ◅ ε ⟫ (↦ ⟦ e₁ ⟧ ◅ s)
≡⟨ distrib (↦ ⟦ e₁ ⟧ ◅ s) (comp e₂) (add ◅ ε) ⟩
⟪ add ◅ ε ⟫ (⟪ comp e₂ ⟫ (↦ ⟦ e₁ ⟧ ◅ s))
≡⟨ cong ⟪ add ◅ ε ⟫ (thm1 (↦ ⟦ e₁ ⟧ ◅ s) e₂) ⟩
↦ ⟦ e₁ ⊕ e₂ ⟧ ◅ s
∎
thm2 : forall {i j} (s : Stack i) e (ops : Code (1# + i) j) ->
⟪ comp e ◅◅ ops ⟫ s ≡ ⟪ ops ⟫ (↦ ⟦ e ⟧ ◅ s)
thm2 s (val n) ops = refl
thm2 s (e₁ ⊕ e₂) ops = begin
⟪ comp (e₁ ⊕ e₂) ◅◅ ops ⟫ s
≡⟨ refl ⟩
⟪ (comp e₁ ◅◅ comp e₂ ◅◅ add ◅ ε) ◅◅ ops ⟫ s
≡⟨ cong (\ops' -> ⟪ ops' ⟫ s)
(◅◅-assoc (comp e₁) (comp e₂ ◅◅ add ◅ ε) ops) ⟩
⟪ comp e₁ ◅◅ ((comp e₂ ◅◅ add ◅ ε) ◅◅ ops) ⟫ s
≡⟨ cong (\s' -> ⟪ comp e₁ ◅◅ s' ⟫ s)
(◅◅-assoc (comp e₂) (add ◅ ε) ops) ⟩
⟪ comp e₁ ◅◅ (comp e₂ ◅◅ add ◅ ops) ⟫ s
≡⟨ thm2 s e₁ (comp e₂ ◅◅ add ◅ ops) ⟩
⟪ comp e₂ ◅◅ add ◅ ops ⟫ (↦ ⟦ e₁ ⟧ ◅ s)
≡⟨ thm2 (↦ ⟦ e₁ ⟧ ◅ s) e₂ (add ◅ ops) ⟩
⟪ ops ⟫ (↦ ⟦ e₁ ⊕ e₂ ⟧ ◅ s)
∎
module Calculational where
module Step₁ where
Cont : Set
Cont = ℕ -> ℕ
mutual
eval : Expr -> Cont -> ℕ
eval e c = witness (evalP e c)
evalP : (e : Expr) (c : Cont) -> EqualTo (c ⟦ e ⟧)
evalP (val n) c = ▷ begin c n ∎
evalP (e₁ ⊕ e₂) c = ▷ begin
c (⟦ e₁ ⟧ + ⟦ e₂ ⟧)
≡⟨ refl ⟩
(\(m : _) -> c (m + ⟦ e₂ ⟧)) ⟦ e₁ ⟧
≡⟨ proof (evalP e₁ (\m -> c (m + ⟦ e₂ ⟧))) ⟩
eval e₁ (\m -> c (m + ⟦ e₂ ⟧))
≡⟨ refl ⟩
eval e₁ (\m -> (\(n : _) -> c (m + n)) ⟦ e₂ ⟧)
≡⟨ cong (eval e₁)
(ext (\m -> proof (evalP e₂ (\n -> c (m + n))))) ⟩
eval e₁ (\m -> eval e₂ (\n -> c (m + n)))
∎
c₁ : Cont
c₁ = \n -> n
c₃ : ℕ -> Cont -> Cont
c₃ m c = \n -> c (m + n)
c₂ : Expr -> Cont -> Cont
c₂ e c = \m -> eval e (c₃ m c)
⟦_⟧' : Expr -> ℕ
⟦ e ⟧' = eval e c₁
correct : forall e -> ⟦ e ⟧ ≡ ⟦ e ⟧'
correct e = proof (evalP e c₁)
module Step₂ where
data Cont : Set where
c₁ : Cont
c₂ : Expr -> Cont -> Cont
c₃ : ℕ -> Cont -> Cont
⟦_⟧c : Cont -> Step₁.Cont
⟦ c₁ ⟧c = Step₁.c₁
⟦ c₂ e c ⟧c = Step₁.c₂ e ⟦ c ⟧c
⟦ c₃ m c ⟧c = Step₁.c₃ m ⟦ c ⟧c
mutual
eval : Expr -> Cont -> ℕ
eval e c = witness (evalP e c)
evalP : (e : Expr) (c : Cont) ->
EqualTo (Step₁.eval e ⟦ c ⟧c)
evalP (val n) c = ▷ begin ⟦ c ⟧c n ∎
evalP (e₁ ⊕ e₂) c = ▷ begin
Step₁.eval e₁ (\m -> Step₁.eval e₂ (\n -> ⟦ c ⟧c (m + n)))
≡⟨ refl ⟩
Step₁.eval e₁ (Step₁.c₂ e₂ ⟦ c ⟧c)
≡⟨ proof (evalP e₁ (c₂ e₂ c)) ⟩
eval e₁ (c₂ e₂ c)
∎
mutual
⟦_⟧c' : Cont -> Step₁.Cont
⟦ c ⟧c' n = witness (cSem c n)
eval' : Expr -> Cont -> ℕ
eval' e c = witness (evalP' e c)
cSem : (c : Cont) (n : ℕ) -> EqualTo (⟦ c ⟧c n)
cSem c₁ n = ▷ begin n ∎
cSem (c₂ e c) n = ▷ begin
Step₁.eval e (Step₁.c₃ n ⟦ c ⟧c)
≡⟨ refl ⟩
Step₁.eval e ⟦ c₃ n c ⟧c
≡⟨ proof (evalP e (c₃ n c)) ⟩
eval e (c₃ n c)
≡⟨ proof (evalP' e (c₃ n c)) ⟩
eval' e (c₃ n c)
∎
cSem (c₃ m c) n = ▷ begin
⟦ c ⟧c (m + n)
≡⟨ proof (cSem c (m + n)) ⟩
⟦ c ⟧c' (m + n)
∎
evalP' : (e : Expr) (c : Cont) ->
EqualTo (eval e c)
evalP' (val n) c = ▷ begin
⟦ c ⟧c n
≡⟨ proof (cSem c n) ⟩
⟦ c ⟧c' n
∎
evalP' (e₁ ⊕ e₂) c = ▷ begin
eval e₁ (c₂ e₂ c)
≡⟨ proof (evalP' e₁ (c₂ e₂ c)) ⟩
eval' e₁ (c₂ e₂ c)
∎
⟦_⟧' : Expr -> ℕ
⟦ e ⟧' = eval' e c₁
correct : forall e -> ⟦ e ⟧ ≡ ⟦ e ⟧'
correct e = begin
⟦ e ⟧
≡⟨ Step₁.correct e ⟩
Step₁.⟦_⟧' e
≡⟨ proof (evalP e c₁) ⟩
eval e c₁
≡⟨ proof (evalP' e c₁) ⟩
⟦ e ⟧'
∎
module Step₃ where
open Step₂ public
using (Cont; correct)
renaming ( c₁ to STOP; c₂ to EVAL; c₃ to ADD
; eval' to eval; ⟦_⟧c' to exec; ⟦_⟧' to run
)