Haskell

Paul Hudak谈Haskell

摘自InfoQ中国受访人 Paul Hudak 采访人 Sadek Drobi

个人简介
                                    
Paul Hudak是耶鲁大学计算机系的教授,Haskell编程语言的主要设计者之一。他热爱艺术,开发了用于计算机音乐的Haskore函数语言。他最近在耶鲁助创立了计算与艺术专业。                                            
                        
关于会议                        
QCon全球企业开发大会(QCon Enterprise Software DevelopmentConference)是由C4Media媒体集团InfoQ网站主办的全球顶级技术盛会,每年在伦敦、旧金山、北京、东京召开。自2007年3月份在伦敦召开首次举办以来,已经有包括金融、电信、互联网、航空航天等领域的近万名架构师、项目经理、团队领导者和高级开发人员参加过QCon大会。

我是Sadek Drobi,这里是旧金山的QCon,和我在一起的是Paul Hudak。Paul,何不介绍一下您自己以及您所从事的工作呢?
首先,感谢大会邀请我来到这里。EricMeijer邀请我来这里作一个采访,我认识Eric已经很多年了,差不多是从我们参与到函数式编程早期的黄金年代开始。我在耶鲁大学已经工作了26个年头了,一切都进行得非常顺利,我仍然在从事Haskell以及函数式编程方面的研究工作,在也是我来到这里的原因。
我阅读了您关于Haskell的著作,令我惊讶的是,直到全书的后面你才提到类型类与monads。您认为学习Haskell的步骤就是这样的吗?(译注:monads是一种函数式编程中的一种抽象数据类型,请参考:<ahref="http://en.wikipedia.org/wiki/Monad_(functional_programming)">百科全书monads</a>)
是的,这就是我这样安排的原因,我觉得这是教授这些概念的最佳方式。在后面才讲monads而不是在前面,是因为我发现大多数的读者都已经有一些命令式编程的经验,并且期望能看到一些命令式计算的概念。事实上,我在这本书的前面就介绍了这一概念,大概在第3章,全书共20章节,在那里我只是将它们称作动作(action)。那里提到的IO动作就是这样的概念,只要是熟悉命令式编程的读者,理解这一部分是不会有什么困难的。

我在前面章节所保留的是monad的正式定义,当然如果要了解它,就必须要了解什么是类型类,才能真正从最广泛的意义上理解它。在本书的前面章节中我甚至有意避免使用“monad”这一术语,因为它会让人感到害怕。在函数式编程的社区里流传着这样一个笑话,我们应该从一开始就叫它们“温暖绒球”(warmfuzzy things:让人友好而有感情的事物),而不是叫它们“monads”,也许这是对的,谁知道呢。

这是一方面,但说到类型类,事实上,我认为应该在正式介绍什么是类型类之前介绍在介绍类型类上下文的概念。换言之,如果你看到的函数的类型签名有上下文或者约束等,就能联想到这是一个类型类。这一概念的介绍实际上能够提前,放在介绍类型类的声明以及什么是实例声明等等之前。

我想这也许是个好主意,因为我了解到的人们(并不只来自我的书,也来自学习Haskell的人们)的抱怨之一就是当你得到类型错误时,程序会丢出错误而错误信息自然地指向类型类或者其他。如果你不理解那些错误信息的话,那你就很不幸了。如果我重写这本书的话,我也许会做出一些小小的调整。回到原始的问题上:是的,我这么做是有意为之。
                                    
我们逐渐看到Haskell对其它主流语言所带来的启发。比如我们看到Philip Wadler为Java设计的泛型,以及Eric Meijer在微软的.NET平台上所进行的大量工作。这是否可以看作是Haskell的成功呢?
我认为这是极大的成功。我认为衡量一个语言的成功并不仅仅是从语言本身被使用或者被接受等维度来衡量。Haskell本身对其它语言所产生的影响或者说对整个编程系统的影响是巨大的。在语言设计方面有很多这类的例子,包括最近平地而起的一些新语言,如Scala。另一方面是我经常听见人们说,实际上中午吃饭的时候,我还听到有人说:“我一直在使用Haskell编程;我并不是在日常的工作中使用它,但是我喜欢这门语言。我工作中可能没用到它,但我理解它并且欣赏它的思想,而且我发现它影响了我使用Java或者C#进行编程的方式”。这真是一件很酷的事情。

