类型系统(二)


本文为学习类型系统的系列文章的第二篇。主要参考资料为大名鼎鼎的 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[xt2]t12

其中 [ x → t 2 ] t 12 [x \rightarrow t_2]t_{12} [xt2]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),定义如下: tFV(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 [xs]x=s [ x → s ] y = y  if y ̸ = x [x \rightarrow s]y = y\text{ if y}\not=x [xs]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) [xs](λy.t1)=λy.[xs]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) [xs](t1 t2)=([xs]t1)([xs]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 t2t1 t2t1t1 (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 t2v2 t2t2t2 (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[xv2]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 &lt; c k + d i f k ≥ c \uparrow ^d_c(k) =\begin{cases} k&amp; if\quad k &lt; c\\ k + d &amp;if\quad k \ge c \end{cases} cd(k)={kk+difk<cifkc ↑ 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&amp; if \quad k == j\\k&amp;else\end{cases} [js]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 [js](λ.t1)=λ.[j+11(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) [js](t1t2)=([js]t1[js]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) 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

由于暂时未用到上下文环境,故并未给出定义。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值