设计一个图灵非完备的编程语言。这件事情在外行人看来一点也不酷。就好比如果有人声称自己要做个“解决宇宙间一切计算问题的终极语言”,不管做得出来做不出来,总会有人把他奉若神明;也许很少有人意识到,只要有纸和笔,人人都是一台能解决任何计算问题的通用图灵机。自然,程序语言的可编程能力是纸带所无所比拟的:对于计算的规范化表述,高阶的数据抽象能力,丰富的类型系统,高度模块化及可重用性,等等。但,如果你不知道在纸上计算矩阵乘法的算法,而你的程序语言的库(注意——库不被看作是语言本身的一部分,即使是标准库)未曾实现这个功能,那么,再图灵完备、抽象能力再强的语言,也终究无法帮助你实现一个最简单的矩阵乘法。由此看来,设计一门语言并不能解决任何实际的问题;真正解决具体问题的,只能是设计算法的人。程序语言只是工具:表达思想的工具,表述计算过程的载体,无他。没有作为思想的算法灵魂,语言只是徒有其表的空壳。这就是为什么说程序语言的作用,常常被过分高估了的理由。

当然,如果有谁一上来就把“我想做个程序语言,它不是图灵完备的,基本上不可能解决所有的计算问题……”作为广告词,恐怕看见的人也只会哑然失笑。对于稍通一点计算理论的人来说,计算机具有和图灵机理论等价的计算能力是常识中的常识;而给某种计算机语言加上“图灵非完备”的限定,似乎等于是放弃了表达一切通用计算的能力,转而成为一个领域专有语言。

我要说的是,作为理论模型计算能力的图灵完备性质,与作为一种计算机语言的实际可编程能力之间是没有太多直接联系的。即使是理论上可以被证明是图灵非完备的计算机语言,仍然可以做到很多事情,从而足够资格被称作通用计算语言:

1、它可以用来实现一切可形式化验证的正确算法,但无法实现你自己都不知道是否停机的算法;

2、它可以用来实现永不终止但持续执行有效计算的软件,如一个操作系统、一个网站;但它无法实现空的死循环、爆栈而不产出有效数据输出的递归,或其他一切任何你认为“无用却不停机”的计算。

换言之,图灵机(或任何一种图灵完备语言)能实现而它所不能实现的计算,从实际的角度来看,基本上可说是没有意义的。譬如:你试图写一个“寻找正整数集中最大的素数”的算法,那么你在运行这个程序之前应该先从逻辑上理清这么做的意义:一旦程序找到了一个极大的素数,因为无法确定它是否为最大,它必须继续找下去。因此,不管这个最大的素数是否存在,程序为了输出正确的结果,将永远不会停机,你也就永远无法知道确切的答案。这样的计算除了让机器发热之外,意义何在?又譬如,你的程序若是要“寻找尽可能大的素数”,那么它总得时不时输出点什么,来确保它于你是有用的。一种图灵非完备的程序语言应当拒绝执行前一种 不停机不产出 的无效计算,从而使得自身失去和图灵机等效的计算能力;但它应当允许后一种 不停机持续产出 的有效计算,从而确保用它写出的程序永远是“有用的”。这些,构成了一种语言虽非图灵完备、其“有用”程度却丝毫不输于任何图灵完备语言的关键要素。

这样的图灵非完备程序语言实际存在着,但它们大多是因程序语言类型系统的研究用途而生,作为软件形式化验证的辅助工具而存在,并未有实际作为通用语言直接用于软件开发的尝试:如 Coq、Epigram 和 Agda。由于标准库中缺乏相应的支持,前两者甚至难以完成最简单的标准输入输出;而因为缺乏原生数据类型的实现,实际编程中司空见惯的整数、浮点数和字符串运算,到了这些语言中仍然极端繁琐。

作为证明辅助工具的它们,就纯函数式编程而言,其用途相当有限,不会超出为了对应 Curry-Howard 同构所需的范围。从它们的设计目的上很容易知道,这些语言本身不可能是图灵完备的;因为图灵完备意味着你可以写出没有终止的递归,这就破坏了类型所对应于逻辑的自恰和完备性,正如要回答“全能的上帝能造出一块他自己都搬不动的石头吗?”这个问题般,让机器的类型检查陷入无尽的逻辑循环推演;而我们知道,一次永不停机的证明是一次无效的证明,否则我们也就能够轻易地写出一个不停机的程序去验证哥德巴赫猜想对于一切数的情形都成立了。至于“纯函数计算是没有副作用的”,这一点更是老生常谈了,一个东西一旦被定义,那么它的值绝不能被改变;因为对于依赖于值的类型而言,一个值若可以在运行时改变,那么类型系统(编译时的类型检查即为证明)将失去它的意义,故而 依赖类型的语言几乎总是纯函数式的 ,从而使得它们无法直接完成对 状态量 的操作。

