对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 (> ) $ map (* ) arr
f = length . filter (> ) . map (* ) -- 可以进一步省略参数(这其实就是lambda演算中的 Eta转换, 也可以称为 point-free风格)
我们先对 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> :
对Haskell这门语言的基本认识的更多相关文章
- 不把C作为第一门语言是个好主意么
---------------------------------------------------------------------------------- 不把C作为第一门语言是个好主意 ...
- web 开发人员必须学习的 3 门语言
web 开发人员必须学习的 3 门语言:html css js HTML 定义了网页的内容 CSS 描述了网页的布局 JavaScript 网页的行为
- 最近一些朋友问我,临近快毕业了专业不对口,想转行看到IT行业就业前景不错,但是编程语言众多不了解,不知道哪门语言能够快速入门掌握,短期能让我找到工作
我做互联网前端后台开发也有四年多了,一路走过来,累并快乐着.快乐比艰辛更多,源自我的兴趣驱动.初中的一个偶然的机会我接触到了计算机,从那个时候就喜欢上开始经常到网吧上网.那个时候我对计算机领域的认识是 ...
- 高可用数据采集平台(如何玩转3门语言php+.net+aauto)
同类文章:高并发数据采集的架构应用(Redis的应用) 吐槽下:本人主程是PHP,团队里面也没有精通.net的人才,为了解决这个平台方案,还是费了一部分劲. 新年了,希望有个新的开始.技术+团队管理都 ...
- 知名游戏开发者称 C++ 是一种非常糟糕、可怕的语言(C++不是一门可怕的语言,可怕的是一群没有耐心的程序员来使用C++这门语言)
抛出一个问题:C++ 真的很可怕吗? 2016 年底,C++ 之父 Bjarne Stroustrup 在一次采访中表示:”C++ 让编程专家很容易编写出复杂.高性能.低资源消耗的代码,但不足以成为广 ...
- Rust 2017 调查报告:学习曲线是最大痛点(最大的问题是这门语言太偏底层了,现在做底层的少了。还有C这个绕不过去的存在)
Rust 官方在社区上做了一次调查,以了解用户如何看待 Rust 的发展.调查共收到 5368 份回复,其中有 大约 2/3 的是 Rust 用户,剩下的 1/3 是非 Rust 用户,调查结果如下. ...
- python这门语言为什么要起这个名字
我只是一只可爱的小虫 前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Liz喵 PS:如有需要Python学习资料的小 ...
- 学前端的第一门语言HTML
学前端最终要做的就是制作各种各样的网页,html就相当于网页的骨架,所以我们学习前端的第一步就是先学html,接下来学习什么是html. 什么是HTML? HTML指的是超文本标记语言(Hyper T ...
- php 这门语言
1,基本语法 php在解析一个文件时,会查找开始和结束标记,在开始标记和结束标记之外的会被php引擎忽略 注释:使用 // 和 /*这里是注释*/ 2,php 数据类型 整形 (2345) 浮点型(3 ...
随机推荐
- pipenv管理python开发环境
简介 简单说,pipenv就是把pip和virtualenv包装起来的一个便携工具. 它不会在你的项目文件夹里生成一大堆东西,只有两个文本文件: Pipfile, 简明地显示项目环境和依赖包. Pip ...
- odoo10学习笔记五:高级视图
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/11189279.html 树视图 tree视图表现出来是列表视图,列表中一行一纪录.可以根据每行纪录的某字段值 ...
- STM32F429驱动SDRAM
1 SDRAM控制原理 1.1 SDRAM信号线 1.2 SDRAM地址线 SDRAM包含有“A”以及“BA”两类地址线: A:行(Row)与列(Column)共用的地址线 BA:独立的用于指定SDR ...
- Quantization aware training 量化背后的技术——Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference
1,概述 模型量化属于模型压缩的范畴,模型压缩的目的旨在降低模型的内存大小,加速模型的推断速度(除了压缩之外,一些模型推断框架也可以通过内存,io,计算等优化来加速推断). 常见的模型压缩算法有:量化 ...
- ping脚本--无网不利
一.本文主要涉及的内容 二.预备知识 1.打印网络接口列表 2.提取IP地址的小套路 3.更改网卡的MAC地址 4.高速的ping工具:fping 三.套路连招 1.通过一个for循环和ping列出所 ...
- JS中的箭头函数与this
转载自:https://juejin.im/post/5aa1eb056fb9a028b77a66fd#heading-1 JavaScript在ES6语法中新增了箭头函数,相较于传统函数,箭头函数不 ...
- 重装系统的jdk问题???
重装系统了!!!! 之前因为不懂电脑,然后自己动手装了台台式机,简直太开心了,又自己装了个系统,一切都非常欢乐,来到了给电脑起名字的时候,我不知道有多少人会卡在起名字这里,但是我那个时候非常开心,就想 ...
- [RN] 使用 Genymotion 导致 ” Genymotion 已连接,但无法访问互联网 “ 的错误
使用 Genymotion 导致 Genymotion 已连接,但无法访问互联网 的错误 先把要点 放前面: 网络二 一定要设置 桥接模式 网上很多文章都是设置为 NAT,笔者均失败! 笔者使用的An ...
- [LeetCode] 139. Word Break 拆分词句
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine ...
- divide two numbers using + opertor
package testpacknm; import java.util.Scanner; public class testcnm { public static void main(String[ ...