Haskell给我的感觉非常好。在我看来,特别是近几年来,我觉得说它是成功的是没有任何问题的。就算它此时此刻结束了自己的历史使命,它所产生的影响也已经证明了它自己。我并不是说我们会止步不前解甲归田了,而是说明它的成功。在我看来确实如此。                                            
                                    
您认为Haskell的目标是作为一门启发其它语言的研究用编程语言这一已实现的目标,或者它能真正用于主流的企业(开发),比如软件
它当然能用于主流开发,事实上它也一直主流开发中使用,并且赢得了越来越多的亲睐。我们最终有了能够更好的支持主流开发的各种库,各种实现以及相应的编程环境。这方面长时间以来都是一个障碍,但是像Simon PeytonJones以及他所领导的微软小组在这方面做了令人难以置信的工作,他们为在业界需要使用这一语言的人们创建了相应的工具。另外,我们过去也常常担心性能可能是个大问题,而现如今的编译器也已经变得越来越好了,所以发自内心的讲,我实在想不出不选择Haskell的理由。我们将看来越来越多的人使用它,谁知道呢?
                                    
能给我们进一步谈一谈高阶编程吗?
能不能多讲讲高阶编程?它是一种思维状态,是一种思考的方式,它认为任何事物都是头等公民。当你在某一层次上做某事时,你可以将它抽象到一个更高的层次上。一旦你领悟了这一思想,它就无处不在。如果我突然不能使用Haskell或者被迫去使用比如Java或者C#等语言——尽管这些语言已越来越多的在朝着函数式的方向努力——我将无比想念的不是类型或者延迟求值,但离开了高阶函数我就非常难熬。

它对于计算抽象而言是如此关键,并且它引领人们用一种极佳的方式思考问题和编写程序,因此我不知道人们离开了高阶函数会如何继续。我可以忍受失去一些其它特性,但高阶函数是不可缺失的。我们说“高阶编程”的时候,它同时也意味着一些别的事物。比如高阶类型等等,而如果你想知道更多的话,最近Haskell在类型系统与高阶编程方面着实走得比较远了。

我们直到最近才发现它所蕴含的强大力量。我认为故事才刚刚开始而已。高阶函数实际上非常直接,一旦你有了lambda算子,你就可以对任何事物加以抽象。而由于可判定性的问题和一些其它原因,类型系统相对而已就没有这么容易了。我想可能是由于我们的设计还没有臻于完善吧,目前仍有各种扩展和思潮在不断的发展当中。然而,当我们看待高阶类型些,它的能力就变得如此的明显,可以很肯定的说这就是我们需要的东西而且我们将不断的发展下去,谁知道发展到头会是什么样子呢?
                                    
当我们谈到函数与高阶函数时,我们同时也谈到函数式交互动画。您能为我们进一步解释一下吗?
动画,从图形学的角度上讲是我们所泛指的函数式反应性编程的一类实例。这一思想源于ConalElliot,是他将这一思想带入了Haskell,我们相互合作并开发了FRAN,它一个函数式反应性动画语言。在耶鲁大学,我们也在积极探索这一思想的其它应用,因为这其实是一个相当一般性的概念。而Conal一早就意识到了这一点,虽然他最初主要将其应用于动画领域。

我们将这一思想引入了机器人设计,现在又开始探索它在信号处理与声音合成方面的应用——我们已将其应用到了并行编程中。这是一个非常强大并且普遍的思想,其基本意思是,不把程序里面的变量想成值,而是想成静态的,因此一个给定的变量在一次迭代、函数的一次调用,或者递归中执行一次时仍保持原值。这样你完全可以将它想像成随着时间的每一次极微小的变化时都是保持一致的,这就是真正的持续值。

