In mathematical logic, the De Bruijn notation is a syntax for terms in the λ calculus invented by the Dutch mathematician Nicolaas Govert de Bruijn.[1] It can be seen as a reversal of the usual syntax for the λ calculus where the argument in an application is placed next to its corresponding binder in the function instead of after the latter's body.
Terms (
M,N,\ldots
v
[v]
(M)
M,N,...::= v | [v] M | (M) N
Terms in the traditional syntax can be converted to the De Bruijn notation by defining an inductive function
l{I}
\begin{align} l{I}(v)&=v\\ l{I}(λv. M)&=[v] l{I}(M)\\ l{I}(M N)&=(l{I}(N))l{I}(M). \end{align}
All operations on λ-terms commute with respect to the
l{I}
(λv. M) N \longrightarrow\beta M[v:=N]
(N) [v] M \longrightarrow\beta M[v:=N].
A feature of this notation is that abstractor and applicator wagons of β-redexes are paired like parentheses. For example, consider the stages in the β-reduction of the term
(M) (N) [u] (P) [v] [w] (Q) z
\begin{align} (M) \underline{(N) [u]} (P) [v] [w] (Q) z &{ \longrightarrow\beta }(M) \underline{(P[u:=N]) [v]} [w] (Q[u:=N]) z\\ &{ \longrightarrow\beta } \underline{(M) [w]} (Q[u:=N,v:=P[u:=N]]) z\\ &{ \longrightarrow\beta } (Q[u:=N,v:=P[u:=N],w:=M]) z. \end{align}
Thus, if one views the applicator as an open paren ('(
') and the abstractor as a close bracket (']
'), then the pattern in the above term is '((](]]
'. De Bruijn called an applicator and its corresponding abstractor in this interpretation partners, and wagons without partners bachelors. A sequence of wagons, which he called a segment, is well balanced if all its wagons are partnered.
In a well balanced segment, the partnered wagons may be moved around arbitrarily and, as long as parity is not destroyed, the meaning of the term stays the same. For example, in the above example, the applicator
(M)
[w]
Several properties of λ-terms that are difficult to state and prove using the traditional notation are easily expressed in the De Bruijn notation. For example, in a type-theoretic setting, one can easily compute the canonical class of types for a term in a typing context, and restate the type checking problem to one of verifying that the checked type is a member of this class.[3] De Bruijn notation has also been shown to be useful in calculi for explicit substitution in pure type systems.[4]