本文为学习类型系统的系列文章的第二篇。主要参考资料为大名鼎鼎的 T y p e s Types Types a n d and and P r o g r a m m i n g Programming Programming L a n g u a g e s Languages Languages。
无类型 λ \lambda λ演算
基础
变量与元变量(Variables and Metavariables)
首先看一个式子
λ
\lambda
λx.
λ
\lambda
λy.xy有形式
λ
\lambda
λz.s
其中z
,s
被称为元变量,x
,y
被称为对象语言变量
作用域(Scope)
在
λ
\lambda
λx.t中,x
的作用域就为t
。而在
λ
\lambda
λy.xy或者xy
中,x
就是自由变量。不含自由变量的项成为封闭项,也称为组合子。最简单的组合子是恒等函数:
i
d
=
λ
x
.
x
id = \lambda x.x
id=λx.x
操作语义
β \beta β规约
( λ x . t 12 ) t 2 → [ x → t 2 ] t 12 (\lambda x.t_{12}) t_2 \rightarrow[x \rightarrow t_2]t_{12} (λx.t12)t2→[x→t2]t12
其中
[
x
→
t
2
]
t
12
[x \rightarrow t_2]t_{12}
[x→t2]t12表示由
t
2
t_2
t2代换在
t
12
t_{12}
t12中所有自由出现的
x
x
x得到的项。例如
(
λ
x
.
x
(
λ
x
.
x
)
)
(
u r
)
(\lambda x.x(\lambda x.x))(\text{u r})
(λx.x(λx.x))(u r)
规约后可得到结果
u r
(
λ
x
.
x
)
\text{u r }(\lambda x.x)
u r (λx.x)
求值策略
考虑项
(
λ
x
.
x
(
λ
x
.
x
)
)
(
λ
z
.
(
λ
x
.
x
)
z
)
(\lambda x.x(\lambda x.x))(\lambda z.(\lambda x.x)z)
(λx.x(λx.x))(λz.(λx.x)z)
可记作
i
d
(
i
d
(
λ
z
.
i
d
z
)
)
id(id(\lambda z.id\text{ z}))
id(id(λz.id z))
这个项包含三个约式:
i
d
(
i
d
(
λ
z
.
i
d
z
)
)
‾
\underline{id(id(\lambda z.id\text{ z}))}
id(id(λz.id z))
i
d
(
i
d
(
λ
z
.
i
d
z
)
)
‾
id\underline{(id(\lambda z.id\text{ z}))}
id(id(λz.id z))
i
d
(
i
d
(
λ
z
.
i
d
z
)
)
‾
id(id(\lambda z.\underline{id\text{ z}))}
id(id(λz.id z))
-
β
\beta
β规约
i d ( i d ( λ z . i d z ) ) ‾ \quad id(id(\lambda z.\underline{id\text{ z}))} id(id(λz.id z))
→ i d ( i d ( λ z . z ) ) ‾ \rightarrow id\underline{(id(\lambda z.z))} →id(id(λz.z))
→ i d ( λ z . z ) ‾ \rightarrow \underline{id(\lambda z.z)} →id(λz.z)
→ λ z . z \rightarrow \lambda z.z →λz.z - 正则序
i d ( i d ( λ z . i d z ) ) ‾ \quad \underline{id(id(\lambda z.id\text{ z}))} id(id(λz.id z))
→ i d ( λ z . i d z ) ‾ \rightarrow \underline{id(\lambda z.id\text{ z})} →id(λz.id z)
→ λ z . id z ‾ \rightarrow \lambda z.\underline{\text{id z}} →λz.id z
→ λ z . z \rightarrow \lambda z.z →λz.z - 按名调用
i d ( i d ( λ z . i d z ) ) ‾ \quad \underline{id(id(\lambda z.id\text{ z}))} id(id(λz.id z))
→ i d ( λ z . i d z ) ‾ \rightarrow \underline{id(\lambda z.id\text{ z})} →id(λz.id z)
→ λ z . id z \rightarrow \lambda z.\text{id z} →λz.id z - 按值调用
i d ( i d ( λ z . i d z ) ) ‾ \quad \underline{id(id(\lambda z.id\text{ z}))} id(id(λz.id z))
→ i d ( λ z . i d z ) ‾ \rightarrow \underline{id(\lambda z.id\text{ z})} →id(λz.id z)
→ λ z . id z \rightarrow \lambda z.\text{id z} →λz.id z
λ 演 算 中 的 程 序 设 计 \lambda 演算中的程序设计 λ演算中的程序设计
多参数
λ (x y) . s → λ x . λ y . s \lambda \text{(x y)}.s \rightarrow \lambda x.\lambda y.s λ(x y).s→λx.λy.s
Church布尔式
t r u = λ t . λ f . t tru = \lambda t.\lambda f.t tru=λt.λf.t f l s = λ t . λ f . f fls= \lambda t.\lambda f.f fls=λt.λf.f
条件式
i f = λ l . λ m . λ n . l m n if = \lambda l.\lambda m.\lambda n.\text{l m n} if=λl.λm.λn.l m n
逻辑式
a n d = λ b . λ c . b c fls and = \lambda b.\lambda c.\text{b c fls} and=λb.λc.b c fls a n d = λ b . λ c . b c tru and = \lambda b.\lambda c.\text{b c tru} and=λb.λc.b c tru a n d = λ b . if b fls tru and = \lambda b.\text{if b fls tru} and=λb.if b fls tru
序对
p a i r = λ f . λ s . λ b . b f s pair = \lambda f.\lambda s.\lambda b.\text{b f s} pair=λf.λs.λb.b f s f s t = λ p . p tru fst = \lambda p.\text{p tru} fst=λp.p tru s n d = λ p . p fls snd= \lambda p.\text{p fls} snd=λp.p fls
数值
c 0 = λ s . λ z . z c_0 = \lambda s.\lambda z.z c0=λs.λz.z c 1 = λ s . λ z . s z c_1 = \lambda s.\lambda z.\text{s z} c1=λs.λz.s z c 2 = λ s . λ z . s (s z) c_2 = \lambda s.\lambda z.\text{s (s z)} c2=λs.λz.s (s z) e t c . etc. etc.
后继
s u c c = λ n . λ s . λ z . s (n s z) succ = \lambda n.\lambda s.\lambda z.\text{s (n s z)} succ=λn.λs.λz.s (n s z)
加法
p l u s = λ m . λ n . λ s . λ z . m s (n s z) plus=\lambda m. \lambda n.\lambda s.\lambda z.\text{ m s (n s z)} plus=λm.λn.λs.λz. m s (n s z)
乘法
t i m e s = λ m . λ n . m (plus n) c 0 times=\lambda m. \lambda n.\text{ m (plus n) }c_0 times=λm.λn. m (plus n) c0
前驱
z z = pair c 0 c 0 zz = \text{pair }c_0\text{ } c_0 zz=pair c0 c0 s s = λ p . pair (snd p) (plus c 1 (snd p)) ss=\lambda p.\text{ pair (snd p) (plus }c_1\text{ (snd p))} ss=λp. pair (snd p) (plus c1 (snd p)) p r e d = λ m . fst (m ss zz) pred=\lambda m.\text{fst (m ss zz)} pred=λm.fst (m ss zz)
减法
m i n u s = λ m . λ n . m (fst (n ss zz)) minus=\lambda m.\lambda n.\text{ m (fst (n ss zz))} minus=λm.λn. m (fst (n ss zz))
递归
ω = ( λ x . ( x x ) ) ( λ x . ( x x ) ) \omega = (\lambda x.\text( x x)) (\lambda x.\text( x x)) ω=(λx.(xx))(λx.(xx)) f i x = λ f . ( λ x . f ( λ y . x x y ) ) ( λ x . f ( λ y . x x y ) ) fix = \lambda f.(\lambda x.f(\lambda y.\text{ x x y})) (\lambda x.f(\lambda y.\text{ x x y})) fix=λf.(λx.f(λy. x x y))(λx.f(λy. x x y))
形式性
定义:
一
个
项
t
的
自
由
变
量
集
合
,
记
作
F
V
(
t
)
,
定
义
如
下
:
一个项t的自由变量集合,记作FV(t),定义如下:
一个项t的自由变量集合,记作FV(t),定义如下:
F
V
(
x
)
=
{
x
}
FV(x) = \{x\}
FV(x)={x}
F
V
(
λ
x
.
t
1
)
=
F
V
(
t
1
)
\
{x}
FV(\lambda x.t_1) = FV(t_1) \backslash\text{\{x\}}
FV(λx.t1)=FV(t1)\{x}
F
V
(
t
1
t
2
)
=
F
V
(
t
1
)
∪
F
V
(
t
2
)
FV(t_1\text{ }t_2)=FV(t_1)\cup FV(t_2)
FV(t1 t2)=FV(t1)∪FV(t2)
代换
[ x → s ] x = s [x \rightarrow s]x = s [x→s]x=s [ x → s ] y = y if y ̸ = x [x \rightarrow s]y = y\text{ if y}\not=x [x→s]y=y if y̸=x [ x → s ] ( λ y . t 1 ) = λ y . [ x → s ] t 1 if y ̸ = x and y ∉ F V ( s ) [x \rightarrow s](\lambda y.t_1) = \lambda y.[x \rightarrow s]t_1\text{ if y}\not=\text{x and y} \notin FV(s) [x→s](λy.t1)=λy.[x→s]t1 if y̸=x and y∈/FV(s) [ x → s ] ( t 1 t 2 ) = ( [ x → s ] t 1 ) ( [ x → s ] t 2 ) [x \rightarrow s](t_1\text{ }t_2)=([x \rightarrow s]t_1)([x \rightarrow s]t_2) [x→s](t1 t2)=([x→s]t1)([x→s]t2)
语法
t ::= terms:
x variable
λx.t abstraction
t t application
v ::= values:
λx.t abstraction value
求值
t 1 → t 1 ′ t 1 t 2 → t 1 ′ t 2 (E-App1) \frac{t_1 \rightarrow t_1'}{t_1\text{ }t_2 \rightarrow t_1' \text{ }t_2} \text{ (E-App1)} t1 t2→t1′ t2t1→t1′ (E-App1) t 2 → t 2 ′ v 1 t 2 → v 2 t 2 ′ (E-App2) \frac{t_2 \rightarrow t_2'}{v_1\text{ }t_2 \rightarrow v_2 \text{ }t_2'} \text{ (E-App2)} v1 t2→v2 t2′t2→t2′ (E-App2) ( λ x . t 12 ) v 2 → [ x → v 2 ] t 12 (E-AppABS) (\lambda x.t_{12})v_2 \rightarrow [x \rightarrow v_2]t_{12} \text{ (E-AppABS)} (λx.t12)v2→[x→v2]t12 (E-AppABS)
项和上下文
为确定变量的出现该如何表示,我们将变量直接指向它的绑定器。这样可以用自然数代替有名变量来实现。例如
λ
x
.
x
\lambda x.x
λx.x
可表示为:
λ
.
0
\lambda .0
λ.0
而
λ
x
.
λ
y
.
x
(
y
x
)
\lambda x.\lambda y.x(yx)
λx.λy.x(yx)
可表示为:
λ
.
λ
.
1 (0 1)
\lambda .\lambda .\text{ 1 (0 1)}
λ.λ. 1 (0 1)
移位
要对用自然数代替有名变量的项进行代换,首先需要一个辅助操作,称为移位用来将项中的自由变量重新索引。一个项在截断参数c
(表示从第c
个索引开始需要移位)上的d
步位移,记为
↑
c
d
(
t
)
\uparrow ^d_c(t)
↑cd(t)。定义如下:
↑
c
d
(
k
)
=
{
k
i
f
k
<
c
k
+
d
i
f
k
≥
c
\uparrow ^d_c(k) =\begin{cases} k& if\quad k < c\\ k + d &if\quad k \ge c \end{cases}
↑cd(k)={kk+difk<cifk≥c
↑
c
d
(
λ
.
t
1
)
=
λ
.
↑
c
+
1
d
(
t
1
)
\uparrow ^d_c(\lambda .t_1) =\lambda .\uparrow ^d_{c+1}(t_1)
↑cd(λ.t1)=λ.↑c+1d(t1)
↑
c
d
(
t
1
t
2
)
=
↑
c
d
(
t
1
)
↑
c
d
(
t
2
)
\uparrow ^d_c(t_1\quad t_2) =\uparrow ^d_c(t_1)\uparrow ^d_c(t_2)
↑cd(t1t2)=↑cd(t1)↑cd(t2)
一般用
↑
d
(
t
)
\uparrow ^d(t)
↑d(t)表示
↑
0
d
(
t
)
\uparrow ^d_0(t)
↑0d(t)
代换
[ j → s ] k = { s i f k = = j k e l s e [j \rightarrow s]k = \begin{cases} s& if \quad k == j\\k&else\end{cases} [j→s]k={skifk==jelse [ j → s ] ( λ . t 1 ) = λ . [ j + 1 → ↑ 1 ( s ) ] t 1 [j \rightarrow s](\lambda .t_1)=\lambda .[j+1 \rightarrow \uparrow^1(s)]t_1 [j→s](λ.t1)=λ.[j+1→↑1(s)]t1 [ j → s ] ( t 1 t 2 ) = ( [ j → s ] t 1 [ j → s ] t 2 ) [j \rightarrow s](t_1\quad t_2)=([j \rightarrow s]t_1 \quad [j \rightarrow s] t_2) [j→s](t1t2)=([j→s]t1[j→s]t2)
求值
求值规则稍有变化的地方在于,当一个约式的规约消耗掉某个变量x
以后,考虑到该变量x
不再是上下文的一部分,所以需要重新生成索引。例如:
(
λ
.
1 0 2
)
(
λ
.
0
)
→
0
(
λ
.
0
)
1
(
not 1
(
λ
.
0
)
2
)
(\lambda .\text{1 0 2})(\lambda .0)\rightarrow \text{0 } (\lambda .0)\text{ 1} \quad (\text{not 1 }(\lambda .0) \text{ 2})
(λ.1 0 2)(λ.0)→0 (λ.0) 1(not 1 (λ.0) 2)
haskell实现
同样首先定义项
data Term = TmVar Int Int
| TmAbs String Term
| TmApp Term Term
deriving (Show)
定义辅助函数
isval :: Term -> Bool
isval (TmAbs _ _) = True
isval _ = False
定义移位
termShift :: Int -> Term -> Term
termShift d = walk 0
where walk :: Int -> Term -> Term
walk c (TmVar x n)
| x >= c = TmVar (x + d) (n + d)
| otherwise = TmVar x (n + d)
walk c (TmAbs x t1) = TmAbs x (walk (c + 1) t1)
walk c (TmApp t1 t2) = TmApp (walk c t1) (walk c t2)
定义代换
termSubst :: Int -> Term -> Term -> Term
termSubst j s = walk 0
where walk :: Int -> Term -> Term
walk c (TmVar x n)
| x == j + c = termShift c s
| otherwise = TmVar x n
walk c (TmAbs x t1) = TmAbs x (walk (c+1) t1)
walk c (TmApp t1 t2) = TmApp (walk c t1) (walk c t2)
termSubsetTop s t = termShift (-1) (termSubst 0 (termShift 1 s) t)
求值函数
eval :: Term -> Maybe Term
eval (TmApp (TmAbs _ t12) v2)
| isval v2 = return $ termSubsetTop v2 t12
eval (TmApp t1 t2)
| isval t1 = liftM2 TmApp (return t1) (eval t2)
| otherwise = liftM2 TmApp (eval t1) (return t2)
eval _ = Nothing
由于暂时未用到上下文环境,故并未给出定义。