这就是我们想要展现的抽象。当然,这并不是我们的底层实现方式,但只要你这么做,各方面的事情就都会套用到这一范型,再给你一个动画方面的简单例子。一个图像通常被当作是一个静态的值,但随时间变化的图像却是一个动画。有很多这样的例子,而我们最近所使用的是图形化用户界面的例子,关注在音乐或者是进行声音合成的计算机音乐应用这一领域。典型的是,我们通常用把手和滑棒来代表控制音量的值。

这只是些信号——我们习惯这么称呼——或者说行为中的一种。它是一个随时间变化的量,使用这一框架可以优雅的捕捉到它。当你提起任何事物,或执行任何操作,不管是加法这样的算术运算,还是积分或微分这样的有状态操作,你得到的都是一种完全不同的编程风格。当整个世界不再永远是连续的时候,真正的挑战来自于你如何将这一点与离散时间所发生的事件这一事实集成起来。比如,如何将点击鼠标或者敲击键盘集成起来?

要做到这一点,最终是使用了一种非常优雅的方式,引入了离散事件这一概念,但却是把这些离散事件看作是事件流——就像我们有连续变化的值一样,我们现在有连续的潜在事件流。可以开发出允许你在离散与连续之间进行仲裁的“话务员”,我们称它为交换器,它在基于事件的基础上会调用连续的行为来作出改变。它工作的如此之好,创造出一种高阶的编程方式。

要用Haskell实现它将完全依赖于高阶函数等元素,但不仅仅是实现它,而是将它概念化。这是一种正确的思考方式,而且这是一种很好的做法。                                            
                                    
您的意思是只要我们知道一个事件流是用户事件,或者是其它的企业相关的GUI事件,它们可以被应用到Web应用上,对吗?
是的,我是这么认为的。最近我在这一领域作了许多工作。虽然在这一问题上还谈不上能以专家的身份来作什么评论,但同样还是我们之前所探讨的那些概念,包括希望web应用是无状态的这一事实,都能很好的适合这一模型,甚至包括对web应用的基于连续的理解这一思想,自然也是符合于这一模型的。

正如我所说,人们还在不断开发各种各样这样的概念。我认为这一领域非常有意义的一点在于,它不仅限于web应用,而适合普遍的因特网事务。当产生重叠时,就会产生特别的面向时间的事件序列,可能会碰上并发事件,可能会出现超时的情况或者某些事件使得你不得不停止其它正在进行的工作。这就直接引出了在Haskell社区里正讨论的如火如荼的另一个重要概念,那就是并发。

令人兴奋的意外收获是,当你处理好所有与实现高阶函数等等相关的问题之后,一旦这些机制都全部就位了,要加入并发就是一件再容易不过的事情了。因为要用高阶函数处理延迟求值,你必须要有一种封装计算的方式,挂起,延迟——不管你想怎么命名——,或者说闭包(closure)。一旦有了这些机制,并发不过就是这种思想的另一种形式而已了。Simon PeytonJones和他的小组在这方面作出了杰出的工作,并为Haskell提供了这样的线程库,大大简化了这一类工作。
                                    
函数式抽象的能力与OOP,面向对象相比,差别在哪里呢?
这两者截然不同。OOP所带来的很多东西在函数式的世界实际上是不怎么存在的。或许Haskell的类型系统有点面向对象里的类的意味这一点会让人觉得有点疑惑,但它们没有相关的状态与之联系。我觉得OOP语言的一个问题是——这只是我个人的观点——他们搞混了几个不同类别的问题,而且我觉得完美的OOP语言还没有被设计出来。

关于状态,封装,以及对象与继承等问题都太容易造成人们的困惑,因此你会看到对象在Java这样的语言中以不同的方式被使用。使用它们的思想在概念上有着真正的不同这一事实也许正说明了它有什么不对劲的地方。再次声明,这只是我个人的观点而已,而且我认为学习面向对象编程是困难的。实际上,我在耶鲁教了够多的Java和C#,因此我才知道它的不易之处以及学生容易产生困惑的地方。