看起来,这种语言似乎没有什么实用价值。然而一旦接受了“计算过程本身也可以是计算处理的对象,对于计算之计算”这种设定,将对计算的描述本身借助于 Monad 归一化到它们的类型系统中,那么正如 Haskell 能够容纳副作用(状态、输入输出)于函数式计算的体系中一般,它本身虽为纯函数范式的数学语言,却可以用来实现非纯的外部物理过程;更进一步,一旦通过 codata 来描述无限的数据结构,它本身虽非图灵完备的语言,却可以用来模拟任何不停机的计算。

这是一个非常巧妙的问题:既然我已经鼓吹图灵非完备语言可以和图灵完备语言一样实用,足够完成任何有实际价值的计算,那么我必须用它写出一个图灵完备语言的解释器来证明这一点,因为“图灵完备语言的解释器”显然也属于所有“有实际价值”的程序范畴内;而一旦当我这样做了,似乎就等于是用一个计算模型模拟了一个图灵机,从而证明我原来的计算模型不可能是图灵非完备的。

现在,既然我们已经提到了这种图灵非完备语言的存在性与实用性,你可能不禁想问:能否用这种图灵非完备的语言,去实现一个图灵完备语言的解释器呢?这看似自相矛盾而又无比自恰,看似痴人说梦却又实在可及,其招致误解的根源在于人们总是习惯性地把“程序语言”和“计算模型”等同起来:Brainfuck、C、Pascal 是命令式的语言,它们等价于图灵机;Unlambda、Scheme、Haskell 是函数式的语言,它们等价于λ演算。故而这些语言都是图灵完备的,因为它们可以实现与图灵机等效的计算过程。这种说法看似没有什么问题,程序语言本来就是为了描述计算而生的实用工具,而抽象的计算模型才是真正描述计算的方法学。如果说图灵完备可以成为衡量计算模型计算能力的尺度,那么体现这些具体计算模型的程序语言,自然也就存在着相应计算能力的说法。我还可以在这里举出很多例子:正则表达式不是图灵完备的,所以像嵌入在通用程序语言里的 PCRE 库这类正则实现不是图灵完备的;谓词逻辑是图灵完备的,所以嵌入在通用程序语言里的 miniKanren 是图灵完备的;递归函数是图灵完备的,所以 C++ 里的模板是图灵完备的;项重写系统是图灵完备的,所以 Maude 是图灵完备的;马尔可夫算法是图灵完备的,所以 Refal 是图灵完备的;如此种种,数不胜数。

但是,今天的一些程序语言,已然超越了单一计算模型的范畴;单一的计算过程,已经不再适于描述所有程序语言的工作方式——不,我甚至不是在讨论副作用这件事情。就程序本身而言,有些程序语言能做的事情,图灵机是做不到的。这其中的一个典型例子,就是元编程。

给图灵机一连串指令,它能够执行任何计算,也可以模拟纯数学的λ演算;给λ演算一系列定义,它能够编码出世间万物,也可以模拟出基于顺序执行的机器。而它们都无法做到的,是改变自身被分配的指令或定义,也就是它们所注定的计算本身。然而,对于某些具有元编程能力的计算机语言来说,你可以在程序里嵌入一套规则,让这套规则具有操纵“计算”本身的能力。

以许多人都熟悉的 C++ 为例:你可以把 C++ 里的任意循环、递归函数的能力拿掉,从而成功地把它阉割成为一个必定停机的图灵非完备语言(事实上你不必通过强制所有程序停机来使得一个语言图灵非完备;但这么做可以简单粗暴地达到我们的目的)。在这种情形下,你将不能用 C++ 自身的语言来模拟一个图灵机,因为它已经不具备通用计算的能力;但是,没有什么能阻止你用 C++ 模板来实现这一切。换言之,C++ 的语言规范至少实现了两个相互独立的计算模型:C++ 自身的语言,和其嵌入的模板语言。由此来看,仅仅用“图灵完备”来形容 C++ 的计算能力是不够的,因为 C++ 作为一种程序语言,并不是 一个 图灵完备的计算模型,而体现着 两个 相互独立的图灵完备计算模型。

既然理解了“程序语言不必等同于计算模型”这件事情,前面的矛盾也就迎刃而解了:你实际上可以在图灵非完备的程序语言里内嵌一个图灵完备的计算模型 ;因为这个图灵完备的计算模型可以用来实现任何计算,因此,也就间接为使用该(图灵非完备)语言来实现一个图灵完备语言的解释器提供了无限的可能性。

这样容纳了另一个计算过程于自身内的程序语言,其计算潜力是无法用单一模型(如图灵机)的计算能力来完整表达的,正如你无法把 C++ (连同模板在内)的计算方式转化成单一的图灵机指令序列一样。C++ 模板元编程在这里也许并不是一个很好的例子;实际上,你可以把任何图灵完备的计算过程容纳到一门语言的类型系统里,从而让一门程序语言自身的计算模型虽非图灵完备,却可以借纯函数式的类型系统之手完整地描述图灵完备的计算模型。

图灵非完备语言的“有用性”,将会随着今后对于程序语言和类型论的研究愈加深刻地体现出来。

