永不消逝的浪漫:Programming Languages and Haskell

MIT大牛林达华

最近两周工作轻松了一些,于是闲不住,花了不少时间钻研一门新的程序设计语言——Haskell。其实,这门语言在上世纪八十年代就产生了,到现在也算有些年纪了吧,只是对我来说,是第一次学习它。

从初中学习Basic,到现在,学过的语言不记得有多少了,在相当一段时间内用来干serious的事情的应该也有八九种了。我这个人在对待计算机语言方面属于喜新不厌旧(在现实生活中,我还是很专一滴~~~

先说说对几个老相好的印象吧:

不一样的她,不一样的魅力

Basic / Pascal:初中时代的初恋情人,历史有点久远。。。只是没事的时候时不时在脑海翻出和TurboPascal的蓝底白字共同度过的good old days来怀旧一把。

C / C++:从高中相识到现在,一直不离不弃,也是学习得最全面的一种语言,从Helloworld,到Boost/Loki里面的各种被称奇技淫巧Template technique都玩了个遍。OOP + Template的表达力,High performance,和对机器的直接控制能力的结合,成就了它在长达几十年历久不衰的生命力。在性能关键的地方,它是不二的选择。但是,选择它往往也意味选择承担它给你带来的痛苦:一版代码干不了几件正事,层不不穷的指针错误和内存溢出,编译复杂的模板类时几英里长的诡异错误。

软件工程的教科书说良好的设计可以帮助我们在很大程度上避免这些错误,这话一点不假。但是,这里面的根本问题是:我们花了太多的精力在这些地方——而它们并不是我们真正要做的事情。我本来想开车去玩的,但是,我却花了更多的时间去修路——为了让车子更安全顺畅。

C#:这门语言很年轻,我看着它从1.0成长到4.0。和它呆在一起很舒服,就像和一位充满青春活力而又善解人意的女孩在海边漫步。她有着各种方便的语言特性,和一个全面实用的标准库,包括一个特别好用的标准GUI库(在这点上,别的语言无出其右)。她在一个富裕的家庭(Microsoft)长大,而她的父母总是不遗余力的给她佩戴各种首饰,从而让全世界的帅哥回头——我不知道她吸引了多少人,但是她至少吸引了我。

说起C#,不得不提到一位比她出道早,和她长得很像的姐姐——Java。和Java在一起,给我的感觉是,她是大家闺秀,成熟优雅,但是外形略显臃肿。即使是一行的函数,即使没有名字(Anonymousfunction),也得写个interface/class来给它包装一番。而且大小姐架子忒大,一个十行不到的class,也得要自己的一个套房(单独文件),就不能和别人share一下?

C++/C#/Java都是重量级的语言,平时要处理个把文件,还真不想劳它们大驾,特累。

对这种事情,我需要一个秘书。我最初雇的是Perl 5.xx (据说Perl 6很有进步,但是不太了解),但是它的风格不太对我的胃口,很快我就另觅新人了。然后,我找到了Ruby。这位秘书讨好老板的玩意还真不少(很多syntax sugar——当然很多是从别人那学来的。刚开始的时候,还真是挺喜欢她的。可是,我这人有一毛病,记性不太好,花里胡哨的东西太多,老记不住。过两天不用,又忘了。最后,我选择了Python,这是个特别爱干净(对代码缩进都有严格要求,否则干脆不伺候)而又很干练的人。没什么很花的东西,但是用起来很顺手。直到现在,我都用它来写普通script

革命伴侣

MATLAB:我到目前为止,本职工作还是做学术,而不是工程,因此,用得最多的还是matlab。虽然感恩节过去了,还是要对她表示我最衷心的感谢,没有你,就没有我的今天~~”周围的人吐了一地。表白完了,还是得说说她的好处。她有着一种特别迷人的气质——不知道迷不迷你,起码迷我——和代数的紧密结合。

计算机发展到今天,曾经出现的语言不知凡几,一种流行的看法是语言背后的思想都是一致的,不同的语言只是换个语法换个库。对于很多语言,这是正确的。但是,对于一种有独特生命的语言,却往往传承着独特的思想,独特的思维哲学。MATLAB正是这样的一种语言。在处理重复操作方面,C/C++之类的传统语言倾向于使用循环,而MATLAB更强调向量化(Vectorization),把很多运算转化为代数结构,比如矩阵的整体操作。这在思维上,就是需要一个把问题代数化的过程。在不少时候,这是一种挑战,也是一种对数学思维的享受。

从大一开始就使用matlab,到现在也有一些年月了。长期的斗争实践中我和她相濡以沫,也培养了深厚的革命情谊——就在我已经默默地打算和这位气质不凡的她成为革命伴侣的时候,我遇到了FunctionalProgramming

走进 Functional Programming 的家族

Functional Programming (函数式编程,FP),是一个大家族。这个家族的历史绝不比主流语言的历史短,起源于上世纪50年代。这个家族的第一个成员,就是大名鼎鼎的Lisp,由图灵奖得主John McCarthy1958年在MIT最早提出(这位老先生后来去了Stanford)。Lisp最早是个很小的语言,基于它发展出很多分支(方言),最有影响的是CommonLispScheme,前者博大,多用于实际应用;后者精巧,多用于教学和学术研究。 MITSussman教授所写的SICP——被誉为学习ProgrammingBible,同时也是MIT CS的经典基础课程6.001的教材——就是基于Scheme

在来MIT之前有一段空闲时间,我慕名学习了Scheme。这门语言的语法核心非常简单,整个语言的标准全文大约50页,但是却非常灵活,有着令人赞叹的表达能力。这是一位很单纯的小姑娘,她不会让你敬畏,但是却能激发你无穷的想象力。这是一个超越时代的语言,诞生于40年前,却支持着很多后生晚辈很久之后才实现甚至现在还没实现的东西:First-classfunction, Closure, Tail recursion optimization, Lazy evaluation, Pattern-basedSyntax-rule 还有Continuation。但是,这小姑娘太小巧玲珑了,虽然欣赏她却不能用她干多少实际的事情——对实际应用缺乏足够的支持。

Scheme的引导下,我进入了FunctionalProgramming的家庭,在这个过程中,我开始对它的另外一个成员发生了兴趣,Haskell——她可能是后面几篇文章的主角,在这里先让她出来露个面。过去的两个星期里,我和她频繁约会,亲密接触,欲罢不能。我知道,我又遇到一个让我动心的情人了。

从地球到火星和新的情人亲密接触

如果说,用MATLAB让你在一定程度上改变思维,那么,Haskell就是对世界观的彻底冲击,在这里,我所体验到的是一个根本不同的世界。前面的无论是初恋,秘书,伴侣,还是情人,都是地球人;Haskell似乎是来自火星的。

Haskell的世界里(准确的说,在Purefunctional programming的世界里),没有赋值,没有循环,甚至没有顺序执行的语句(不过,可以如果需要的话,可以通过某种方式来模拟出类似的效果),在这里,有一些完全不一样的概念:Purefunction(Referential Transparency), Partial Application and Currying, Functor,  Folding,  Monad,  Arrow

在传统的语言里,数据是主要的操作对象,函数一般只是把它apply到输入数据中获取输出。在FP里面,对函数的操作起着核心的作用。在这种语言的代码里,会密集地看到对函数的各种传递,合并,改装,变形。比如下面的情景是很常见的:一个函数作为参数送入一个高阶函数里面,产生出一个新的高阶函数,然后可以用它对别的函数进行变形。。。。。。可能有点晕吧,晕几次后就会发现这个东西写出来的代码veryvery elegant。你会发现,原来分别要用几十行代码实现的很多看上去千差万别的东西,这这里可以抽象成几行短短的代码统一实现。如果说,传统的语言,一个函数所描述的是某种具体的计算过程;那么,Haskell的每个高阶函数所描述的就是各种表面不同但是蕴含着相似逻辑结构的计算过程的抽象。

话说回来,Haskell能做的东西,不是说别的语言,比如MATLAB/C++之类的不能做。理论上说,实现了Lambda functionClosure的语言,比如C#/MATLAB/Python,都可以肩负起对函数进行合并和改造的任务;而C++template functor也可以模拟类似的效果。但是,这些语言不是设计出来做这种事情的,让它们去做的话语法上会比较繁琐,思维上也不符合这些语言的主流逻辑,所以很少有人这么写东西——其实,我以前时不时也会这么写,算是一点FP思想的萌芽吧。而Haskell在语言核心上对这些东西提供了直接和强大的支持,在这个世界里,你不这样写,反而成了异类了。

因为之前多多少少运用了一些functional的思想来写程序,我刚接触Haskell的时候并不觉得多不适应,反而,因为它让我很舒服的做一些我以前做起来很繁琐的东西,我很快就觉得这个新的情人特别亲切。可是,跟着她从地球去火星的路,可不是这么好走的,走着走着就开始缺氧了——当我第一次接触Monad这个概念,尤其是StateMonad的时候,有好一段时间始终不能appreciate。看了好几个tutorial之后,终于开窍了——一觉醒来,天空还是那么晴朗。之后,再看Monad TransformerArrow的时候就心情舒畅了——庆祝自己算是初步融入了火星生活。

值得一说的是,Haskell是我见到的学术色彩非常浓厚的语言,学别的语言,看的是这门语言的教科书。Haskell也有教科书,讲的很多只是初级的东西,看到后面的一些概念,很多都是90年代后才在学术界propose出来的,要学习它们,看的不是书,而是paper。一门要通过academic paper学习的语言,本身就有着不一样的魅力。

我终究还是要在地球上生活的——Haskell在学术上是非常创新的语言,但是,未必特别适合实用——去火星的目的,不是为了定居,而是为了取经。很小很小的时候,大人们告诉我们,站得高看得远,那么站在火星看地球呢?。。。。。。

(也许,在后面的一些文章里,会更详细地分享这个旅程)

你可能感兴趣的:(奇文共赏)