4

I'm trying to understand NbE (Normalisation by Evaluation). One thing I don't get is why it uses two different representations of programs: a syntactic and a semantic one.

All the implementations of NbE I found do this. They all look somewhat similar to this:

data Term = ... -- syntactic representation
data Val  = ... -- semantic representation

eval :: Env -> Term -> Val quote :: Ctx -> Val -> Term

nbe :: Term -> Term nbe = quote newCtx . eval newEnv

I would understand it if they did it this way because it's convenient for whatever algorithm/approach they chose. However all the articles about NbE describe this as a necessity: it sounds like swapping representation is a fundamental part of NbE.

Why is it necessary to model NbE this way? Shouldn't it be possible to normalize "in place", using whatever representation the program is already in?

Rrelated question: why do they switch back to the syntactic representation, instead of just continuing with the semantic one?

I spent quite some times looking for an answer. That led me to hear that a normalization "in place" might reduce terms to a non-unique form, or that it could have issues handling η-conversion. However I don't understand why this would be the case, and would love to see examples.

Blue Nebula
  • 213
  • 1
  • 2

1 Answers1

3

It is good to know some basic facts about section-retraction pairs.

Suppose $f : X \to Y$ of and $g : Y \to X$ are maps such that $g \circ f = \mathrm{id}_X$. We say that they form a section-retraction pair, where $f$ is the section and $g$ the retraction. Then the map $r \mathrel{{:}{=}} f \circ g : Y \to Y$ is idempotent because $r \circ r = (f \circ g) \circ (f \circ g) = f \circ (g \circ f) \circ g = f \circ g = r$.

Conversely, every idempotent map $r : Y \to Y$ arises as the composition $r = f_r \circ g_r$ of a section-retraction map. Indeed, we may take $X = \{y \in Y \mid r(y) = y\}$, $f_r : X \to Y$ the subset inclusion, and $g_r = r$. In general, this is not the only way to "split" $r$ into a section and retraction. Depending on the situation, some splitting might be more useful than others.

The normalization map norm : Term → Term is idempotent, because normalizing a normalized term does nothing. We can ask whether there are some nice ways of expressing norm as the composition of a retraction and a section. Of course there is the one mentioned above: let nterm := {t ∈ Term | norm t = t} be the set of normal terms, f : nterm → term the inclusion f t = t, and g : term → nterm normalization g t = norm t (but with the codomain changed to nterm). This is silly and it does not explain anything.

Apart from norm : Term → Term people often define an evaluation function eval : Term → Value which evaluates a term to a value (for example, if Term is the syntax of arithmetical expressions built from numerals, addition and multiplication, then Value would be the natural numbers ). Does eval have a section quote : Value → Term? Yes, usually it does, in fact it has many. Is one of them particularly nice? Yes, the one that quotes values as normal terms, because that explains how norm and eval are related: the latter is a splitting of the former.

So in principle you could normalize "in place", and doing so would be isomorphic to splitting with eval and quote, but the whole point of NbE is that it relates two important concepts, namely normalization and evaluation. Moreover, it is often easier and more insighful to devise an appropriate datatype Value than to insist that we should only ever work with terms.

Andrej Bauer
  • 31,657
  • 1
  • 75
  • 121