QCon 演讲火热征集中,快来分享技术实践与洞见! 了解详情
写点什么

专访《Haskell 函数式编程入门》作者张淞:浅谈 Haskell 的优点与启发

  • 2015-08-20
  • 本文字数:3448 字

    阅读完需:约 11 分钟

张淞,Haskell 语言爱好者,著有《Haskell 函数式编程入门》一书。目前就职于网易杭州研究院。在10 月15 日~17 日的 QCon 上海 2015 上,他将分享《Haskell 中的函数与类型系统》

Haskell 中的主要概念其实都是围绕类型展开的,类型系统主要是为我们管理程序的抽象与保证程序的正确性而引入的。为了更好的复用代码,于是有了多态类型。某些类型有着共同的属性,于是 Haskell 引入了类型类来管理它们。有一些类型是需要接受一个或者多个类型参数的,为了保证这一环节不会出错,于是 Haskell 又引入了 kind 这一概念;同样出于复用代码的原因,Haskell 又引入了 kind 多态。总之,抽象在一步一步加深,每加深一步就总结出更多公共的代码,为我们自动完成更多事情,而带来的问题就是会让人更加难以理解。所以了解 Haskell 的类型系统对于我们理解代码的复用、抽象非常有帮助。所以本次的演讲主要包括:

  • Haskell 中的值
  • Haskell 中的类型
  • Haskell 中的类型类
  • Haskell 中的类型的 kind
  • 以上特性之应用

Haskell 不仅仅是一门学术型的语言,而是一门非常适用于编写应用软件的工程型语言,其实相当多的思想是可以迁移到非函数式语言上的,但是对想要应用这些思想的人来说,在思维的转变上可能会有更长的路要走。主要的问题是,现在的人们习惯于他们已经熟悉的东西,需要学习如何让函数编程中的理论来指导实践编程,最大程度上减少重复,用更少的代码完成更多的工作。

在大会开始前,InfoQ 采访了张淞,谈到了 Haskell 的优点,对实际编程的启发等话题。以下为采访内容:

InfoQ:您好,可以简单做一下自我介绍吗?

张淞:我本名叫张淞 ,网上叫阅千人而惜知己,算是一个文艺屌丝吧。2012 年从英国诺丁汉大学本科毕业,2013 年从牛津大学研究生毕业,都是计算机科学专业。课程并没有特别明确的方向,但是由于偏爱函数式编程与编程语言一些,所以选课大多与之相关。2014 年年初,因为母校宁波诺丁汉大学空缺一个临时的教职,于是牛津大学毕业后就先决定回国任教了,全职教授函数式编程这门课,所用的语言就是 Haskell。目前供职于网易杭州研究院,现在的工作与数据分析相关。

InfoQ:从学校到公司应该有很多不同,可以分享一下这方面的感受么?

张淞:在学校工作时我没有研究压力,所以是比较自由的。在教函数式编程之前,这门课的课本我已经读了 5 遍,并且已经译成中文。书很薄,是由我在英国诺丁汉大学的老师 Graham Hutton 教授著的。后来在牛津又旁听了一遍这门课,当时还给有问题的同学答疑,所以回到宁波诺丁汉大学,教大二的学弟学妹们基本上是驾轻就熟的。教学任务也不是很大,一周大约有 2 小时的教学还有 2 小时的研讨课,课件、课本、练习、试卷的参考很多,也不用太花时间准备,所以比较轻松。有时间可以做自己喜欢的事,从 SICP 那本书上找一些题出给学生,读一些 Haskell 相关的论文。而在公司则不太一样,但是在网易杭州研究院,好处就是我们的工作不太会受到技术的限制,完全是由我们做什么、想怎么做决定的,不单调也不乏味,但只是感觉在公司的工作压力比较大,因为自己的工作关乎到其他同事的进度,但即便如此还是比较开心,因为还在做着自己喜欢的事。

InfoQ:Haskell 吸引你的地方是?

张淞:严格地说我的第一语言是 Java,教我学 Haskell 的人正是招我回去教书的那位老师。很坦诚地讲,Haskell 在一开始并不吸引我,纯函数、没有变量让当时的我十分困惑并且有点抵触。后来考试完,在学校的图书馆里解了 24 点,发现用 Haskell 比同学的 Java 解法长度短了接近 10 倍,后来又解决了八皇后问题,也是比 Java 少了近 10 倍的代码;先不说效率,单纯在表达能力上,Haskell 是不能与其他如 Java 一类的语言同日而语的。偶然间又在学校图书馆里发现了 Real World Haskell,完全颠覆了我对 Haskell 肤浅的认识,才知道那薄薄的课本连 Haskell 的冰山一角都不算。

