类型系统(一)

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

相信有很多跟我一样的读者都是从 C C C系语言如 J a v a Java Java, C / C P P C/CPP C/CPP等入门开始学习编程。而对我来讲,对于类型系统的概念仅仅停留在 J a v a Java Java的泛型语言之中。由于 J a v a Java Java的泛型相对来说较为简单,一度让我以为类型不过是些细枝末节,直到我接触到了 S c a l a Scala Scala H a s k e l l Haskell Haskell这样的语言,才一点一点对类型系统有了较为清楚的认识,同时也开始学习相关方面的知识。

类型系统简介

首先来看看对于类型系统的定义

A A A t y p e type type s y s t e m system system i s is is a a a t r a c t a b l e tractable tractable s y n t a c t i c syntactic syntactic m e t h o d method method f o r for for p r o v i n g proving proving t h e the the a b s e n c e absence absence o f of of
c e r t a i n certain certain p r o g r a m program program b e h a v i o r s behaviors behaviors b y by by c l a s s i f y i n g classifying classifying p h r a s e s phrases phrases a c c o r d i n g according according t o to to t h e the the k i n d s kinds kinds
o f of of v a l u e s values values t h e y they they c o m p u t e . compute. compute.

类型系统有以下几个优点

  • Detecting Errors(错误检查)
  • Abstraction(抽象)
  • Documentation(文档化)
  • Language Safety(语言安全性)
  • Efficiency(有效性)
  • Further Applications(更多应用)

数学基础

需要读者有集合,序列,归纳等方面的知识,具体可自行查阅

无类型算术表达式

无类型算术表达式主要为了介绍诸如抽象语法,归纳定义和证明,求值,运行时错误等概念的建模。
首先我们需要定义算术表达式的语言形式。以BNF文法形式表达如下

t ::=            terms:
   true         constant true
   false          constant false
   if t then t else t     conditional
   0           constant zero
   succ t         successor
   pred t         predecessor
   iszero t         zero test

语法

归纳定义

  • t r u e , f a l s e , 0 ⊆ T ; {true, false, 0} ⊆ T ; true,false,0T;
  • i f t 1 ∈ T , t h e n s u c c t 1 , p r e d t 1 , i s z e r o t 1 ⊆ T ; if t1 ∈ T ,then{succ t1, predt1,iszerot1}⊆T; ift1T,thensucct1,predt1,iszerot1T;
  • i f t 1 ∈ T , t 2 ∈ T , a n d t 3 ∈ T , if t1 ∈ T , t2 ∈ T , and t3 ∈ T , ift1T,t2T,andt3T, t h e n then then i f if if t 1 t1 t1 t h e n then then t 2 t2 t2 e l s e else else t 3 ∈ T . t3 ∈ T . t3T.

推导规则定义

  • t r u e ∈ T false ∈ T 0 ∈ T true ∈ \text{T false} ∈ \text{T 0} ∈ T trueT falseT 0T
  • t 1 ∈ T pred t1 ∈ T \frac{t1 ∈ T} {\text{pred t1} ∈ T} pred t1Tt1T t 1 ∈ T iszero t1 ∈ T \frac{t1 ∈ T} {\text{iszero t1} ∈ T} iszero t1Tt1T t 1 ∈ T succ t1 ∈ T \frac{t1 ∈ T} {\text{succ t1} ∈ T} succ t1Tt1T
  • t1 ∈ T iszero t1 ∈ T t1 ∈ T t2 ∈ T t3 ∈ T if t1 then t2 else t3 ∈  T \frac{\text{t1 ∈ T iszero t1 ∈ T t1 ∈ T t2 ∈ T t3 ∈ T}}{\text{if t1 then t2 else t3 ∈ }T} if t1 then t2 else t3 ∈ Tt1 ∈ T iszero t1 ∈ T t1 ∈ T t2 ∈ T t3 ∈ T

具体定义

S 0 = ∅ S_0 = \emptyset S0=
S i + 1 = { true,false,0 } S_{i+1} =\quad \left\{\text{true,false,0}\right\} Si+1={true,false,0}
     ∪ { succ t1,pred t1,iszero t1  ∣ t 1 ∈ S i } \cup\left\{\text{succ t1,pred t1,iszero t1 }\mid t1 \in S_i\right\} {succ t1,pred t1,iszero t1 t1Si}
     ∪ { if t1,then t2 else t3  ∣ t 1 , t 2 , t 3 ∈ S i } \cup\left\{\text{if t1,then t2 else t3 }\mid t1,t2,t3 \in S_i\right\} {if t1,then t2 else t3 t1,t2,t3Si}

对项的归纳

常量集合

