这段时间零零散散地看完了Haskell的基础部分。对于长期使用命令式编程的人来说,要理解函数式的思想还是很痛苦的,不过几天下来,还算少许有些感悟, 写下来以作备忘。
函数式编程是基于lamda演算(Lambda Calculus)的一种编程形式,最早由阿隆左.丘奇提出。基本学过计算机的人都知道,现在的计算机是基于图灵的图灵机而 设计的,用于解决逻辑推理和计算问题。而就在lamda演算被提出来不久,丘奇就有证明了它和图灵机有等价的演算能力,也就是说,图灵机模型能干的东西lamda演算也可以干。 这也就是函数式编程的理论基础。好了,关于上面的叙述我们只要牢牢记住lamda演算和图灵机是等价的就可以了,因为在初学阶段函数式编程的种种奇怪特点可能会让你在感觉上质疑这个论断。
好了,开始说Haskell。
首先,它没有变量,或者说全部变量都是常量。这是我开始最诧异的一点,你能想象满是final声明的Java代码么,完全不能!但是Haskell可以,因为它是函数式语言。 在函数式语言中,“函数”才是一类公民,基本所有的逻辑都是靠函数之间的运算和调用完成的。既然没有变量,那产生的中间结果如何存储哪?答案是函数调用的返回值,也就是栈上。 看起来有些奇怪,吃饱了撑得非得搞这么绕来绕去的方法干什么哪?首先,函数式编程嘛,让变量出风头还叫什么函数式编程。其次,它确实有一些好处,比如无副作用(side-effect)函数
无副作用
如果一个函数是无副作用的,他至少包含两点:一个是函数的运行不会改变任何状态(常量确保了这点),另一点是对于相同的输入函数总是返回相同的输出。 Haskell大部分函数都是无副作用的,当然为了和真实世界相连,也有一些副作用的函数(比如处理输入输出),但会通过明确地表示把他们分隔开来。
相比于命令式语言,函数式语言中的函数更“纯粹”和“干净”,而且更接近数学中的定义,这也是它的一大特点吧。
无副作用函数有什么优点么?
首先,易于调试:因为函数的返回值不依赖于时间和场合,我们很容易地恢复运行现场,只要确定输入参数就好了,比起普通函数错综复杂的依赖关系,调试顿时容易很多。
其次,程序健壮性好:函数不会改变外部状态,也不会受外部状态的影响,如果逻辑正确,想写出bug百出的代码都难(编程中大部分bug隐藏在状态的相互影响和制约中)
然后,无副作用的代码也使惰性求值成为了可能。
惰性求值
在haskell中如果你运行下面的代码:
let a = 1+2+3+4
当运行完这段代码的时候,a的值并没有被算出来,只有a被真正调用,比如当
print a
的时候a才会被真正算一遍并输出到屏幕上。同学们想到了在截止之前赶实验报告的情景了么,就是这样的情景。
无副作用的函数是惰性求值的基础,如果一个函数的输出不受制于时间和环境,那么什么时候的计算结果都是一样的。
惰性赋值的好处是我们可以完成下面的操作:
let x = [1..]
print head x
上面的代码x声明了一个正整数集,并输出这个集合的第一个数(head)。按照常规做法,程序会先生成x集合,然后把第一个数字取出来。但是注意:x是个无限集合! 在有限运算能力的机器上第一步就会耗尽其所有的时间。但对于惰性求值的程序哪?因为在调用x的时候已经知道只取第一个值就可以了,所以程序不比再生成之后的元素了。
惰性求值的好处在于给了编译器一个优化的空间,编译器可以综合不同函数的行为来生成最优化的结果,并最终提高代码效率(但实际上大部分Haskell程序还是很慢的,但这至少在理论上有优化的空间不是么)。
另一方面,Haskell函数更接近于数学的函数定义,我们可以借助数学工具对代码进行调优,演算,甚至在理论上验证运行的结果。
另外对于编程人员来讲,函数式编程的特性使我们更加注重于要做什么,而不是怎么做。(比如上面的例子,函数式编程的思路是:来一份正整数集,然后给我第一个数。命令式编程的思路是: 生成一个循环,上界设为1,并取出循环的序号1)。
闭包
感觉没什么可以说的,既然函数作为第一类公民,则函数可以扮演任何变量所能扮演的角色,可以做输入,也可以做返回值,可以来回传递。由于函数式语言一切量皆为常量的性质, 所以不必担心像JS里面的赋值问题(见这里)。
以上是一个作为Haskell新手的粗鄙理解,难免有很多错误。希望大家能多提意见
分享到:
相关推荐
学习您的haskell笔记本:Jupyter改编的《 Learn a Haskell for Great Good!
haskell-概念-思维导图作为思维导图的学习haskell笔记
Haskell实践Graham Hutton撰写的Haskell编程笔记/实践-第二版
这些是我关于如何使用 github 和 cabal 创建新的 Haskell 库的笔记。重要链接阴谋集团指南: : Github 降价帮助: : Haddock 用户指南: : 初始化 Cabal 您只需为每个系统执行一次此操作。 以下所有步骤都应在您的...
Action-Haskell-分析这是你... 布赖恩赫特的 Monad 教程4/4/14 读写 JSON,使用 Haskell 数据结构1、2、12MWF早晨早餐桌编码器。 喜欢健身房,但有代码和咖啡。 4/18/14 数字和字符串操作3、7、8 5/2/14 可视化数据,将
很棒的笔记 _ _ _____ ___ ___ _ __ ___ __... 个人学习笔记-很棒的自我笔记 样品 C 用指针实现通用变量 void * lsearch ( void *key, void *base, int n, int elemSize, int (*cmpfn)( void *, void *) ) { f
本项目记录从本科开始的各种代码片段和学习笔记,以便再实际应用中Swift造出轮子。本项目涵盖领域如下 收录的编程语言包括跑的比谁都快的C/C++,面向对象的Java和Python,函数式编程家族的Haskell、Scala和Lisp,...
例如:C ++,Java,Python,PHP,Ruby,Erlang,Perl,Haskell,C# Cocoa,JavaScript,Node.js,Smalltalk,OCaml和Delphi等语言。 Thrift功能简介 在使用Thrift时,我们首先需要编写一个thrift文件。 这个文件是...
思维转储在浏览书籍时,此回购... Munkres拓扑的学习笔记。我解决方案 我的解决方案 。 我对SICP练习的解决方案。 在我的博客上查看有关SICP的。我尝试实现各种算法来解决。我的Daniele Turi的“类别理论讲义”笔记。
编程语言:复习说明编程语言:复习笔记为什么要进行函数式编程为什么选择HaskellHaskell-Windows上的安装和入门前往Haskell IDE for 学习资料了解Haskell
个人学习笔记与博文 Menu Tools Plugin css-plugin js-plugin react-plugin python-plugin Framework css-ui-framework react-ui-framework Notes JavaScript Python html & css 前端工程 NodeJS 基础 Express KOA ...
我们专注于与Haskell,Elm和Nix合作。关于我自2000年代中期以来,我一直在进行编程,并从编写IRC脚本和调整论坛软件开始。 我最喜欢的编程语言是 ,我最喜欢的编程语言是 。 我认为静态类型的函数式编程可提高开发...
用于 Idris 的实验性 Google Go 后端这样做的动机我想改进我的 Haskell 和 Idris,并学习 Go ???一些功能/好处与 Go 以及通过 cgo 与 C 轻松互操作UTF-8 支持来自 Go(进入 Idris)支持的回调还没有调整,性能...
想象一下,您正在工作或正在学习许多不同的技术,我的情况,有罪!!! 或我们中许多使用NodeJS , React , C# , Ruby , PHP甚至Haskell (我几天前使用的是\ o /,或者例如,您只想在笔记本电脑或PC中运行一些...
您想学习描述符协议如何实现魔术方法调用,您可以通过将恶意代码插入超类来劫持,从而使调用C3线性化图的方法破坏竞争对手的代码! 好吧,如果您出于正确的原因阅读本笔记本,那么您将成为认证的Python Pro! 如果...