# 对Haskell这门语言的基本认识

Haskell语言的核心特征:

1. 函数式,而且是纯函数式(purely functional)

首先,引用一下维基百科上对“典型的函数式编程语言”的划分:

    一: 纯函数式

      1. 强静态类型: Miranda , Haskell

      2. 弱类型: Lazy K

    二:  非纯函数式

      1. 强静态类型:  ML家族(包括OCaml , F#), Scala

      2. 强动态类型:Lisp家族(包括Comon Lisp,Scheme, Clojure), Erlang

      3. 弱类型:Unlambda

考虑到Haskell自一出生起就替代了Miranda,实际上Haskell就是现在唯一一门还算使用者比较多的纯函数式编程语言。

而“纯”函数式的好处就是:

  a. 引用透明 (Referential Transparency) :

   即无论何时调用一个函数,对于相同的输入总产生相同的输出

  b. 无副作用 (Side-effect free) :

   不存在函数的执行过程中偷偷修改了一个全局状态而从函数类型签名上看不出来的情况。(副作用是现在很多OOP语言里Bug的根源)

   当然,不是说Haskell里无法表达副作用,副作用,比如IO,肯定是要有这种能力的。而是说Haskell通过 Monad(中文译为: 单子)这种手法,把副作用体现在类型签名上。

函数式编程相较于面向对象编程很大的不同就是一种思维方式上的变化:

  面向对象编程OOP中,貌似更关注于“数据及它们的行为”:我们把程序表现为 一堆数据(对象objects),并通过使用对象提供的接口来访问这些数据。

  函数式编程FP中,关注点更着眼于“数据及它们的流动处理”: 就像数学函数的连续运算一样。

而Haskell有了‘pure‘的特点以后,就更有利于进行 函数的“组合(composition)” 了: 因为函数都是“引用透明的”,所以真正发生计算的顺序就不重要了,这使得我们进行函数组合时更加得心应手。(如果存在副作用的话,那么 函数f -> 函数g 两个函数依次调用时,先计算f 还是先计算g 是很不一样的!因为f,g 内部可能都带有全局的副作用)

使用Haskell编程总时不时有这种感觉:函数就像“水管”,而数据就像水管中的“水”,而我们所做的就是把不同的水管“首尾拼接起来”(其中每一段水管只完成特定的小工作), 从而完成对数据的复杂的处理。

比如:

-- 写一个函数,将制定的数组中的数字全部乘以2,然后统计其中大于100的数字的个数
f :: [Int] -> Int
-- f arr = length . filter (> 100) $ map (* 2) arr
f = length . filter (> 100) . map (* 2)    -- 可以进一步省略参数(这叫做lambda演算中的 啥xx来着..., 也可以称为 啥xx风格? ...)

我们先对 arr 进行 map (* 2)  ——> 再 filter (> 100) ——> 最后统计length个数 , 一行代码即可、毫无废话、极其简洁!(想想Java 8 以前的话该怎么写。。。)

       

2. 静态类型(statically typed),支持自动类型推导(type inference)

这个特点就不多说了。

Haskell的类型系统是基于著名的 Hindley-Miller类型系统(和ML家族的语言一样),并进行了一些扩展(如typeclass)。

从表现上看就是每个函数可自行选择添加类型签名(type signature/ contract, 一般建议都写,是很好的编程习惯),而函数体中完全不出现任何类型。

3. 惰性求值(lazy evaluation)

这其实是一种函数调用时的传参策略。

一般的传参策略包括:

  1. call by value (按值调用) :  即形参对象其实是实参对象的拷贝副本,二者不是同一个对象,函数体内对形参的修改不影响外部的实参对象。Java 中的基本类型都是按值调用的。

  2. call by reference (按引用调用) : 即形参对象和实参对象是同一个对象,拷贝的其实是一个对象的地址。 这在C++中很容易体现,Java中的引用类型都是按引用调用的。

注意,上述策略中实参都会被计算完成,比如 f (g(x)); 这个调用,肯定是先计算 g(x)得到一个值val,然后调用 f(val)

而对于惰性求值来讲,g(x) 不必进行计算!直到 f 函数体内真正使用这个 g(x)对应的形参变量时、g(x)才会被计算!

  3. 惰性求值又支持两种策略: call by name (按名调用) 和 call by need (按需调用) 。 区别是后者比前者多一个 memorization的过程,即一旦一个表达式被求值了,就会保存该结果、避免再次使用该值时的反复求值。

Haskell是 call by need.

4. 其他

比如 代数数据类型ADT、模式匹配、typeclass (类似于Java中的Interface)和多态类型。

尤其是模式匹配,实在是太好用了!

另外的什么  List Comprehension啥的不过是简单的语法糖,倒也没什么。



加一些可以扩展理解的材料吧:

1. 王垠 :  <不再推荐Haskell> :

原文地址:https://www.cnblogs.com/nanlan2017/p/10428820.html

时间: 2024-11-01 13:33:12

# 对Haskell这门语言的基本认识的相关文章

怎样才算会一门编程语言(如果你已经会了一门语言, 并且想一直会这门语言, 请在工作持续使用。如果没有机会使用, 自己给自己创造机会)

今天, 同事问我会不会Python, 我犹豫了一下:不会. 实际上我曾经学习过这个语言,当时还用它写了些小工具, 可现在我对这个语言的印象只剩下它那特殊的缩进格式了. 由此思考怎样才算会一门语言?我想每个程序员都接触过多门语言 , 那么究竟怎样才算会这门语言了呢? 会一门语言, 当需要它时, 应该能很快用该语言解决某个问题, 这个是最基本的. 如果深入一点, 真正会一门语言, 我觉得需要满足以下几点: a. 有超过一年的实践经验 b. 理解语言背后的机制, 最好阅读过该语言标准库的部分源码 c.

互联网职场:程序员如何选择第二门语言

多人爱争论第一门程序语言该学什么.每个人的出发点不同,有人认为,第一门语言应当是有趣.无进入门坎:有人则认为,第一门语言影响往后程序开发的思考方式,要严谨而富有思考性:有人以实用为出发点,认为视(将来)工作与环境而定会比较好. 似乎哪个出发点都对,只是现今程序开发领域中,开发者势必要学习多个语言,对第一门语言的争议很多,却很少人谈论第二门程序语言该学什么. 回想一下,你的第一门语言是在什么情况下开始的,你有机会选择吗? 很多人对第一门语言的选择就是无从选择,多半是学校指定课程或工作上需要,或者是

可能引发编程革命的4门语言

所有人都听说过“应该学好 C”,“Java 是 Web 开发者的首选”等等,它们几乎成为了真理.那么问题来了,难道就没有其他语言能挤走这些老家伙,使他们不再受欢迎?还是说十年后我们还是依靠着不断升级的 Objective C 和 PHP,或者一些偏向底层的语言?        幸运的是,我们已经有不少具备潜力的新兴语言,正在成为主流.其中有些是从现存的语言衍生出来的,以填补源语言的不足的.毫无疑问他们将震撼整个编程界.        更进一步地说,这些新语言的目标就是提高开发效率.他们很像这篇文

初创企业需要懂得多少门语言

Siri 可以用 17 种语言来回答问题和开玩笑.语言种类是不是很多,还是少了点?初创企业必须知道多少种语言才能覆盖全部的目标受众?我们研究了最为成功的一些公司,获得了一些非常有意思的结果. 功能和价格只是众多初创企业成功的部分原因.许多的"首选"服务之所以受欢迎,也是因为他们有着设计漂亮.易于使用的移动和网页界面,再加上富有优势的品牌口碑.而做到这些需要良好的写作和优秀的翻译能力. 不妨看一下今夜酒店预订应用,它那有些古怪但却新鲜的文案一下就抓住了用户.或是在法国用 Uber 打一次

Rust 2017 调查报告:学习曲线是最大痛点(最大的问题是这门语言太偏底层了,现在做底层的少了。还有C这个绕不过去的存在)

Rust 官方在社区上做了一次调查,以了解用户如何看待 Rust 的发展.调查共收到 5368 份回复,其中有 大约 2/3 的是 Rust 用户,剩下的 1/3 是非 Rust 用户,调查结果如下. 点此查看完整调查报告 先看正在使用 Rust 的用户情况.在使用年限方面,超过一年的占 42.5% (高于去年的 30%),有 18% 的用户只使用了不到一个月. Rust 目前主要被用于小型和中型项目,大型项目占比 16%(高于去年的 8.9%),这也表明用户越来越有兴趣将 Rust 用在大型项

高可用数据采集平台(如何玩转3门语言php+.net+aauto)

同类文章:高并发数据采集的架构应用(Redis的应用) 吐槽下:本人主程是PHP,团队里面也没有精通.net的人才,为了解决这个平台方案,还是费了一部分劲. 新年了,希望有个新的开始.技术+团队管理都有新的突破吧,在新的一年对自己好些,不能再继续搞基下去. 问题出发点: ´随着软件的日益强大,用户的使用需求越来越多,用户也希望众多数据进行整合,来达到资源的合理应用. ´有些数据资源需要抓取网页的形式来采集到数据. ´采集应用不统一,没有良好的管理程序,杂乱无章. ´采集应用经常性无响应,无相应的

最近一些朋友问我,临近快毕业了专业不对口,想转行看到IT行业就业前景不错,但是编程语言众多不了解,不知道哪门语言能够快速入门掌握,短期能让我找到工作

我做互联网前端后台开发也有四年多了,一路走过来,累并快乐着.快乐比艰辛更多,源自我的兴趣驱动.初中的一个偶然的机会我接触到了计算机,从那个时候就喜欢上开始经常到网吧上网.那个时候我对计算机领域的认识是相当有限,相当肤浅的,就知道玩游戏,以前从来都不知道不懂编程,连程序是什么,都说不出个所以然来.一次偶尔的机会接触到软件编程这块,开始说真的一窍不通,什么逻辑,脑子晕晕的,直到接触网页制作,也就是前端,入门简单,才给我带来了一个很大的自信转折,我就慢慢的去挖掘这种自信,然后我对这块产生了兴趣,一有机

学习汇编的第一天,简单看了一下这门语言的一些小技巧

我的原创:Windows环境下32位汇编语言是一种全新的编程语言.它使用与C++语言相同的API接口,不仅可以用来开发出大型的软件,而且是了解操作系统运行细节的最佳方式.本书从编写应用程序的角度,从"Hello World!"这个简单的例子开始到编写多线程.注册表和网络通信等复杂的程序,通过60多个实例逐渐深入Win32汇编语言的方方面面.本书作者罗云彬拥有十余年汇编语言编程经验,是汇编编程网站和汇编编程论坛qanda.ren的站长.本书是作者多年来编程工作的总结,适合于欲通过Win3

JDK8的怪东西,这门语言不能优雅点吗?

import java.util.Arrays; class Add2 {     int add2(int a, int b) {         return a + b;     } } interface Add3 {     default int add3(int a, int b, int c) {         return a + b + c;     } } // 利用接口的默认方法我们实现的多继承,什么玩意? class AddAll extends Add2 imple