更新日期:2026.5.14

Homepage

求值顺序与CPS

最近在读小林直树写的Model checking higher-order programs时发现了一个错误。在把 call-by-name的

xx

转换成call-by-value的

λk.k x\lambda k. k\ x

时,他把式子写成了λx.k x\lambda x.k\ x。要说我是怎么发现这个错误的,这其实是因为一开始我完全没有看懂什么叫做可以把call-by-value的程序转换成顶层全是unit类型的call-by-name程序。于是我就去查了Plotkin的原始文献,发现了上面的错误。

正确来说,用于转换的公式有以下四个(用unary算符\overline{\cdot}表示转换)

  1. a=λk.k a\overline{a} = \lambda k.k\ a,其中aa是常量
  2. x=λk.k x\overline{x} = \lambda k.k\ x,其中xx是变量
  3. λx.M=λk.k (λx.M)\overline{\lambda x.M} = \lambda k. k\ (\lambda x. \overline{M})
  4. MN=λk.(M(λfN(λa.f a k)))\overline{MN} = \lambda k. (\overline{M} (\lambda f \overline{N} (\lambda a. f\ a\ k)))

话说Plotkin居然会把κ\kappaxx混起来用,在论文的样式下这两个字符简直一模一样。1975年的文献还只有影印版,真是视力毁灭者。也难怪小林直树会把这两个字符搞混了。

Call-by-value, Call-by-name和λ\lambda演算

在讨论一些更深入的事情之前,有必要解释一下λ\lambda calculus里的cbv和cbn。粗略地讲,在程序语言中,call-by-value指在进行函数参数传递时所有参数会被首先求值,最后把值传进函数;而call-by-name则会把表达式直接传进去,直到完全传透为止不进行表达式的求值。

λ\lambda演算中的call-by-value和call-by-name则按照如下方式定义,注意下面指的是非application的表达式(即常量,变量和抽象)

  1. call-by-value:仅允许值进行代入;
  2. call-by-name:从最外层最左侧的表达式开始求值(代入)。

我们知道,根据Church-Rossar定理,一个λ\lambda表达式的最简式和它的代入顺序无关(当然,如果“不恰当地”选择顺序,式子可能无法化到最简)。因此无论是cbv还是cbn,对于同一个λ\lambda表达式,最终的结果总是一样的。但是这个结论不总是成立。其一,存在上述的规约顺序的问题,这会影响规约最终是否能够终止;其二,如果λ\lambda演算允许副作用存在,则可能出现不同的结果。一个程序例子如下

let x := 0 in
let f a := a + a in
f (x := !x + 1; !x)

在这个例子里,call-by-value的最终结果是2,而call-by-name的最终结果是3。一般而言, call-by-name会获得更好的终止性,而call-by-value则更符合机器执行逻辑。一个只在 call-by-name的情况下可以终止规约的λ\lambda表达式如下:

(λx.y)((λx.x x)(λx.x x))V(λx.y)((λx.x x)(λx.x x))(\lambda x.y)((\lambda x.x\ x)(\lambda x.x\ x)) \rightarrow_V (\lambda x.y)((\lambda x.x\ x)(\lambda x.x\ x)) (λx.y)((λx.x x)(λx.x x))Ny(\lambda x.y)((\lambda x.x\ x)(\lambda x.x\ x)) \rightarrow_N y

转换

在小林直树的文章里,他使用了并不非常正式的表述“转换”。严格来说,在被转换之前和之后,程序始终是λ\lambda表达式,转换并不足以表达前后的某种等价关系。在原始文献中,有更加严密的表达。

Our object here is to show that call-by-value can be simulated by call-by-name, and vise versa.

作者使用了“模拟”。也就是说,用call-by-name的方式对转换后的程序进行规约时,能够得到和用call-by-value方式对转换前程序进行规约时的同样行为。作者用三个定理描述了这个性质。

  1. Theorem1. (Indifference). EvalN(M(λx.x))=EvalV(M(λx.x))\mathbf{Theorem1}.\ (\text{Indifference}).\ Eval_N(\overline{M}(\lambda x.x)) = Eval_V(\overline{M}(\lambda x.x))
  2. Theorem2. (Simulation). Ψ(EvalV(M))=EvalN(M(λx.x))\mathbf{Theorem2}.\ (\text{Simulation}).\ \Psi(Eval_V(M)) = Eval_N(\overline{M}(\lambda x.x))
  3. Theorem3. (Translation).\mathbf{Theorem3}.\ (\text{Translation}). If λVLM=N\lambda_V^{\mathcal{L}}\vdash M=N then λVLM=N\lambda_V^{\mathcal{L''}}\vdash \overline{M}=\overline{N} and then λNM=N\lambda_N\vdash \overline{M}=\overline{N} . The second but not the first implication is reversible.

