关于Haskell
翻译:funnywei 原文:http://www./aboutHaskell.html Haskell是一种程序语言。特别的,它是多态类型,懒惰的,纯的函数式语言,与大多数其它编程语言 不同。 该语言被命名为Haskell Brooks Curry。它是以数学逻辑为基础的函数式语言,基于 lambda演算。 为什么使用Haskell? 写一个能工作的大型的软件系统是很困难的而且很昂贵的。维护这个系统甚至更加困难和昂贵。函数 式程序语言,例如Haskell,能够使之变得简单而且廉价。例如,用Haskell写一个小的关系DBMS的一 个新用户会说: 喔!只是考虑类型间的转换,我基本写好了我的程序,且没有测试。我写了测试和例子代码并且基本 上代码中没有实现错误。编译/类型系统是真的很好的阻止你犯下编码错误!我一生中从没有有这样一 大段代码,第一次尝试就能工作了。我印象深刻。 Haskell,一个纯的函数式程序语言,提供你: 充分提高了程序员的生产力(爱立信Ericsson在一组电话软件测试中提高9到25个因子)。 简单,干净,可维护代码 更少的错误,高可靠性 更小的语义鸿沟,在编程者和语言之间 缩短订货交互时间 Haskell是一种广谱语言,适合各种应用。他尤其适合需要高度可修改和维护的程序。大多数软件产品 的生命期主要花费在规范,设计和维护而不是编程。函数式语言能很好的写能够真正执行(也可以测 试和调试)的规范,该规范也就是最终程序的第一个原型。 函数式程序也相应的容易维护,因为代码更短,更干净,严格控制了副作用,消除了大量的不可预见 的交互。 什么是函数式程序语言? C, Java, Pascal, Ada, 等等,都是命令式语言。他们在某种程度上是由命令序列构成的,严格的按 照顺序来执行。haskell是函数式语言。函数式程序是一个单独的表达式,通过推算表达式来执行。任 何使用过电子制表的人都有函数式语言的经历。在电子制表中,你可以根据其它单元的值来指定每个 单元的值。焦点是什么需要计算,而不是如何计算。例如: 我们不需要指定单元应该按照什么顺序来计算-相反我们认为电子表格将会按照单元间的依赖关系来计 算。我们不是说告诉电子制表如何分配内存--而是,我们期望它提交给我们单元的无限平面,并且仅仅 分配内存给实际使用的。 对于大多数部分,我们指定单元的值是通过表达式(这些部分是可以按照任意顺序估算),而不是通过 命令序列来计算值的。 电子制表不制定重算顺序的一个有趣的结果式,指派的概念不是很有用。宗旨,如果你不确切知道什么 时候一个指派要发生,你不能很好的用它!这个与常见的类似C语言的程序非常强烈的对比,这个包含 了一个仔细说明的制定或者Java中方法调用顺序对于程序的意义很重要 焦点在高级的what而不是低级的how式函数式语言的最显著区别的特性。 另外的众所周知的接近函数式语言的是标准的数据库查询语言SQL。一个SQL查询是包含了投影,选择, 连接等的表达式。查询表达了应该计算什么样的关系,却没有说该如何去计算。事实上,查询可以按照 任意方便的顺序来求值。SQL实现经常执行昂贵的查询优化,指出如何求值表达式式最优顺序。 函数式程序语言有什么好? 电子制表和SQL都是相当专用的语言。函数式语言的思想是,把他们放到一个通用目的的程序语言的领域 里。为了知道一个函数式程序是什么样的,看看下面的快速排序程序。他们都是使用标准的叫做快速排序 的方法对数字进行升序排序。第一个程序是用Haskell写的,第二个是用C程序写的。 Haskell写的Quicksort qsort [] = [] qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x where elts_lt_x = [y | y <- xs, y < x] elts_greq_x = [y | y <- xs, y >= x] C写的Quicksort qsort( a, lo, hi ) int a[], hi, lo; { int h, l, p, t; if (lo < hi) { l = lo; h = hi; p = a[hi]; do { while ((l < h) && (a[l] <= p)) l = l+1; while ((h > l) && (a[h] >= p)) h = h-1; if (l < h) { t = a[l]; a[l] = a[h]; a[h] = t; } } while (l < h); t = a[l]; a[l] = a[hi]; a[hi] = t; qsort( a, lo, l-1 ); qsort( a, l+1, hi ); } } 我们来看看Haskell和函数式程序语言的优点。更多的关于Haskell和函数式程序的细节实例可以看 The Computer Journal, Vol. 32, No.2,1989,pp.98 - 107杂志John Hughes写的Why Functional Programming Matters。也可以看:David A. Turner (ed.): Research Topics in Functional Programming, Addison-Wesley, 1990, pp. 17 - 42. Sebastian Sylvan受到上面论文鼓舞的一个不是很正式的文章Why Does Haskell Matter 1. 简洁 函数式程序比他们对应的命令式语言精简。快速排序是一个相当极端的例子,但是在一般的函数程序 语言会更短(2/10倍) 2. 易于理解 函数式程序更易于理解。在没有任何关于Haskell或者快速排序的了解得情况下,你应当可以理解这个 程序。而C语言就不能这么说了。他需要你花一定时间来理解,甚至当你理解的时候,你也很容易犯点 小错并且得到一个不正确的程序。It takes quite a while to understand, and 这儿是关于Haskell 快速排序的细节的解释: qsort [] = [] qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x where elts_lt_x = [y | y <- xs, y < x] elts_greq_x = [y | y <- xs, y >= x] 第一行读做:排序一个空列表的结果是一个空表 第二行读做:排序一个列表,他的第一个元素是x并且剩下的部分叫做xs,排序xs中所有比x小的元素 (他们叫做elts_lt_x),排序xs中所有比x大的(他们叫做elts_greq_x),并且连接(++)结果,x夹 在中间。 elts_lt_x的定义,理解在下面给出,读作: elts_lt_x是所有y的列表,y是从xs列表里抽取的,y比x小。 elts_qreq_x类似。语法是标准的数学集合概念的回顾,|发音为定义为,<-发音为抽取。 当问到非空列表的排序,qsort调用自身排序elts_lt_x和elts_greq_x。因为两个列表都比给定排序的要 小。所以分割和排序过程最终简化为排序一个空表,qsort的第一行作的相当琐细。 3. 没有 core dumps 大多数函数式语言,尤其是Haskell,是强类型的,去掉了编译时大量的容易犯的错误。尤其,强类型意 味着没有core dump。这就简单了,不需要将一个整型作为指针或者空指针。 4. 代码重用 当然,强类型对于许多命令式语言也是可用的,例如Ada或者Pascal。然而,Haskell的类型系统更加严 格限制,也就是说,因为使用了多态机制。例如,qsort程序,将不仅可以排序整型,也可以排序浮点 数字和字符,还有对表进行排序;真的,他可以排序任何东西,只要是可以进行大于或者大于的比较操 作。对比而言,C版本就限制对整型数组的操作。多态 加强了重用性。 5. Strong glue 不严格的函数式程序语言有其他的优点: 他们仅仅在程序需要得到答案的时候求值--这叫做懒惰求值。这个特性非常类似Unix的管道。例如, Unix命令 grep printf Foo.c | wc 计算文件Foo.c中的包含了printf字符串的行数。命令"grep printf Foo.c" 产生了所有包含字符串 printf的行,这里wc命令计数。管道"|"从第一个命令得到输出。The pipe并且传给第二个。这两个命 令一起执行,所以第一个的输出或多或少理解被第二个命令使用。这样,不需要产生大量的中间文件, 你可以考虑wc需要grep的行数。如果第二个命令仅仅需要第一个部分的输入,那么第一个命令的执行也 许没有必要完全做,例如 grep printf Foo.c | head 5 之需要打印包含"printf"的前5行。考虑到有些执行需要遗弃这个事实,我们没有必要修改grep命令。 非严格限制的语言提供了需求驱动(demand-driven)的求值(funnywei注:目前过程式语言应该说 是data-driven,这也就是为什么在挖据漏洞过程中数据流分析的重要性,关键找出data-dependency 。)。求值出来的数据结构足够传递答案的信息,甚至他们中的部分就不需要求值。就像Unix命令中的 例子,这提供了强大的"glue",通过这个将程序合在一起。这个的意思就是重用程序或者程序片断是很 有可能的,这比命令式的设置能做更多的事情。懒惰求值允许我们写更多模块化的程序。 6. 强大的抽象 通常的,函数式程序语言提供了强大的新的方法来封装抽象。抽象允许你定义一个内部工作被隐藏起来 的对象;C过程,例如,是一种抽象。抽象对于构建模块化,可维护的程序等等很关键,"什么样的抽象 机制它提供?”函数式语言中一个强大可用的抽象机制是高阶函数。Haskell中,函数是一个高级公民: 它可以自由的传递给其他函数,作为函数的结果返回,存储在数据结构中,等等。明智的使用高阶函数 可以充分的提高许多程序的结构和模块化。 7. 内置的内存管理 许多程序需要从堆里面分配动态内存。在C里面通过调用malloc,在分配后紧接着初始化存储。当存储 空间不再需要时,程序员负责释放到未使用的池,声名狼藉的“摇摆指针”错误。此外,malloc相当费 事,所以程序员经常分配一个单独的大的存储chunk,然后手工从里面再分配。每个函数式程序语言解 除了程序员存储管理的负担。存储分配和初始化式隐式的,通过垃圾回收器来自动恢复。存储分配和垃 圾回收的技术现在已经很成熟了,代价非常小。 什么时候 C 更好 C的快速排序使用了一个Hoare发明的非常有创造性的技巧,它可以排序数组到恰当的位置;也就是说, 没有使用任何额外的存储。结果,它运行很快,只需要很小的内存。对比而言,Haskell程序在幕后分 配许多额外的内存,而且比C程序要运行的慢。在效果上来说,C的快速排序有许多创造性的小技巧,用 算法复杂度来交换运行时的存储耗费。 在应用程序中,对性能要求非常高,不惜代价,或者当目标用低级的算法来描述细节的时候,使用命令 式语言例如C可能是比haskel更好的选择,这是因为它提供了更多的计算该如何执行的方法的紧密的控 制。 函数式 vs 命令式 但只有少数程序需要不惜代价的获得性能!总之,我们都不再去写汇编语言,或许除了关键的内部循环。 拥有更多支持的编程模型的好处(如意树木命名的,局部变量而不是固定树木的寄存器,例如)远不会 超过适度的运行时开销。类似的,我们欣然的接受虚拟内存页面系统的开销,以此交换更多支持的具备 无限地址空间的编程模式。清晰的内存的使用的日子结束了。 函数式语言朝着高级编程模型取得了大的进步。程序更易于设计,编写和维护,但语言提供给编程人员 更少的对于机器的控制。对于大多数程序结果是完全可以接受的。 什么是Haskell? Haskell是现代的,标准的,非限制的,纯的函数式程序语言。以上提供了所有重要的特性,包括多态 类型,懒惰求值和高阶函数。它也包含了创新的类型系统,支持重载的体系形态和模块系统。 他专门设计为处理广泛的应用。从数字到符号。至此,Haskell有一个表达的语法,并且有丰富的内置 的数据类型,包括任意精度的整型和有理数,和更多的常规的整数,浮点和布尔类型。 有大量的实现可以用。都是免费的。初次使用的用户可能想用Hugs开始,一个小的可以移植的Haskell 解释器。 有谁使用了函数式程序语言? 略 其他经常问的问题 函数式编程很难学嘛? 函数式编程需要在观念上变化,一些程序员发现很难。但爱立信的训练程序员在Erlang实践,大多人发 现转换很容易--提供他们训练要严肃而不是假设他们当场就学会了。 函数式程序语言是不是非常慢? 通常是的,但编译器已经改进了。Haskell程序已经运行的足够快,除了对性能需求的应用程序。 我已经有了一个大的C或者C++应用程序;我可以在没有重写的情况下从函数式编程中受益嘛? HaskellDirect是一个基于IDL的工具,允许Haskell程序可以和软件组建一起工作。低层的C/C++接口 可以可以使用Green Card产生,允许在Haskell和C之间紧密整合。这些工具已经用于创建大量的成功的混合 的语言系统。 Haskell支持什么样的库? 已为Haskell开发了许多软件库。看Haskell库的列表来得到什么可用的列表。 有那些其他的Haskell的软件工具? Glasgow Haskell帮助你找到你的程序的那个部分耗费了最多的时间和空间 Chalmers Haskell是空间档案工具,类似并行的模拟器你可以并行运行你的程序。Hugs也有一些相应的 工具 我可以得到支持或者帮助? 略 |
|