0 前言

在看论文的时候,发现用了Haskell,本来想温故一下,发现有篇文章写的不错,转过来,大家分享一下。以下是原文。

在之前的一篇博文里,我推荐从函数式语言入手掌握程序语言。推荐的两种语言是 Scheme 和 Haskell。可是出于多种原因,我必须告诉大家,我已经不再推荐 Haskell。这里的原因比较深入,可能不容易说清楚,所以只简述一下。如果有异议的话,可以来信跟我讨论,这样也可以帮我理清思路。

先说说之前推荐 Haskell 的原因吧。推荐它其实是因为是它的类型关系较 Scheme 清晰,并且有模式匹配等方便的功能。可是类型系统和模式匹配,却不是 Haskell 所专有的。其它的一些语言,比如 OCaml 和 Racket 也有很方便的模式匹配和能力相近的类型系统。

现在停止推荐 Haskell,其实是出于很多原因的积累:

1. 类型系统过于复杂

最开头的时候,Haskell 使用的是普通的 Hindley-Milner 类型系统(HM 系统)。使用这种类型系统的原因是因为程序员不需要写任何类型标记(typeannotation)就可以“静态”的确保类型的正确。可是这样做的代价是,这个类型系统表达能力太弱。很多程序需要拐弯抹角的绕过这个类型系统的种种限制才写得出来。比如,Haskell 的 sum type 导致 constructor 的非常麻烦的多重嵌套,这我已经在一篇英文博文里面比较隐晦的批评了一下。显然 HM 系统灵活性太差,所以 Haskell 内部后来引进了 SystemFw。可是这些系统发展了好多年,还是不能解决问题。到现在,你仍然会在 Haskell 里面遇到莫名其妙的限制。你觉得程序应该编译通过,可是它就是编译不过(比如我这篇英文博客所述)。究其原因,其实是类型系统有问题,而不是程序员的思路有问题。

有的 Haskell 程序员可能会反驳,说是因为我不能理解 Haskell 的类型系统。那么我可以告诉你,我不但实现了 Haskell 和 ML 所用的 HM 系统,而且实现了比 HM 还要强大的 MLF, intersection type 等类型系统。Haskell 推导不出来的类型,我的系统可以推导出来。所以我说的话其实是出自第一手的依据。

2. 参数和返回值的类型标记很有必要

与 Haskell 同门的 SML 和 OCaml 的类型系统也有类似的问题,甚至更加严重(比如 ML 有 value restriction,导致不必要的约束和困惑)。但是很多“常规语言”,特别是像 Java,C++ 等需要类型标记的语言,却没有这个问题。很多人喜欢 Haskell 都是因为用它可以“不写类型标记”,可是现在呢,最好的 Haskell 程序员都是先把类型写下来,才开始写函数。一来这样思路清晰,你知道这函数要处理哪些类型的数据,你就明确的把它写下来,以后再来看,或者给其他人看,都一目了然。二来是因为 Haskell 的类型系统由于加入的一些“不可判定”(undecidable)的扩展功能,有时候已经无法推导出类型了。而给函数的参数和返回值加上类型标记之后,就可以轻松推导出类型。所以你看到,给参数和返回值加上类型标记,不管是对人还是对机器,都有好处。所以经过我一学期的研究得出的结论是,HM 系统的类型推导,其实是多此一举。

不过需要注意的是,函数的局部变量,其实是不需要类型标记的。比如在 Java 程序里常见的:

List ls = newArrayList();

这样的赋值语句,其实是没必要在左边加一个类型标记的,因为右边的类型我们知道。在这一点上C++11 的 “auto” 是一个正确的方向。比如在 C++11 里,你可以写:

auto ls =newArrayList();

这种类型推导不难做,基本就是一个抽象解释器。我给 Python 做的 PySonar 类型推导系统里面就实现了这样的功能。

对任何语言,具体是哪些地方有必要加上类型标记呢?其实有一个很简单的方法来判断:观察信息进出函数的“接口”,把这些接口都做上标记。直观一点说,函数就像是一个电路模块,只要我们知道输入和输出是什么,那么中间的导线里面是什么,我们其实都可以推出来。类型推导的过程,就像是模拟这个电路的运行。这里函数的输入就是参数,输出就是返回值,所以基本上把这两者加上类型标记,里面的局部变量的类型都可以推出来。另外需要注意的是,如果函数使用了全局变量,那么全局变量就是函数的一个“隐性”的输入,所以如果程序有全局变量,都需要加上类型标记。