“非图灵完备”到底意味着什么相关推荐

  1. 互联网时代的B2B电商系统到底意味着什么

    互联网时代,很多企业纷纷想要开展属于自己的业务,可是在当下的电商体系当中,B2B电商系统是发展最快最成熟的一种电商模式,其中使用数 商 云 电商系统是当下比较流行的一种模式,想要知道更多的B2B电商系 ...

  2. 数字化改造转型到底意味着什么

    数字化改造转型这一周期性的热门术语再度火爆,但大多数人不明白其真正的实力所在. 数字化改造转型,又名DX,在时下是相当热的--而如果您不这样做,您所在的公司会被淘汰,而您自己也或将失去您的CIO或IT ...

  3. 任正非:到底什么样的人才能当干部

    任正非:到底什么样的人才能当干部?   干部要长期艰苦奋斗   我们培养人的目的,是要为实现企业目标而努力奋斗.如果缺少这种品德的人,担任了各级负责干部,团队就会逐步惰怠,就像温水煮青蛙一样,企业会逐 ...

  4. 认真工作对自己到底意味着什么?

    现在年轻人当中有一种旺盛的倾向在滋长,那就是厌恶工作,逃避责任,甚至会对积极工作的人报以嘲笑,人们越来越追求轻松挣钱,且最好是不劳而获,及时行乐,哪怕是得过且过的生活状态.这不仅让我们去思考,人类年轻 ...

  5. java静态类和非静态类的区别_Java中静态内部类和非静态内部类到底有什么区别?...

    内部类(Inner Class)和静态内部类(Static Nested Class)的区别: 定义在一个类内部的类叫内部类,包含内部类的类称为外部类.内部类可以声明public.protected. ...

  6. python 图灵完备_图灵完备到底是个什么鬼?

    题记:看资料时经常看到图灵完备这四个字,但完全不知道什么意思,所以整理了关于图灵完备的资料. 1.图灵 艾伦·麦席森·图灵(Alan Mathison Turing,1912年6月23日-1954年6 ...

  7. 计算机科学与技术专业师范与非师范,同一个专业,师范和非师范到底有啥区别?...

    填志愿的时候,师范,是家长们最喜欢问的专业.同时也会问一个问题:我听说人家非师范专业的也能考教师资格证,那我有必要读师范专业吗?今天就聊一下师范专业和非师范专业到底有什么区别! 一般来说,在报志愿的时 ...

  8. PCG、可微渲染、原生云......这些“时髦词”对游戏到底意味着什么?

    来源:游戏陀螺 8 月14-17 日,由腾讯游戏学堂举办的第六届腾讯游戏开发者大会(简称TGDC)顺利举行.大会以Inspire Six Senses为主题,汇聚国内外顶尖游戏从业者以及学界专家学者, ...

  9. 拆分大科技公司到底意味着什么?

    许多对当今庞大科技公司的批评者越来越有信任情绪,但尚不清楚该采取什么措施来缩小它们的规模. 对于苹果.亚马逊.脸书和谷歌来说,covid-19是经济上的福音.尽管流感大流行导致全球经济陷入深度衰退,并 ...

最新文章

  1. 集五福,我用Python
  2. go移植linux内核书名叫啥,Go语言移植Linux内核数据结构hlist
  3. python 完全面向对象_史上最全的Python面向对象知识点疏理
  4. postman跨域测试_安装使用Hoppscotch构建API请求访问与测试
  5. 二分答案——H指数(Leetcode 274)
  6. ui kit模板的用途是什么?
  7. java web典型模块大全_python+selenium基于po模式的web自动化测试框架
  8. 比尔·盖茨承认犯下 4000 亿美元大错:误给 Google 推出 Android 机会!
  9. camera驱动电源配置_基于AD7656-1和ADuC7026评估电源时序控制影响
  10. JDK环境变量设置以及检验是否配置成功
  11. Xcode9 iOS12 支持包
  12. R 语言 中的条件推理树
  13. 使用ftl生成word
  14. 刷IP工具、刷IP软件的原理和工作过程
  15. Bmob后端云上传多张图片
  16. dell笔记本外接显示器_戴尔笔记本怎么连接外接显示器?
  17. NOIP2018 自闭记
  18. EXCEL中发现不可读的内容。是否恢复此工作薄的内容?如果信任此工作薄的来源,请单击”是“
  19. PX4二次开发——PX4程序架构
  20. 【solarwinds】【Orion】综述

热门文章

  1. 《图像超分辨率研究综述》笔记
  2. SCOI-2017 游记 SCOI-2017 酱油记 SCOI-2017 没有滚粗资格的记
  3. 手把手教你用Unet实现语义分割(Pytorch版)
  4. Java.Canvas
  5. 5款服装进销存软件测评,教您如何挑选出好用的
  6. 千张照片合成你一张美照-【OpenCV实战二】
  7. 520 钻石争霸赛 7-2 真的恭喜你 (10分)
  8. 了解一个人最好的方式就是和他(她)去旅行,
  9. Uva 167 The Sultan's Successors(dfs)
  10. 黑马程序员——JAVA集合