\begin{code} {-# OPTIONS --cubical --safe #-} module Snippets.Expr where open import Prelude hiding (_⟨_⟩_; T; ⊤; tt) module DataTop where \end{code} %<*data-top> \begin{code} data ⊤ : Type₀ where tt : ⊤ \end{code} %</data-top> \begin{code} open import Data.Unit open import Data.Maybe open import Data.Maybe.Sugar open import Data.Nat hiding (_∸_) open import Data.Nat.Properties using () renaming (_≤ᴮ_ to _≤_; _≡ᴮ_ to _≟_) \end{code} %<*op-def> \begin{code} data Op : Type₀ where +′ : Op ×′ : Op -′ : Op ÷′ : Op \end{code} %</op-def> %<*expr-def> \begin{code} data Expr : Type₀ where lit : ℕ → Expr _⟨_⟩_ : Expr → Op → Expr → Expr \end{code} %</expr-def> \begin{code} _ : Expr _ = \end{code} %<*example-expr> \begin{code} lit 4 ⟨ +′ ⟩ lit 5 \end{code} %</example-expr> \begin{code} module IncorrectEval where open import Data.Nat renaming (_∸_ to _-_) \end{code} %<*incorrect-eval> \begin{code} ⟦_⟧ : Expr → ℕ ⟦ lit x ⟧ = x ⟦ xs ⟨ +′ ⟩ ys ⟧ = ⟦ xs ⟧ + ⟦ ys ⟧ ⟦ xs ⟨ ×′ ⟩ ys ⟧ = ⟦ xs ⟧ * ⟦ ys ⟧ ⟦ xs ⟨ -′ ⟩ ys ⟧ = ⟦ xs ⟧ - ⟦ ys ⟧ ⟦ xs ⟨ ÷′ ⟩ ys ⟧ with ⟦ ys ⟧ ⟦ xs ⟨ ÷′ ⟩ ys ⟧ | zero = zero ⟦ xs ⟨ ÷′ ⟩ ys ⟧ | suc ys′ = ⟦ xs ⟧ ÷ suc ys′ \end{code} %</incorrect-eval> %<*safe-sub> \begin{code} _-_ : ℕ → ℕ → Maybe ℕ n - zero = just n suc n - suc m = n - m zero - suc m = nothing \end{code} %</safe-sub> \begin{code} private module NoApplEval where ⟦_⟧ : Expr → Maybe ℕ \end{code} %<*add-helper> \begin{code} ⟦ x ⟨ +′ ⟩ y ⟧ = add-helper ⟦ x ⟧ ⟦ y ⟧ where add-helper : Maybe ℕ → Maybe ℕ → Maybe ℕ add-helper nothing nothing = nothing add-helper nothing (just x) = nothing add-helper (just x) nothing = nothing add-helper (just x) (just y) = just (x + y) \end{code} %</add-helper> \begin{code} ⟦ _ ⟧ = nothing private module ExplicitApplMonEval where ⟦_⟧ : Expr → Maybe ℕ \end{code} %<*add-helper-app> \begin{code} ⟦ x ⟨ +′ ⟩ y ⟧ = pure _+_ <*> ⟦ x ⟧ <*> ⟦ y ⟧ \end{code} %</add-helper-app> %<*sub-bind> \begin{code} ⟦ x ⟨ -′ ⟩ y ⟧ = ⟦ x ⟧ >>= λ x′ → ⟦ y ⟧ >>= λ y′ → x′ - y′ \end{code} %</sub-bind> \begin{code} ⟦ _ ⟧ = nothing \end{code} %<*eval-ty> \begin{code} ⟦_⟧ : Expr → Maybe ℕ \end{code} %</eval-ty> %<*lit-case> \begin{code} ⟦ lit x ⟧ = just x \end{code} %</lit-case> %<*appl-cases> \begin{code} ⟦ x ⟨ +′ ⟩ y ⟧ = ⦇ ⟦ x ⟧ + ⟦ y ⟧ ⦈ ⟦ x ⟨ ×′ ⟩ y ⟧ = ⦇ ⟦ x ⟧ * ⟦ y ⟧ ⦈ \end{code} %</appl-cases> %<*sub-case> \begin{code} ⟦ x ⟨ -′ ⟩ y ⟧ = do x′ ← ⟦ x ⟧ y′ ← ⟦ y ⟧ x′ - y′ \end{code} %</sub-case> %<*div-case> \begin{code} ⟦ x ⟨ ÷′ ⟩ y ⟧ = do suc y′ ← ⟦ y ⟧ where zero → nothing x′ ← ⟦ x ⟧ guard (rem x′ (suc y′) ≟ 0) just (x′ ÷ suc y′) \end{code} %</div-case> %<*is-just> \begin{code} is-just : Maybe A → Bool is-just nothing = false is-just (just _) = true \end{code} %</is-just> %<*tee> \begin{code} T : Bool → Type₀ T true = ⊤ T false = ⊥ \end{code} %</tee> %<*valid> \begin{code} Valid : Expr → Type₀ Valid e = T (is-just ⟦ e ⟧) \end{code} %</valid> \begin{code} module StaticEvalExplicit where \end{code} %<*static-eval-explicit> \begin{code} ⟦_⟧! : (e : Expr) → Valid e → ℕ ⟦ e ⟧! v with ⟦ e ⟧ ⟦ e ⟧! v | just x = x \end{code} %</static-eval-explicit> \begin{code} module StaticEvalRetrieve where \end{code} %<*retrieve-implicit> \begin{code} ⟦_⟧! : (e : Expr) → { _ : Valid e } → ℕ ⟦ e ⟧! { valid } with ⟦ e ⟧ ⟦ e ⟧! { valid } | just x = x \end{code} %</retrieve-implicit> %<*static-eval> \begin{code} ⟦_⟧! : (e : Expr) → { _ : Valid e } → ℕ ⟦ e ⟧! with ⟦ e ⟧ ⟦ e ⟧! | just x = x \end{code} %</static-eval> %<*example-eval> \begin{code} example-eval : Maybe ℕ example-eval = ⟦ lit 4 ⟨ ×′ ⟩ lit 2 ⟧ \end{code} %</example-eval> %<*pair> \begin{code} record Pair (A : Type a) (B : Type b) : Type (a ℓ⊔ b) where field fst : A snd : B \end{code} %</pair> %<*example-static-eval> \begin{code} example-static-eval : ℕ example-static-eval = ⟦ lit 4 ⟨ ×′ ⟩ lit 2 ⟧! \end{code} %</example-static-eval> %<*example-static-proof> \begin{code} example-static-proof : ⟦ lit 4 ⟨ ×′ ⟩ lit 2 ⟧! ≡ 8 example-static-proof = refl \end{code} %</example-static-proof> %<*quot-expr> \begin{code} data Expr/ : Type₀ where lit/ : ℕ → Expr/ _⟪_⟫_ : Expr/ → Op → Expr/ → Expr/ +-comm : ∀ x y → x ⟪ +′ ⟫ y ≡ y ⟪ +′ ⟫ x trunc/ : (x y : Expr/) → (p q : x ≡ y) → p ≡ q \end{code} %</quot-expr> \begin{code} m-+-comm : (x y : Maybe ℕ) → ⦇ x + y ⦈ ≡ ⦇ y + x ⦈ m-+-comm nothing nothing = refl m-+-comm nothing (just x) = refl m-+-comm (just x) nothing = refl m-+-comm (just x) (just y) i = just (Data.Nat.Properties.+-comm x y i) open import Data.Maybe.Properties eval/ : Expr/ → Maybe ℕ eval/ (lit/ x) = just x eval/ (xs ⟪ +′ ⟫ ys) = ⦇ eval/ xs + eval/ ys ⦈ eval/ (xs ⟪ ×′ ⟫ ys) = ⦇ eval/ xs * eval/ ys ⦈ eval/ (xs ⟪ -′ ⟫ ys) = do x′ ← eval/ xs y′ ← eval/ ys x′ - y′ eval/ (xs ⟪ ÷′ ⟫ ys) = do suc y′ ← eval/ ys where zero → nothing x′ ← eval/ xs guard (rem x′ (suc y′) ≟ 0) just (x′ ÷ suc y′) eval/ (+-comm xs ys i) = m-+-comm (eval/ xs) (eval/ ys) i eval/ (trunc/ x y p q i j) = Discrete→isSet (discreteMaybe Data.Nat.Properties.discreteℕ) (eval/ x) (eval/ y) (cong eval/ p) (cong eval/ q) i j \end{code}