教授这些语言的最近一些趋势是,至少直到学期的结尾以前,都不去强调这些语言面向对象的方面,这样学生才能首先掌握计算的基本思想。显然,面向对象编程有不少优秀的思想,我同样也不想贬低它们。为了达到同样的效果,比如继承,在函数式语言中必须要花费更多的功夫才行。你可以用高阶函数来模拟它,我曾经这么做过,比如我在计算机音乐库HasKore里就这么做过。

也许在面向对象的语言中能更容易进行表达,但这并不意味着我已经准备好转入到面向对象的语言中,不过可以肯定的是,它也有其精华的部分。                                            
                                    
现在,我们越来越多的看到monads的应用。我的意思是,当monads初来乍到的时候,一些人认为它是一个奇怪的概念,而现在,仅仅过了几个年头,我们已经在LINQ或者其它的主流语言里面看到了它的应用。您认为monads是可以应用在任何地方的新的API抽象吗?
当然,它们可以被用于任何适合的地方。试着很好的理解monads以去理解哪些是适合/不适合使用它们的地方是一个挑战,而且这么做可以教给人们相关的技术并让他们理解monad到底是什么。遗憾的是,许多人都把monads当成或者是基本跟所谓的“状态monad”——一种特殊的monad——等同起来,因为它最主要是跟IO和命令运算联系在一起,但其实“状态monad”不过是monad的一种而已。

真正要很好地处理到底monad的真正抽象意义何在,我觉得是一个挑战。意思是,我确实认为monads应当被理解并且可以对帮助人们理解他们的软件产生影响,但这里还存在超越了monads的一些事。所以,真正重要的事情是要理解,monad在某种意义上讲是对一种抽象计算的捕获,而这种计算可以非常正式的用monadic的运算符和monadic规则进行描述,但这并不是唯一的计算类型。

举例来说,最近在一些特定背景下变得越来越流行的东西就是所谓的arrows,它是来自JohnHughes的思想。arrows可以被看作是一般化的monads。你可以将任何monad编码成arrows,但反过来则不行。目前Haskell实际已经在monads语法的基础上,又加入了arrows的语法。所以,这样一来,我们又得了另一种抽象计算。我们需要去理解它,我们需要去理解什么时候适合使用monad,什么时候适合使用arrow。

当然,自然而然,像“还有其它别的东西吗?”这样的问题就会接踵而来。是的,确实有。适用函子(Applicativefunctor)就是另一个例子,但它却是朝另一个方向在发展——它甚至有着更加简单的概念,比monads还要简单——因此更加适合于特定的背景。可能会出现这种情况,程序员可能会想到:“哇,我应该使用monad!”而实际上,使用一个适用函子就已经足够了。而且适用函子有着更为简单的代数规则集合。因为它这些更简单的运算符,更易于使用的特点,使用得变得理所当然。杀鸡焉用牛刀呢?

与此同时,可能会出现这样的情况,一个应用应当需要一个arrow,却错误的强行使用了monad去迎合它,造成的结果要不是无法工作,就是不能够表达你想要的东西。要处理所有这些问题,函数式编程社区本身也仍然在整理细节。最近相关的论文层出不穷,这些思想都是有待他们去解决的。

话说回来,这不是说因为monads可能不再是当初让人害怕的词汇,主流就不为之激动了,他们可以看到在其它的环境里已经发生的很好的例子,他们也可以尝试在新的环境里运用它们,这非常棒。事情本该如此。我想说的是,需要更多这样的思想涌现。而这些东西最后是否都会加入到主流里呢?我说不好,但可以肯定的是对像我这样的研究编程语言的人来说,这些东西都是足以让人兴奋的。
                                    
我们知道您致力于和对非程序员一起开发嵌入式DSL,能给我们分享一下这方面的经验吗?
这方面我的经验也不能说非常丰富,但是今早我还谈到了这样的一个例子。实际上,我是和音乐家一起工作,比如,使用我们的计算机音乐软件库比如Haskore和HaskSound这样的DSL,他们爱不释手,至少当我在一边旁观并提供一些帮助的情况下确实如此。这可以说是非常积极的一种经验。