Consts(true)     = t r u e \text{Consts(true)} \qquad\qquad\qquad\ \,= {true} Consts(true) =true
Consts(false)   = false \text{Consts(false) \qquad\qquad\qquad\ = {false}} Consts(false)  = false
Consts(0)       = 0 \text{Consts(0) \qquad\qquad\qquad\quad\ \ \,= {0}} Consts(0)   0
Consts(succ t1)    = Consts(t1) \text{Consts(succ t1) \qquad\qquad\quad\,= Consts(t1)} Consts(succ t1) = Consts(t1)
Consts(pred t1)      = Consts(t1) \text{Consts(pred t1) \qquad\qquad\ \ \ \ = Consts(t1)} Consts(pred t1)     = Consts(t1)
Consts(iszero t1)    = Consts(t1) \text{Consts(iszero t1) \qquad\qquad\ \ = Consts(t1)} Consts(iszero t1)   = Consts(t1)
Consts(if t1 then t2 else t3)    = Consts(t1) ∪ Consts(t2) ∪ Consts(t3) \text{Consts(if t1 then t2 else t3) \,= Consts(t1) ∪ Consts(t2) ∪ Consts(t3)} Consts(if t1 then t2 else t3) = Consts(t1) ∪ Consts(t2) ∪ Consts(t3)

长度

size(true)     = 1 \text{size(true)} \qquad\qquad\qquad\ \,= 1 size(true) =1
size(false)   = 1 \text{size(false) \qquad\qquad\qquad\ = 1} size(false)  = 1
size(0)       = 1 \text{size(0) \qquad\qquad\qquad\quad\ \ \,= 1} size(0)   = 1
size(succ t1)    = size(t1) + 1 \text{size(succ t1) \qquad\qquad\quad\,= size(t1) + 1} size(succ t1) = size(t1) + 1
size(pred t1)      = size(t1) + 1 \text{size(pred t1) \qquad\qquad\ \ \ \ = size(t1) + 1} size(pred t1)     = size(t1) + 1
size(iszero t1)    = size(t1) + 1 \text{size(iszero t1) \qquad\qquad\ \ = size(t1) + 1} size(iszero t1)   = size(t1) + 1
size(if t1 then t2 else t3)    = size(t1) + size(t2) + size(t3) + 1 \text{size(if t1 then t2 else t3) \,= size(t1) + size(t2) + size(t3) + 1} size(if t1 then t2 else t3) = size(t1) + size(t2) + size(t3) + 1

深度

depth(true)     = 1 \text{depth(true)} \qquad\qquad\qquad\ \,= 1 depth(true) =1
depth(false)   = 1 \text{depth(false) \qquad\qquad\qquad\ = 1} depth(false)  = 1
depth(0)       = 1 \text{depth(0) \qquad\qquad\qquad\quad\ \ \,= 1} depth(0)   = 1
depth(succ t1)    = depth(t1) + 1 \text{depth(succ t1) \qquad\qquad\quad\,= depth(t1) + 1} depth(succ t1) = depth(t1) + 1
depth(pred t1)      = depth(t1) + 1 \text{depth(pred t1) \qquad\qquad\ \ \ \ = depth(t1) + 1} depth(pred t1)     = depth(t1) + 1
depth(iszero t1)    = depth(t1) + 1 \text{depth(iszero t1) \qquad\qquad\ \ = depth(t1) + 1} depth(iszero t1)   = depth(t1) + 1
depth(if t1 then t2 else t3)    = max(depth(t1) , depth(t2) , depth(t3)) + 1 \text{depth(if t1 then t2 else t3) \,= max(depth(t1) , depth(t2) , depth(t3)) + 1} depth(if t1 then t2 else t3) = max(depth(t1) , depth(t2) , depth(t3)) + 1

引理

一 个 项 上 t 中 不 同 常 量 的 个 数 不 大 于 t 的 长 度 s i z e ( t ) , 即 ∣ C o n s t s ( t ) ∣ ≤ s i z e ( t ) 一个项上t中不同常量的个数不大于t的长度size(t),即|Consts(t)| \leq size(t) ttsize(t)Consts(t)size(t)

定理(项上归纳原理)

假 设 P 是 项 上 的 一 个 谓 词 : 假设P是项上的一个谓词: P

对 深 度 的 归 纳 : 如 果 对 每 个 项 s 对深度的归纳:如果对每个项s s
假 设 对 所 有 使 得 d e p t h ( r ) &lt; d e p t h ( s ) 的 项 r 有 P ( r ) , 我 们 能 证 明 P ( s ) 假设对所有使得depth(r)&lt;depth(s)的项r有P(r),我们能证明P(s) 使depth(r)<depth(s)rP(r)P(s)
则 P ( s ) 对 所 有 的 s 成 立 则P(s)对所有的s成立 P(s)s
对 长 度 的 归 纳 : 如 果 对 每 个 项 s 对长度的归纳:如果对每个项s s
假 设 对 所 有 使 得 s i z e ( r ) &lt; s i z e ( s ) 的 项 r 有 P ( r ) , 我 们 能 证 明 P ( s ) 假设对所有使得size(r)&lt;size(s)的项r有P(r),我们能证明P(s) 使size(r)<size(s)rP(r)P(s)
则 P ( s ) 对 所 有 的 s 成 立 则P(s)对所有的s成立 P(s)s
结 构 归 纳 : 如 果 对 每 个 项 s 结构归纳:如果对每个项s s
假 设 对 所 有 s 的 直 接 子 项 r 有 P ( r ) 成 立 , 我 们 能 证 明 P ( s ) 假设对所有s的直接子项r有P(r)成立,我们能证明P(s) srP(r)P(s)
则 P ( s ) 对 所 有 的 s 成 立 则P(s)对所有的s成立 P(s)s

