【TAPL学习笔记 1】Untyped Arithmetic Expressions


为了严格讨论类型系统以及它们的性质,我们需要从形式化地处理一些程序语言更基础的方面来开始。特别的,我们需要清晰的,精确的以及数学意义上容易处理的工具来表达和推理程序的语法【syntax】以及语义【semantic】。
本章和下一章主要针对包含数字以及布尔值的简单语言来开发所要求的工具。这个语言很平凡,但可以作为引入一些基础概念的载体–抽象语法、归纳定义以及证明、求值、运行时错误的模型。第5章到第7章针对更强大的语言–无类型lambda 演算,详细阐述了相同的事情,我们必须处理名称绑定以及替换的问题。继续往前看,第8章将回到本章的简单语言引入静态typing的内容。第9章将typing扩展到lambda演算中。

3.1 Introduction

本章使用的语言语法可以总结为下图:
在这里插入图片描述
注意这里右边的t表示元变量(meta-variable),这意味着它是对于特定term的占位符。

当前语言的一个程序仅仅是一个term,它主要是由上面给定的语法规则来构造的。这里有一些程序的例子,以及它们的结果。
在这里插入图片描述
求值的结果是某些简单形式的terms:它们总是布尔常量或者numbers。这些term称为values,并且它们将在我们对于求值顺序的形式化中发挥作用。
注意term的语法允许一些不好的term表达,比如succ true 以及 if 0 then 0 else 0。我们将在之后讨论这个问题–事实上我们想让类型系统排除这种情况。

3.2 Syntax

有一些等价的方式定义我们语言的语法。上面的语言实际上只是下面这种归纳定义的紧凑表示:
在这里插入图片描述
实际上,我们是将T定义为了树的集合而不是字符串的集合。下面是使用二维的推理规则(inference rules)来进行定义:
在这里插入图片描述
这里需要知道两个术语:(1)axioms: 没有前提的规则,术语inference rule通常包含axioms和“proper rules”。(2)inference rules实际上是rule schema,可以代表无限的具体集合。

最后还存在一种不相同的定义,是一种更加具体的风格来生成T中元素。
在这里插入图片描述

3.3 Induction on Terms

我们可以发现,如果t属于T,那么必存在一种情况是真的:(1)t是常量(2)t有succ t1, pred t1 or iszero t1的形式(3)t有if t1 then t2 else t3的形式。
我们可以通过两种方式使用这个观察:(1)给出函数的归纳定义(inductive definition) (2)给出terms性质的归纳证明。

下面为一个归纳定义的例子:
在这里插入图片描述
另一个可以通过归纳定义计算的term性质是它们的size
在这里插入图片描述
这里有一个将terms中constant数目与它的size联系在一起的归纳证明。
在这里插入图片描述
我们可以将这个证明过程重述为更加通用的推理原则。
在这里插入图片描述
我们一般更常用structural induction,分开地考虑t可能具有的每个形式。
在这里插入图片描述
在一些更简单的情况下,我们直接写"by induction on t"就可以是一个完美的证明。

3.4 语义风格

我们已经严格形式化了我们语言的语法,接下来需要一个terms如何计算的精确定义–即,语言的语义部分。有三种基础的方法形式化语义:

  1. 操作语义(Operational):通过定义抽象机器来指定语言的行为。这个机器是抽象的,直接使用term作为机器码。对于简单语言来说,一个机器的state仅仅是一个term,机器的行为是通过转换函数来定义,要么可以通过简化步骤转化到另一个state,要么终止。一个term的含义可以通过机器的终止态来得到。有时实现两种语义是有用的,一个更abstract,另一个更接近真实解释器的处理。证明这两种不同的行为以某种合适的方式对应就是在证明语言实现的正确性。
  2. 指称语义(denotational):需要找到semantic domains以及interpretation function(将terms映射到domains内的元素上)
  3. 公理语义(axiomatic):让laws自身成为语言的定义,一个term的含义就是关于它什么可以证明。 不变量(invariants)的概念比较重要。

我们在这本书中将使用操作语义。

3.5 求值[Evaluation]

我们先只考虑布尔表达式的情况。
在这里插入图片描述
左边是定义了两种表达式的语法,其中第二个定义了terms的一个子集,我们称为values。元变量v在整本书中都代表values。

右边定义了terms上的求值关系,写作 t->t’。这个关系通过三条推理规则进行定义。
注意这里规则没有表述的与规则所表述的同样重要,布尔常量true和false不能求值。此外,我们只能先对if t1中的t1先进行求值。我们有时称E-IFTRUE和E_IFFALSE为计算(computation)规则,称E-IF为一致规则(congruence)。

我们可以有如下对求值关系的形式化定义:
在这里插入图片描述
在这里插入图片描述
一个给定陈述的导出性(derivability)可以通过推导树表示。
在这里插入图片描述
我们的一步求值展示了一个抽象机器是如何从一个state到达另一个state的。但就像程序员通常只感兴趣求值的最后结果–即一个不能继续求值的状态。
在这里插入图片描述
在这里插入图片描述
在当前系统中,上面定理的逆命题也是对的,但这不是通常的情况。非值的正规式在我们对于运行时错误的分析中发挥重要作用。
在这里插入图片描述
我们可以定义多步求值关系:
在这里插入图片描述
在这里插入图片描述
Proof. 单步求值确定性的推论。

在我们关注算术表达式之前,还有一个事实需要知道:每个term都能被求值为value。注意到这一性质在更复杂的语言中,比如含有递归函数定义,并不需要成立。在第12章,我们将回到这点,展示类型系统是如何作为某些语言的终止性证明的骨架。

计算机科学中大多数的终止性证明都有相同的基础形式:

  1. 选择一个集合well-founded S【每个子集存在极小元】,并设置一个函数f,将机器状态(这里为terms)映射到S中
  2. 无论机器状态t何时做一步操作转为另一个状态t’,我们有f(t’)<f(t)。
  3. 我们现在观察到一个从t开始的无穷求值序列可以通过f映射为S中的无穷元素递减序列。注意到,我们的S应该是有限的,所以不可能存在无穷序列。此处的f我们称为终止度量(termination measure)。

在这里插入图片描述
Proof. 这里的终止度量为size,并且自然数的常规序是良基的。

我们接下来需要将求值的定义扩展到算术表达式。
在这里插入图片描述
这里指的定义更有趣,因为引入了一个新的语法类别 numeric values。直觉上算术表达式的求值结果应该是数字,要么为0要么为某个数的后继。【注意不能是任意值的后续,比如succ true我们认为不是值】。

右边有四个计算规则【PREDZERO, PREDSUCC,ISZEROZERO,ISZEROSUCC】,以及三个一致规则【SUCC, PRED,ISZERO】

下面是一个表达式的导出树:
在这里插入图片描述
注意到false的后继并没有定义,我们称succ false这种term为stuck。
在这里插入图片描述
Stuckness 可以作为run-time error。在语言实现中,这些不好的状态可能对应不同种类的机器错误:段错误,非法指令的执行等。这里我们将所有这些bad behavior融入一个单独概念“stuck state”。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值