其中L\mathcal{L}指call-by-value的原语言,L\mathcal{L'}指call-by-name的语言,L\mathcal{L''}指call-by-value的语言,但是其常量,变量,变量列表和ConstapplyConstapply使用了call-by-name的版本。其中ConstapplyConstapply是一个应用primitive函数的语法糖,其中Constapply(a,b)Constapply(a,b)指把primitiveaa应用到bb上,若无法把aa应用到bb上,或aa不是primitive,则Constapply(a,b)Constapply(a,b)没有定义,有以下定义

ConstapplyN(a,b)=ConstapplyV(a,b)Constapply_N(a,b) = \overline{Constapply_V(a,b)}

Ψ(x)\Psi(x)定义为

Ψ(a)=a, Ψ(x)=x, Ψ(λx.M)=λx.M.\Psi(a) = a,\ \Psi(x) = x,\ \Psi(\lambda x.M) = \lambda x.\overline{M}.

即保存所有抽象,值和变量,只改变应用。

不过在深入讨论(并证明)这三个定理之前,我们先来非正式地思考一下λ\lambda式规约结果的等价性。让我们回到最开头的转换公式上。

  1. a=λk.k a\overline{a} = \lambda k.k\ a,其中aa是常量
  2. x=λk.k x\overline{x} = \lambda k.k\ x,其中xx是变量
  3. λx.M=λk.k (λx.M)\overline{\lambda x.M} = \lambda k. k\ (\lambda x. \overline{M})
  4. MN=λk.(M(λf.N(λa.f a k)))\overline{MN} = \lambda k. (\overline{M} (\lambda f. \overline{N} (\lambda a. f\ a\ k)))

可以观察到,从构成上来说,前三个公式用了一样的转换方式:接受一个kk,然后对kk应用原式。这里用到的是(CPS, continuation-passing style)的思路。kk是被显式编码的continuation计算,即“执行完a之后会执行的控制流”。在直觉上令人有些迷惑的是,原式被放在了continuation后面,这看起来像是“先执行continuation,然后再执行原式”,例如

(λk.k x)KK x(\lambda k.k\ x)K \rightarrow K\ x

关于KK,一般地,如果表达式处于顶层,我们会把这个KK定义成恒等的λx.x\lambda x.x。这样,表达式才能够被真正执行,例如

(λk.k x)(λx.x)(λx.x)xx(\lambda k.k\ x)(\lambda x.x) \rightarrow (\lambda x.x)x \rightarrow x

而对于非顶层的表达式,在转换到call-by-name(L\mathcal{L'})后,KK也一定在开头携带一个抽象,这部分会把后面的xx翻到前面去。

对于第四个转换公式,可以注意到它获取了3个continuation。第一个continuation kk作为整体表达式的KK,被放在了最后一个λ\lambda抽象的最后的位置,成为了f af\ a的continuation。然而f,af,a似乎又与上面得出的反转直觉相反---它们又不反转了。这是因为M\overline{M}N\overline{N}一定存在把它们各自的continuation翻到前面的λ\lambda抽象。例如

M=λk.k Y, N=λk.k Z,M = \lambda k.k\ Y,\ N = \lambda k.k \ Z, MNK=(λk.k Y)(λk.k Z)K((λk.k Z)Y)KY Z KMNK=(\lambda k.k\ Y)(\lambda k.k\ Z)K \rightarrow ((\lambda k.k\ Z)Y)K\rightarrow Y\ Z\ K MNK=M(λf.N(λa.f a K))=(λk.k Y)(λf.N(λa.f a K))(λf.N(λa.f a K))Y=(λf.(λk.k Z)(λa.f a K))Y(λf.(λa.f a K)Z)YY Z K\overline{MNK}=\overline{M}(\lambda f.\overline{N}(\lambda a.f\ a\ K))= (\lambda k.k\ Y)(\lambda f.\overline{N}(\lambda a.f\ a\ K)) \\\rightarrow (\lambda f.\overline{N}(\lambda a.f\ a\ K))Y = (\lambda f.(\lambda k. k\ Z)(\lambda a.f\ a\ K))Y\rightarrow (\lambda f.(\lambda a.f\ a\ K)Z)Y \rightarrow Y\ Z\ K

定理的证明

Plotkin用4个引理证明了这3个定理。让我们从引理一开始。

引理一

Lemma 1. [Ψ(N)/x]M=[N/x]M, if N is a value and x∉{k,a,b}.\mathbf{Lemma\ 1}.\ [\Psi(N)/x]\overline{M} = \overline{[N/x]M},\text{ if } N\text{ is a value and }x\not\in \{k, a, b\}.

这个引理相对比较好证明,只需对MM进行结构性归纳即可。

  1. MM是常量aa,则有 [Ψ(N)/x]a=[Ψ(N)/x](λk.k a)=(λk.k a)=[N/x]a[\Psi(N)/x]\overline{a} = [\Psi(N)/x](\lambda k.k\ a) = (\lambda k.k\ a) = \overline{[N/x]a}
  2. MM是变量,则有
    • MMyy时,显然。
    • MMxx时,
    [Ψ(N)/x]x=[Ψ(N)/x](λk.k x)=λk.k Ψ(N) (k∉FV(N))=N=[N/x]x[\Psi(N)/x]\overline{x} = [\Psi(N)/x](\lambda k.k\ x) = \lambda k.k\ \Psi(N)\ (k\not\in FV(N)) \\= \overline{N} = \overline{[N/x]x}
  3. MM是抽象λy.M1\lambda y.M_1,则有
    • y=xy = x时,显然。
    • 否则,
    [Ψ(N)/x]λy.M1=[Ψ(N)/x](λk.k (λy.M1))=λk.k (λz.([Ψ(N)/x][z/y]M1))(xk, k∉FV(N), and with the usual condition on z)=λk.k (λz.([Ψ(N)/x][z/y]M1))(by induction hypothesis)=λk.k (λz.([N/x][z/y]M1))(by induction hypothesis)=λz.([N/x][z/y]M1)=[N/x]λy.M1\begin{align*} [\Psi(N)/x]\overline{\lambda y.M_1} &= [\Psi(N)/x](\lambda k.k\ (\lambda y.\overline{M_1}))\\ &= \lambda k.k\ (\lambda z.([\Psi(N)/x][z/y]\overline{M_1}))\\ &(x\not=k,\ k\not\in FV(N),\text{ and with the usual condition on z})\\ &= \lambda k.k\ (\lambda z.([\Psi(N)/x]\overline{[z/y]M_1}))\quad (\text{by induction hypothesis})\\ &= \lambda k.k\ (\lambda z.(\overline{[N/x][z/y]M_1}))\quad (\text{by induction hypothesis})\\ &= \overline{\lambda z.([N/x][z/y]M_1)}\\ &= \overline{[N/x]\lambda y.M_1} \end{align*}

这里有一步可能会造成困扰。第二个等号引入了新的抽象zz。从表面上看,好像更简单的写法是λk.k (λy.([Ψ(N)/x]M1)),y∉FV(Ψ(N)). \lambda k.k\ (\lambda y.([\Psi(N)/x]\overline{M_1})),\quad y\not\in FV(\Psi(N)). 不这么写是因为,由于MM中本身就出现了yyFV(Ψ(N))FV(\Psi(N))可能真的会有yy,使得这种写法不一定总是成立。

  1. MM是应用M1M2M_1M_2,则有 M1M2=[Ψ(N)/x](λk.M1(λf.M2(λa.f a k)))=λk.[Ψ(N)/x]M1(λf.[Ψ(N)/x]M2(λa.f a k))(as x∉{k,f,a} and f,a∉FV(Ψ(N)))=λk.[N/x]M1(λf.[N/x]M2(λa.f a k))(by induction hypothesis)=[N/x]M1[N/x]M2=R.S.\begin{align*} \overline{M_1M_2} &= [\Psi(N)/x](\lambda k.\overline{M_1}(\lambda f.\overline{M_2}(\lambda a.f\ a\ k)))\\ &= \lambda k.[\Psi(N)/x]\overline{M_1}(\lambda f.[\Psi(N)/x]\overline{M_2}(\lambda a.f\ a\ k))\\ &(\text{as }x\not\in \{k,f,a\}\text{ and }f,a\not\in FV(\Psi(N)))\\ &= \lambda k.\overline{[N/x]M_1}(\lambda f.\overline{[N/x]M_2}(\lambda a.f\ a\ k))\quad (\text{by induction hypothesis})\\ &= \overline{[N/x]M_1[N/x]M_2}\\ &= R.S. \end{align*}

引理二

在介绍引理二之前,Plotkin引入了一个新的算符“::”。它定义在L×LL\mathcal{L}\times\mathcal{L'}\rightarrow \mathcal{L'}上,具体如下

N:K=KΨ(N)(N is a closed value)MN:K=M:(λf.N(λa.f a K))(M is not a value)MN:K=N:(λa.Ψ(M) a K)(M, but not N, is a value)MN:K=Ψ(M)Ψ(N)K(M and N are values)\begin{align*} &N:K=K\Psi(N)\quad &(N\text{ is a closed value})\\ &MN:K=M:(\lambda f.\overline{N}(\lambda a.f\ a\ K))\quad &(M\text{ is not a value})\\ &MN:K=N:(\lambda a.\Psi(M)\ a\ K)\quad &(M, \text{ but not } N,\text{ is a value})\\ &MN:K=\Psi(M)\Psi(N)K\quad &(M \text{ and } N \text{ are values}) \end{align*}

在此基础上,我们有引理2

Lemma 2. If K is a closed value then MK+M:K, for any term M,(f,a,k∉FV(K)).\mathbf{Lemma\ 2}.\ \text{If }K\text{ is a closed value then }\overline{M}K\overset{+}{\rightarrow}M:K,\text{ for any term }M,(f,a,k\not\in FV(K)).

其中+\overset{+}{\rightarrow}表示一步及以上但有限的规约。引理二也通过结构性归纳证明。

  1. MM是值(即不是应用),那么 MK=(λk.kΨ(M))KKΨ(M)=M:K\overline{M}K = (\lambda k.k\Psi(M))K \rightarrow K\Psi(M) = M:K
  2. MM是应用(M1M2)(M_1M_2),那么
    • subcase 1:若M1M_1不是值,那么根据“::”的定义有 (M1M2):K=M1:(λf.M2(λa.f a K))(M_1M_2):K=M_1:(\lambda f.\overline{M_2}(\lambda a.f\ a\ K))MK=M1M2K=(λk.M1(λf.M2(λa.f a k)))KM1(λf.M2(λa.f a K))+M1:(λf.M2(λa.f a K))(by induction hypothesis)=M:K\begin{align*} \overline{M}K = \overline{M_1M_2}K &= (\lambda k.\overline{M_1}(\lambda f.\overline{M_2}(\lambda a.f\ a\ k)))K \rightarrow \overline{M_1}(\lambda f.\overline{M_2}(\lambda a.f\ a\ K))\\ &\overset{+}{\rightarrow} M_1:(\lambda f.\overline{M_2}(\lambda a.f\ a\ K))\quad (\text{by induction hypothesis})\\ &=M:K \end{align*}
    • subcase 2:若M1M_1是值,但M2M_2不是值,那么有 (M1M2):K=M2:(λa.Ψ(M1) a K)(M_1M_2):K = M_2:(\lambda a.\Psi(M_1)\ a\ K)MK+M1:(λf.M2(λa.f a K))(by induction step in subcase 1)=(λf.M2(λa.f a K))Ψ(M1)M2(λa.Ψ(M1) a K)+M2:(λa.Ψ(M1) a K)(by induction hypothesis)=M:K\begin{align*} \overline{M}K &\overset{+}{\rightarrow}M_1:(\lambda f.\overline{M_2}(\lambda a.f\ a\ K))\quad (\text{by induction step in subcase 1})\\ &=(\lambda f.\overline{M_2}(\lambda a.f\ a\ K))\Psi(M_1)\rightarrow \overline{M_2}(\lambda a.\Psi(M_1)\ a\ K)\\ &\overset{+}{\rightarrow} M_2:(\lambda a.\Psi(M_1)\ a\ K)\quad (\text{by induction hypothesis})\\ &=M:K \end{align*}
    • subcase 3:若M1M_1M2M_2都是值,那么 (M1M2):K=Ψ(M1)Ψ(M2)K(M_1M_2):K = \Psi(M_1)\Psi(M_2)KMK+M2:(λa.Ψ(M1) a K)(as in subcase 2)(λa.Ψ(M1) a K)Ψ(M2)Ψ(M2)Ψ(M1)K\begin{align*} \overline{M}K &\overset{+}{\rightarrow}M_2:(\lambda a.\Psi(M_1)\ a\ K)\quad (\text{as in subcase 2})\\ &\rightarrow (\lambda a.\Psi(M_1)\ a\ K)\Psi(M_2)\\ &\rightarrow \Psi(M_2)\Psi(M_1)K \end{align*}

这样就完成了这个引理的证明。原始文献里有些跳步让它变得难读,上面做了一些修正。

引理三

引理三如下

Lemma 3. If MVN then M:K+N:K ( If K is a closed value and M and N are terms).\mathbf{Lemma\ 3}.\ \text{If }M\underset{V}{\rightarrow}N\text{ then }M:K\overset{+}{\rightarrow}N:K\ (\text{ If }K\text{ is a closed value and }M\text{ and }N\text{ are terms}).

同样地,我们使用结构性归纳。这里我们按照MM及规约后的NN的类型进行分类。注意MM一定是某种应用。

  1. subcase 1:MM是常量应用abab,此时NN立即地是ConstapplyV(a,b)Constapply_V(a,b),有 M:K=abKConstapplyN(a,b)K=NK+N:K(by Lemma 2)\begin{align*} M:K &= abK\rightarrow Constapply_N(a,b)K = \overline{N}K\\ &\overset{+}{\rightarrow}N:K\quad (\text{by Lemma 2}) \end{align*}
  2. subcase 2:MM是抽象应用(λx.M1)M2(\lambda x.M_1)M_2M2M_2是值(即不是应用),因此NN[M2/x]M1[M_2/x]M_1,有 M:K=Ψ(λx.M1)Ψ(M2)K(by :’s definition)=(λx.M1)Ψ(M2)K[Ψ(M2)/x]M1K=[M2/x]M1K(M2 is a value, hence by Lemma 1)=NK+N:K(by Lemma 2)\begin{align*} M:K &= \Psi(\lambda x.M_1)\Psi(M_2)K\quad (\text{by }:\text{'s definition})\\ &= (\lambda x.\overline{M_1})\Psi(M_2)K \rightarrow [\Psi(M_2)/x]\overline{M_1}K\\ &= \overline{[M_2/x]M_1}K\quad (M_2\text{ is a value, hence by Lemma 1})\\ &= \overline{N}K\\ &\overset{+}{\rightarrow}N:K\quad (\text{by Lemma 2}) \end{align*}
  3. subcase 3:MM是一般应用M1M2M_1M_2,且M1M_1是值,M2M_2有规约M2VN2M_2\underset{V}{\rightarrow}N_2,此时可得N=M1N2N = M_1N_2,有 M:K=M2:(λa.Ψ(M1) a K)(by :’s definition)+N2:(λa.Ψ(M1) a K)(by induction hypothesis)=L,\begin{align*} M:K &= M_2:(\lambda a.\Psi(M_1)\ a\ K)\quad (\text{by }:\text{'s definition})\\ &\overset{+}{\rightarrow}N_2:(\lambda a.\Psi(M_1)\ a\ K)\quad (\text{by induction hypothesis})\\ &= L, \end{align*}
    • N2N_2是值,首先 N:K=(M1N2):K=Ψ(M1)Ψ(N2)KN:K = (M_1N_2):K = \Psi(M_1)\Psi(N_2)K 而根据::的定义,可得 L=(λa.Ψ(M1) a K)Ψ(N2)Ψ(M1)Ψ(N2)K=N:KL = (\lambda a.\Psi(M_1)\ a\ K)\Psi(N_2) \rightarrow \Psi(M_1)\Psi(N_2)K = N:K
    • N2N_2不是值,根据::的定义 N:K=(M1N2):K=N2:(λa.Ψ(M1) a K)N:K = (M_1N_2):K = N_2:(\lambda a.\Psi(M_1)\ a\ K) 直接得到了LL
  4. subcase 4:MM是一般应用M1M2M_1M_2,且M1M_1有规约M1VN1M_1\underset{V}{\rightarrow}N_1,此时可得N=N1M2N = N_1M_2,那么 M:K=(M1M2):K=M1:(λf.M2(λa.f a K))(by :’s definition)+N1:(λf.M2(λa.f a K))(by induction hypothesis)=L,\begin{align*} M:K &= (M_1M_2):K\\ &= M_1:(\lambda f.\overline{M_2}(\lambda a.f\ a\ K))\quad (\text{by }:\text{'s definition})\\ &\overset{+}{\rightarrow} N_1:(\lambda f.\overline{M_2}(\lambda a.f\ a\ K))\quad (\text{by induction hypothesis})\\ &= L, \end{align*}
    • N1N_1是值,根据::的定义,有 L=(λf.M2(λa.f a K))Ψ(N1)M2(λa.Ψ(N1) a K)+M2:(λa.Ψ(N1) a K)(by Lemma 2)=L\begin{align*} L &= (\lambda f.\overline{M_2}(\lambda a.f\ a\ K))\Psi(N_1)\\ &\rightarrow \overline{M_2}(\lambda a.\Psi(N_1)\ a\ K)\\ &\overset{+}{\rightarrow} M_2:(\lambda a.\Psi(N_1)\ a\ K)\quad (\text{by Lemma 2})\\ &= L' \end{align*}
      • 此时考虑M2M_2,若M2M_2是值,根据“::”的定义有 N:K=N1M2:K=Ψ(N1)Ψ(M2)KN:K = N_1M_2:K = \Psi(N_1)\Psi(M_2)KL=(λa.Ψ(N1) a K)Ψ(M2)Ψ(N1)Ψ(M2)K=N:KL' = (\lambda a.\Psi(N_1)\ a\ K)\Psi(M_2) \rightarrow \Psi(N_1)\Psi(M_2)K = N:K
      • 而若此时M2M_2不是值,根据“::”的定义有 N:K=N1M2:K=M2:(λa.Ψ(N1) a K)N:K = N_1M_2:K = M_2:(\lambda a.\Psi(N_1)\ a\ K) 直接得到了LL'
    • N1N_1不是值,根据::的定义有 N:K=N1M2:K=N1(λf.M2(λa.f a K))N:K = N_1M_2:K = N_1(\lambda f.\overline{M_2}(\lambda a.f\ a\ K)) 直接得到了LL

这样就完成了证明。不得不说原始证明写得真是烂透了。

引理四

在引理四的开头,作者首先定义了SticksSticks_*。一个很重要但是作者却没有明说的直觉是,SticksSticks_**的求值策略下最终会卡住而无法进一步化简的表达式SticksVSticks_V定义如下

  1. 常量应用:若ConstapplyV(a,b)Constapply_V(a,b)没有定义(即aa不是可以应用于bb的primitive),则abSticksVab\in Sticks_V
  2. 常量-抽象应用:对于任意项NNa(λx.N)SticksVa(\lambda x.N)\in Sticks_V
  3. 抽象应用:若NSticksVN\in Sticks_V,那么对于任意项MM,有(λx.M)NSticksV(\lambda x.M)N\in Sticks_V
  4. 一般应用:若MSticksVM\in Sticks_V,那么对于任意项NN,有MNSticksVMN\in Sticks_V

作者只分了四类令人有些意外。按照作者的定义,一个项可以是常量,变量,抽象和应用。即使顶层是变量xx没有意义,

SticksNSticks_N定义如下

  1. 常量应用:若ConstapplyN(a,b)Constapply_N(a,b)没有定义(即aa不是可以应用于bb的primitive),则abSticksNab\in Sticks_N
  2. 常量-抽象应用:对于任意项NNa(λx.N)SticksNa(\lambda x.N)\in Sticks_N
  3. 一般应用:若MSticksNM\in Sticks_N,那么对于任意项NN,有MNSticksNMN\in Sticks_N
  4. 常量-一般应用:若NSticksNN\in Sticks_N,那么aNSticksNaN\in Sticks_N

在此基础上,有

  1. M+VNM\underset{V}{\overset{+}{\rightarrow}}N,且MMNN都不是值(都是应用),且MM内没有自由变量,那么MSticksVM\in Sticks_V
  2. M+NNM\underset{N}{\overset{+}{\rightarrow}}N,且MMNN都不是值,且MM内没有自由变量,那么MSticksNM\in Sticks_N

作者指出显然SticksVSticksNSticks_V\subseteq Sticks_N