3. “纯函数式”并不是好主意

我最近常常跟同学开玩笑,说“纯函数式”语言是什么意思。“纯函数式”语言是用来描述这样一个世界的,在这个世界里,所有的东西都是“有线”的(wired)。不存在 3G,4G,不存在 wifi,收音机,卫星电视…… 所谓的 monads,其实就是这个布满电缆的世界里的“接线盒”。

Haskell 编程之麻烦,就是因为这些电缆。你必须小心翼翼的把它们接在一起,安排好,否则就会有各种问题,甚至绊到脚。连生成随机数这么简单的事情,你都得学会使用各种各样的“随机数 monads”。这是因为我们需要记录随机数发生器的“状态”,所以随机数 monad 输入一个随机数发生器,返回一个随机数以及一个新的随机数发生器!想一想,在 C 语言里面,你只需要一个全局变量或者函数内部的 static 变量来记录随机数发生器的状态。到底是谁简单,谁复杂?我想你可能已经意识到,全局变量其实就是 wifi!

Haskell 的支持者常说,纯函数的语言容易“推理”,容易确保程序的正确。因为它的程序就像“数学的函数”,给同一个输入,就会得到同一个输出。这叫做“referentialtransparency”。可是这种性质,真的可以让程序容易“推理”吗?如果 Haskell 的函数使用了 monads,比如“状态”(statemonad),那么这个函数的“输入”,就几乎永远不会相同。因为那个状态每次都可能变化,所以你实际上还是没法知道那里面是什么!

记住这一点:世界上没有包治百病的神药。

4. 惰性求值(lazyevaluation)不是好主意

关于惰性求值,我基本同意 Robert Harper 的观点。惰性求值让类型变得混乱,让程序的时间和空间复杂度难以分析,而且跟并行计算的原则有根本性的矛盾。而惰性求值的功能,却不是经常有用的。即使需要,在普通的语言里也可以通过 thunk 来实现。所以,惰性求值带来的问题恐怕比它解决的问题还要多。

很多自称“从 Haskell 衍生”的语言,很多其实都只是有其形,而无其实。一个例子就是 Bluespec,一种硬件描述语言。它虽然自称是从 Haskell 演变来的,看起来像 Haskell,但是它却不是惰性的,类型系统也很简单,所以基本上它已经不是 Haskell。打着 Haskell 的旗号,恐怕是想借助 Haskell 的名声来抬高自己,或者是因为 Bluespec 的创造者 Lennart Augustsson 最早的时候是 Haskell 的主要发起人之一。

5. 思想局限

所以综上所述,Haskell 自称的“特性”几乎被实践一一推翻。可是 Haskell 程序员往往炫耀自己的“函数式编程”水平,其实经常陷入一些很难理解的“设计模式”,无法自拔。鉴于这个原因,我停止向大家推荐 Haskell。

另外需要申明一下的是,我停止推荐 Haskell 并不是因为我想力推 Scheme。实际上 Scheme 也有自己的问题,但是相对来说,它更加简单易懂,符合学习的需要。另外,以前对 C 和 C++ 的批评也许过于偏激。最近为了在 LLVM 上做一些事情,开始重新理解C++,发现它做的好些事情其实是挺不错的,甚至超过好些最炫的,带有“dependenttype”的函数式语言。所以现在我觉得,其实世界上的语言并没有什么绝对的标准。在一段时间认为是错的东西,可能却是对的。所以不用盲目的排斥一些语言,把它们都拿来看一下,互相对比,才会知道到底什么是好的。