Haskell 吸引我的地方主要是,强大的类型系统十分严谨,部分地方严谨到让人“发指”。这里可以举一个例子,3.14 是小数,3.14e3 等于 3140,而 3140 可以当成数字来处理,因为它可以是整数,也可以是小数,所以应该归属于一个更为一般的类型类 Num 而不是 Integral 或者 Fractional:

复制代码
> :t 3.14
3.14 :: Fractional a => a
Prelude> :t 3.14e3
3.14e3 :: Fractional a => a
Prelude> :set -XNumDecimals // 开启语言扩展
Prelude> :t 3.14e3
3.14e3 :: Num a => a

我没有看到任何语言注意到了这种类型上的微妙变化,Clojure 里直接就是 Double 了。Haskell 里数字类型与数字类型类的关系是相当严谨的,严谨到如果没有一定的理论背景根本不会清楚它背后这么设计的原因,Haskell 里有很多不断颠覆我之前思想的设计。有这样细致入微的类型系统辅助可以保证很大一部分错误不会出现,因为根本写不出来不满足类型的代码,并且在我们的头脑并不清醒的时候编译器会始终帮助你保持理智。

另外,Haskell 的基础 API 设计非常有条理,这也是一些语言比如 Scala 的 scalaz、JavaScript 的 Prelude.ls、Ix,基本都是基于 Haskell Prelude 的。Github 上的 CoffeeScript 的 coffee-mate 与 lazy.coffee,C++ 基于 boost 的 prelude_CPP 都或多或少受了 Haskell 的 API 设计的影响,你可以在 Github 上找到很多这样模仿 Haskell Prelude 的项目。

InfoQ:您感觉 Haskell 主要适合哪类项目?您在工作中使用多吗?

张淞:我并没有什么特别大的项目经验,只是在学校里做过几个玩具级别的编译器与解释器,另外还有一些其他小玩具,不能拿出见人的。但我能比较确定的是,用 Haskell 来编写其他语言的编译器与解释器肯定再合适不过了,整套流程我也比较清楚。恐怕最著名的例子可能就是唐凤的 Perl 6 实现—— Pugs 了,还有由 Ulf Norell 在博士期间用 Haskell 实现的依赖类型的编程语言—— Agda ,另外还有 Haskell 广泛使用的编译器 GHC ,从 92 年到现在已经 20 多年了,还是有非常好的可维护性并且在快速进化着,有很多教授与博士在这个平台上做研究,每次更新都有很多新的特性加入,一件事物有这种进化的能力其实是很可怕的,无论它刚问世的时候有什么缺陷。其实就我的所见所闻,Haskell 从前端到高性能服务器、再到嵌入式开发、自动交易系统都有比较成功能例子,所以 Haskell 比较适合做什么更多的是由人来决定的。

我在工作中直接使用 Haskell 的机会并不多,但是我会使用 Haskell 做一些原型设计与网络接口测试。主要用的还是 Haskell 中的一些思想,比如代数类型、尽量消除变量的共享、尽可能多地使用纯函数等等,此外如果要在动态类型与静态类型语言中做选择,我会主观地倾向于后者。

InfoQ:在实际的业务开发中,选择编程语言会考虑哪些因素?

张淞:我工程经验并不是很多,主要是考虑要解决的问题与团队吧。最近解决的问题比较特殊,所以老大决定用了 Clojure,因为需要用到一个很重要的库,只有 Clojure 的实现比较好,另外就是团队里的人多少都有一些函数式编程背景,所以最后决定使用了 Clojure。

InfoQ:在国外会有不少实际的项目会应用到 Haskell,比如近日 InfoQ 曾报道过 Facebook 如何使用 Haskell 处理垃圾邮件**。**就您所知,Haskell 在国内的应用情况如何?

张淞:我在 Haskell 的 QQ 群里得知有几个小的创业团队在用 Haskell 做前端开发还有游戏服务端开发,但是没有深入了解。在我看来,国内是没有什么使用函数式编程语言的氛围的。最近网易在招聘,看了很多份简历,基本没有见到有函数式编程语言背景的人,感觉主要的问题还是出在中国的高校,有函数式编程这门课的高校屈指可数,他们教的主要还是 C/C++、MFC 这些东西,懂的要么是一些感兴趣的学生,要么是一些好学的工程师,希望以后有空能以网易云课堂为平台进一步推广一下函数式编程。

