Maxim Koltsov
What is NbE
Terms
Syntax
Normalization
What is NbE
Terms
Denotations
Syntax
Semantics
Evaluation
Reification
Normalization by Evaluation
Question: how to build NbE procedure?
Pick semantics model (= meta language) that makes reification easy
Danvy's Type Directed Partial Evaluation
Terms
a, b, c, x, y, ... : variables \x -> t: lambda-abstractions a b: application <t1, t2>: pairs p1 t, p2 t: projections
Danvy's Type Directed Partial Evaluation
reify_t : D -> Normal terms
Let D be some model
reify_o t = t, for o — atomic type reify_(a -> b) t = \x -> reify_b (t (reflect_a x)) reify_(<a, b>) t = <p1 (reify_a t), p2 (reify_b t)>
reflect_o t = t, for o — atomic type reflect_(a -> b) t = fun(s) { reflect_b (t (reify_a s)) } reflect_(<a, b>) t = (reflect_a (p1 t), reflect_b (p2 t))
reflect_t : Neutral terms -> D
So, model (D) must support variables, functions and pairs
In Haskell it may be:
data Ty
= Int
| Fun Ty Ty
deriving (Eq, Show)
data Term
= Var String
| VInt Int
| Lam String Term
| App Term Term
| Pair Term Term
| P1 Term
| P2 Term
deriving (Eq, Show)
-- | Semantics of terms
data Sem
= SNeu Term
-- ^ neutral: only atomic types and applications
| SFun (Sem -> Sem)
| SPair Sem Sem
Can we add sums?
Terms:
Left t, Right t case t of (Left x -> t, Right x -> t)
reflect_(Either a b) t = case t of ...
NO — we need more complicated model and meta-language
Danvy: shift/reset
NbE and calculus properties
Soundness: if Γ⊢p:A, then in a model where Γ holds, A holds
Γ⊢p:A — proof of proposition A under hypotheses Г (Curry-Howard)
Completeness: if in any model Г implies A, then there exists term p such that Г⊢p:A
Г⊢p:A→(w⊩Г=>w⊩A)
(∀w. w⊩Г→w⊩A)→Г⊢p:A
Evaluation
Reification
Ilik's CPS model
Key ideas:
Kripke model for lambda calculus
(K,≤) — preorder of possible worlds
Relation of forcing: for world w in K and n-ary predicate X, w⊩X — n-ary relation on w, such that
For w′≥w, (w⊩X)(d1,…,dn)→(w′,⊩X)(d1,…,dn)
For compound propositions (= types):
w⊩A→B means for all w′≥w w′⊩A implies w′⊩B
w⊩<A,B> means w⊩A AND w⊩B
w⊩Either(A,B) means w⊩A OR w⊩B
Again, meta language must have functions, pairs and sums
Soundness: If Γ⊢p:A, then in any model for any world, if w⊩Γ, then w⊩A
Completeness: if in any model, in any world w⊩Γ implies w⊩A, then there exists a term p such that Γ⊢p:A
We can construct an Universal Model for proving completeness
Universal model
K (possible worlds) will be a set of different contexts Γ
Γ≤Γ′ if Γ⊆Γ′
Forcing: Γ⊩A — a set of normal form derivations Γ⊢nfA, where A — closed and atomic
Then, for example, by definition
Γ⊩A→B when for all Γ′≥Γ Γ′⊢nfA implies Γ′⊢nfB — a function in meta-language
Kripke model for logic with sums
New binary relation: w⊩⊥C — world is exploding at formula C
Strong forcing w⊩sA defined as before for atomic formulas
Non-strong forcing: w⊩A if
∀C∀w′≥w(∀w′′≥w′w′′⊩sA→w′′⊩⊥C)→w′⊩⊥C
Extend strong forcing to all formulas:
Universal model for Kripke model with sums
Forcing:
∀C∀Γ′≥Γ(∀Γ′′≥Γ′Γ′′⊩sA→Γ′′⊢nfC)→Γ′⊢nfC
In Haskell:
data Sem
= Sem ((StrongForcing -> Term) -> Term)
data StrongForcing
= FInt Term
| FPair Sem Sem
| FSum (Either Sem Sem)
| FFun (Sem -> Sem)
Reification
"unit": η:w⊩sA→w⊩A, η(a)=λk.ka
"bind": ∗:(∀w′≥ww′⊩sA→w′⊩B)→w⊩A→w⊩B,
ϕ∗a=λk.a (λb.ϕ b k)
Forcing (w⊩A) is kinda "Cont" monad storing strong forcing (w⊩sA)
"run": μ:w⊩X→w⊩sX for atomic X, by definition of ⊩
Reification
reify_X (a) = μ(a), X — atomic
reify_(A->B) (f) = η(λs.λx.reifyB(s(reflectAx)))
reify_(Either A B) (a) =
η(λs.(Left l→reifyAl;Right r→reifyBr))
reflect_X (a) = η(a), X — atomic
reflect_(A->B) (f) = η(λx.reflectB(f(reifyAx)))
reflect_(Either A B) (t) =
λk.case t of [Left l→k(Left (reflectAl));
Right r→k(Right (reflectBr))]
Examples
t :: Either Church () -> Church -> Church
t = \c -> \n0 ->
case c of
Left n -> add n n0
Right _ -> \f -> \x -> f (n0 f x)
nbe(t (Left 3)):
t' :: Church -> Church
t' = \n0 -> \f -> \x -> f $ f $ f (n0 $ \k -> f k) x
nbe(t (Right ())):
t' :: Church -> Church
t' = \n0 -> \f -> \x -> f (n0 $ \k -> f k) x
Modal logic
New type: □A
New terms:
quot t : □A if t:A
let box u = t in e: A if t:□A and Γ;Δ,u:A⊢e:B
Two contexts: Γ;Δ⊢t:A
exp :: Int -> [] (Int -> Int)
exp b =
if zero b
then box (\_ -> 1)
else
let box u = exp (b - 1)
in box (\x -> x * (u x))
\x -> let box u = exp 3 in u x :: Int -> Int
Kripke CPS model
Strong forcing:
Γ;Δ⊩sbox A is a pair of Γ;∅⊢t and Γ;Δ⊩A
eval(box t) = η(<graft t,eval t>)
eval(let box u = t in e) =
λk.(eval t)(<t,s>→(eval b)k)
reify([] A)(t) = t(<t,s>→box t)
reflect([] A)(t) =
λk.let box u=t in k<u,reflectAu>
Example
nbe (exp 3) :: [] (Int -> Int)
nbe (exp 3) = box \x -> x * ( (\y -> y * ((\z -> ...)) y) x)
nbe (exp 3)
Full normalization: nbe(let box u = exp 3 in u)
nbe (let box u = exp 3 in u) :: Int -> Int
\x -> x * x * x * 1
Next steps