王垠:不再推荐 Haskell相关推荐

  1. 王垠:我和权威的故事

    转自王垠博客,我是垠粉. 每个人小时候心里都是没有权威的,就像每个人小时候也都不相信广告一样.可是权威就像广告,它埋伏在你的潜意识里.听一遍不信,听两遍不信,--,直到一千遍的时候,它忽然开始起作用了 ...

  2. 点评一下王垠的新博文: Oberon 操作系统:一个被忽略的珍宝

    远古邪恶巨坑的日记 远古邪恶巨坑的主页 广播 相册 喜欢 活动 发豆邮 点评一下王垠的新博文: Oberon 操作系统:一个被忽略的珍宝 2013-03-08 16:31:26 原文链接: http: ...

  3. 清华梦的粉碎——转自王垠

    小时候,妈妈给我一个梦.她指着一个大哥哥的照片对我说,这是爸爸的学生,他考上了清华大学,他是我们中学的骄傲.长大后,你也要进入清华大学读书,为我们家争光.我不知道清华是什么样子,但是我知道爱迪生和牛顿 ...

  4. 清华梦的粉碎——写给清华大学的退学申请by王垠

    清华梦的诞生 小时候,妈妈给我一个梦.她指着一个大哥哥的照片对我说,这是爸爸的学生,他考上了清华大学,他是我们中学的骄傲.长大后,你也要进入清华大学读书,为我们家争光.我不知道清华是什么样子,但是我知 ...

  5. 王垠 --清华梦的粉粹

    清华梦的诞生小时候,妈妈给我一个梦.她指着一个大哥哥的照片对我说,这是爸爸的学生,他考上了清华大学,他是我们中学的骄傲.长大后,你也要进入清华大学读书,为我们家争光.我不知道清华是什么样子,但是我知道 ...

  6. 清华梦的破碎——写给清华的退学申请 王垠

    清华梦的破碎--写给清华的退学申请 王垠 经过深思熟虑,我决定放弃清华大学的博士学位.其中的原因,你们有兴趣的话可以看看下面的文章.这就是我的一生与中国教育的故事.一个用血和泪换来的教训. 清华梦的粉 ...

  7. AI人工智能的局限性--王垠

    人工智能的局限性 有人听说我想创业,给我提出了一些"忽悠"的办法.他们说,既然你是程序语言专家,而现在人工智能(AI)又非常热,那你其实可以搞一个"自动编程系统" ...

  8. [荐][转]王垠:我和权威的故事(2014)

    王垠的相关文章: http://docs.huihoo.com/homepage/shredderyin/index.html http://news.cnblogs.com/n/tag/%E7%8E ...

  9. 反清华博士王垠(未来人类科学家在中国的毁灭)

    清华博士王垠的退学申请 http://edu.QQ.com 2005年 09月 26日 11:47 经过深思熟虑,我决定放弃清华大学的博士学位.其中的原因,你们有兴趣的话可以看看下面的文章.这就是我的 ...

最新文章

  1. 【算法】均匀的生成圆内的随机点
  2. 向设计师分享最新30款免费英文字体
  3. Servlet WEB过滤器
  4. 关键词优化一定要从正规渠道入手
  5. P1014Cantor表(找规律)
  6. NOI.AC#2144-子串【SAM,倍增】
  7. 光纤收发器长距离的传输过程出现死机的解决方案
  8. 复制粘贴不连续单元格_表格筛选状态下怎么复制粘贴数据
  9. codeforces332B - Maximum Absurdity 线段数 or dp
  10. seci-log 1.06 发布 增加全文搜索
  11. mysql经纬度 微信_微信获取用户的经纬度
  12. 网易企业邮箱登录服务器出错,网易企业邮箱登录出现故障,无法正常登录
  13. C++ 在栈上分配内存
  14. app支付宝接入流程图_Android App支付系列(二):支付宝SDK接入详细指南(附官方支付demo)...
  15. java pacs上传服务_医疗pacs系统影像数据的同步方法及前置服务器的制造方法
  16. 机器学习知识总结 —— 11. 关于目标检测中的IoU是什么
  17. 陈皓:什么是工程师文化?
  18. JMS入门(一)--JMS基础
  19. 杂七杂八(5): 文件图标变白纸 解决方法(在Windows 10中修复损坏或丢失的图标和缩略图)
  20. Artifactory 简介

热门文章

  1. 【光程科技】IOS上架图标问题
  2. NMF通俗理解及python实现
  3. 京东数科喜提新裤子,员工主题曲来了!
  4. CSS3 background-size图片自适应
  5. 【Matlab】蒙特卡洛算法
  6. 告别卸载软件难 四大方法轻松搞定
  7. Gparted使用(亲测实体机)
  8. 【电池健康状态预测】基于灰狼算法优化BP神经网络实现电池健康状态预测附matlab代码...
  9. 第四章第8节 网络中的网络(NiN)
  10. 纪念过去的一年 之V