我不得不承认我在所有的与完全的新手一起工作的领域中最具挑战的一项,以机器人为例吧:如果你跟一个机器人专家交谈的话,你不会找到没有从事过编程的机器人专家。比如GregHager和他的研究小组(Greg现在在约翰霍普金斯,他曾经在耶鲁):他在耶鲁的时候,我们和他一起合作过一种叫FRAD的DSL,它使用我之前描述过的函数式反应性编程模型来控制机器人。

在那个时候,他所有的编程都是用C和C++完成的。在此之前他从未使用过Haskell,因此在这个叫做FRAD的嵌入DSL的环境中他是第一次使用Haskell。他也非常喜欢Haskell,不少他的学生也是,他们即使在离开耶鲁以后还继续着FRAD的工作。这并不是一拍即散的合作方式或是其他什么——相反他们真正发现了这是一种高效的编程方式。

诚恳的说,我认为我们应该积累更多这方面与非程序员的经验——当然,非函数式编程的程序员,并观察会有怎样的结果。就音乐这一背景来说,我现在所做的一项工作同时也算作一项挑战吧,就是写一本主题与编程无关的书,但我同时也认为这样的事情应当越多越好。也许我们可以在这个过程当中,也教授编程,但这本书的主要目的却是教授其它的主题。就我这个例子而言,我所说的就是计算机音乐。

实际上我是在将我先前的教材《Haskell School of Expression》在计算机音乐的背景下进行了重写,并且彻底地介绍了计算机音乐的思想。这样做意味着对于跟Haskell无关的事物有很多潜在的好处,但与此同时又完整地传授一门语言,不是以一种流于表面的方式,而是让他们真正的理解函数式编程的能力,因此一旦他们理解了Haskell或者理解了计算机音乐的思想,就能做出很酷的东西来。这并不非常事儿。如果投入更多的时间和精力的话,我们可以做得更好。我们也期盼着这些努力能有成效。
                                    
你从一开始就使用Haskell,如今历经岁月沉淀,你认为真正的收获是什么?你如何看待Haskell的今天?有没有什么你想要删除或添加的功能?接下来的时间里,有没有哪个受Haskell启发的语言会引起你的兴趣?
首先,我感觉Haskell非常好。它多年作为一种生僻的研究语言,而从未受到主流的过多关注,最近所收获的成功则令人愉快而满意的惊喜。如果不是它最近所获得的这种关注,也不会有今天我在这里坐着接受采访了。就算退一步而言,它并没有获得这种程度的关注,我也没能在这里接受采访,我想我也不会因此而感到不安,因为我钟情于这一门语言而且一直都在使用它,它仍然是我最爱的语言——如果我想要编什么程序的话,我的抉择就是它。

正如我们之前谈到的那样,我对于它能影响这么多其它的语言感到非常欣慰,但除此以外也有很多非常酷的语言和功能强大的框架。模仿别人的工作就是最好的恭维,确实人们都在从Haskell吸收精华,这非常棒,但也没什么理由让我们不能从Ruby onRails或者任何其它的新技术那里学习经验并影响我们的社区。我认为Scala就是一门非常棒的语言。

我们会看到越来越多这样的事物涌现出来,但现在令人高兴的是,人们都在互相借鉴对方的长处,而且有很多相辅相成的开发正在进行中。整个编程语言的范式非常有趣。我曾经从DARPA得到过很多赞助,而DARPA曾经有一段时间设计过Ada编程语言。Ada的目的就是设计一个终结版的万能编程语言。试图达到Ada之后,再无语言。这是不现实的。

之后DARPA又有一个项目是要标准化一门原型语言。同样的错误又是,“让我们团结起来设计一门语言并让它成为最后的乐章。我们一定行!”这一次又是失败。在我26年的经历里我许多次听到DARPA或者赞助单位说:“编程语言研究已死”或者“编译器研究已死,我们已到了尽头”。非也!它仍然在不断进步,并且正变得越来越让人兴奋。我认为在许多不同的方向上如今都有令人欣喜的进展,并不仅仅是Haskell,这可真是棒极了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值