InfoQ:如果实际应用比较少,您感觉 Haskell 能给我们实际编程带来哪些启发?

张淞:我在前面大约提了几点,一个是 Haskell 核心的 API 的设计逻辑十分清楚,所以被很多语言争相模仿。无论你用什么语言,在设计 API 的时候照着 Haskell 中 Functor、Applicative、Monad、Traversable、Foldable 这些类型类来实现你的 API,最后的逻辑条理都会非常清楚,基本不会看到眼花缭乱的设计模式满天飞,我在看其他语言的 API 的时候也会找它们在 Haskell 中的对应。在实践中很多事情是从零开始的,我一般是先会定义出全部我所需要的类型,然后把计算与程序运行的流程搞清楚,明确需要从哪些类型计算出哪些类型并把函数签名写下来,接下来开始实现他们,最后把它们组合起来得到最终完整的程序。

InfoQ:感谢接受我们的采访,期待您在 QCon 上的分享。

2015-08-20 22:575913
用户头像
臧秀涛 略懂技术的运营同学。

发布了 300 篇内容, 共 136.5 次阅读, 收获喜欢 35 次。

关注

评论

发布
暂无评论
发现更多内容

大数据ELK(十):使用VSCode操作猎聘网职位搜索案例

Lansonli

ELK 10月月更

戏说系统安全(50/100)

hackstoic

系统安全

工赋开发者社区 | 某大型电子装备总装数字化工厂MES/MOM系统实施

工赋开发者社区

【牛客刷题-算法】2-算法入门-栈的压入、弹出序列

清风莫追

算法 10月月更

​Java进阶(三十八)快速排序

No Silver Bullet

Java 快速排序 10月月更

开发者有话说|程序猿工作多年之后的感悟

慕枫技术笔记

个人成长

简述构建微服务架构的四大挑战

穿过生命散发芬芳

微服务 10月月更

MyBatis学习笔记之JDBC

薛定谔的猫

mybatis JDBC 10月月更

数组操作の旋转二维数组

掘金安东尼

算法 10月月更

如何打通 SAP Cloud for Customer 系统和微信公众号的双向消息通信功能

汪子熙

node.js 微信 SAP 微信平台 10月月更

计算机网络——以太网交换机学习和转发帧

StackOverflow

编程 计算机网络 10月月更

Python基础(七) | 文件、异常以及模块详解

timerring

异常 模块 10月月更

计算机网络——集线器与交换机的区别

StackOverflow

编程 计算机网络 10月月更

工赋开发者社区 | 当PLC与见“IT”:MES/MOM标准之ISA-95基础内容介绍

工赋开发者社区

Python基础(六) | 面向对象类定义及特性详解

timerring

实例 10月月更

用任意类型编写代码——一文带你了解泛型编程

宇宙之一粟

Java 泛型编程 10月月更

Docker下,五分钟极速体验机器学习

程序员欣宸

Docker 10月月更

​Java进阶(三十九)Java集合类的排序,查找,替换操作

No Silver Bullet

Java 排序 查找 10月月更 替换

你是如何使用React高阶组件的?

beifeng1996

React

乐观锁和悲观锁

潜水员

并发

JavaScript中this指向哪儿?如何确定this?-前端面试进阶

loveX001

JavaScript

【牛客刷题-算法】NC4 判断链表中是否有环

清风莫追

算法 10月月更

【LeetCode】在LR字符串中交换相邻字符Java题解

Albert

LeetCode 10月月更

面试官:高并发场景下,你们是怎么保证数据的一致性的?

一灯架构

Java MySQL 10月月更

16个分论坛出品标准大揭秘,期待你的申请!

开源社

ESP32-C3 学习测试 蓝牙 篇(五、添加 characteristic)

矜辰所致

蓝牙 ESP32-C3 10月月更

Collections-Arraylist源码解读(一)

知识浅谈

ArrayList 10月月更

这些js原型及原型链面试题你能做对几道

loveX001

JavaScript

COSCon'22主论坛来袭 开源站在十字路口

开源社

Web3.0杂谈-#004(51/100)

hackstoic

NFT Web3.0

【牛客刷题-算法】3-第一篇-斐波拉契数列-C实现

清风莫追

递归 数据结构与算法、 10月月更

专访《Haskell函数式编程入门》作者张淞:浅谈Haskell的优点与启发_后端_臧秀涛_InfoQ精选文章