语义形式

求值

求值规则

  • if true then  t 2  else  t 3 → t 2 ( E − I f T r u e ) \text{if true then }t_2\text{ else }t_3 → t_2 (E-IfTrue) if true then t2 else t3t2(EIfTrue)
  • if false then  t 2  else  t 3 → t 3 ( E − I f F a l s e ) \text{if false then }t_2\text{ else }t_3 → t_3 (E-IfFalse) if false then t2 else t3t3(EIfFalse)
  • t 1 → t 1 ′ if  t 1  then  t 2  else  t 3 →  if  t 1 ′  then  t 2  else  t 3 ( E − I F ) \frac{t_1 → t_1&#x27;}{\text{if }t_1\text{ then }t_2\text{ else }t_3→\text{ if }t_1&#x27;\text{ then } t_2\text{ else }t_3}(E-IF) if t1 then t2 else t3 if t1 then t2 else t3t1t1(EIF)

一步求值关系

项上满足求值的最小二元关系

多步求值关系

多步求值关系是一步求值关系的自反传递闭包

范式

如果没有求值规则可以作用于项t,则该项是范式

受阻(stuck)

如果一个封闭项是一个范式但不是一个值,则称该项受阻

haskell实现

首先定义项。由于需要限制if的第一项类型为布尔型故添加了GADTs扩展

{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}

- term
data Term a where
  TmFalse :: Term Bool
  TmTrue :: Term Bool
  TmIf :: Term Bool -> Term a -> Term a -> Term a
  TmZero :: Term Int
  TmSucc :: Term Int -> Term Int
  TmPred :: Term Int -> Term Int
  TmIsZero :: Term Int -> Term Bool
- show terms
instance Show a => Show (Term a) where
  show TmFalse = "false"
  show TmTrue = "true"
  show TmZero = "zero"
  show (TmSucc a) = "succ " ++ show a
  show (TmPred a) = "pred" ++ show a

然后定义两个方法isnumericvalisVal,分别用来检验当前项是值还是数字

isnumericval :: forall a. Term a -> Bool
isnumericval TmZero = True
isnumericval (TmSucc a) = isnumericval a
isnumericval _ = False

isval :: Term a -> Bool
isval TmTrue = True
isval TmFalse = True
isval t = isnumericval t

然后定义求值方法,穷举所有可能项

eval1 :: Term a -> Term a
eval1 (TmIf TmTrue t2 t3) = t2
eval1 (TmIf TmFalse t2 t3) = t3
eval1 (TmIf t1 t2 t3) =
  let t1' = eval1 t1
  in TmIf t1' t2 t3
eval1 (TmSucc t1) = TmSucc t1'
  where
    t1' = eval1 t1
eval1 (TmPred TmZero) = TmZero
eval1 (TmPred (TmSucc nv1))
  | isnumericval nv1 = nv1
  | otherwise = error "unsupport rules"
eval1 (TmPred t1) = TmPred t1'
  where
    t1' = eval1 t1
eval1 (TmIsZero TmZero) = TmTrue
eval1 (TmIsZero (TmSucc nv1))
  | isnumericval nv1 = TmFalse
eval1 (TmIsZero t1) = TmIsZero (eval1 t1)
eval1 _ = error "unsupport rules"

可以看到上述求值代码有较多冗余,根据多步求值规则重写后如下

eval2 :: Term a -> Term a
eval2 a =
  case a of
    TmIf t1 t2 t3 ->
      case eval2 t1 of
        TmTrue -> eval2 t2
        TmFalse -> eval2 t3
    TmZero -> TmZero
    TmSucc a -> TmSucc (eval2 a)
    TmTrue -> TmTrue
    TmFalse -> TmFalse
    TmPred a ->
      case a of
        TmSucc b -> b
        TmZero -> TmZero
    _ -> error "unsupport rules"

上述实现可以看到,对于受阻项的处理都为打印错误信息。另外一种处理方式则是定义一个名为wrong的项,用来表示受阻项,有兴趣的可自行尝试。

当然,无类型的算术表达式十分简单。接下来就将进入 λ \lambda λ演算的世界…

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值