原文地址:Haskell学习-函数式编程初探
为什么要学习函数式编程?为什么要学习Haskell?
.net到前端,C#和JavaScript对我来说如果谈不上精通,最起码也算是到了非常熟悉的程度。这两门语言就像是我的盾牌和宝剑,给我保驾护航,开山劈石,伴随着我不断成长。同时C#和JavaScript它们本身也在不断地进化,不断出现越来越多方便的语法糖,但追根到底很多都是从函数式语言汲取的精华。比如高阶函数,lambada表达式,柯里化等。
于是从探险的角度,以好奇的心态开始学习函数式语言,探索这个宝库,拾取可供临摹的珍宝。最起码它能让你多一个不同的角度看待编程语言,影响你的思考方式。 学习的对象当然选择函数式语言的集大成者-Haskell。
Haskell 是一门纯粹函数式的语言。
函数式编程是面向数学的抽象,将计算描述为一种表达式求值。命令式编程是关于解决问题的步骤,函数式编程是关于数据的映射。在纯粹函数式程式语言中,你不是像命令式语言那样命令计算机「要做什么」,而是通过用函数来描述出问题「是什么」,也就是所谓范畴论中的映射关系。函数式语言有以下的特性:
函数是一等公民,可以在任何地方定义,在函数内或函数外,可以作为函数的参数和返回值,可以对函数进行组合
变量的值是不可变的(immutable),也就是说不允许像命令式编程语言中那样多次给一个变量赋值。
函数式语言的条件语句,循环语句等也不是命令式编程语言中的控制语句,而是函数的语法糖
抽象数据类型
灵活的多态
高阶函数(Higher-order function)
柯里化(Currying)
闭包(Closure)
函数式编程的优点函数式的最主要的好处主要是不可变性带来的。没有可变的状态,函数就是引用透明(Referential transparency)的和没有副作用(No Side Effect)。
函数即不依赖外部的状态也不修改外部的状态,函数调用的结果不依赖调用的时间和位置,这样写的代码容易进行推理,不容易出错。这使得单元测试和调试都更容易。
由于(多个线程之间)不共享状态,不会造成资源争用(Race condition),也就不需要用锁来保护可变状态,也就不会出现死锁,这样可以更好地并发,能够更好地利用多个处理器(核)提供的并行处理能力。
Haskell基本语法
变量和函数
一起介绍是因为在我看来,haskell中变量和函数是没有区别的。它们都是表达式,根据表达式的不同形式,分别对应到命令式语言中变量和函数的概念。 而且 haskell 中 变量 赋值后就是不可变的,该 变量 就等于被赋予的值,与命令式语言中 变量 是内存地址的引用是完全不同的概念。 硬要对应的话它更像是 C# 中的不可变量 const 或 static readonly 。
你能从下面代码中区分出哪些是变量,哪些是函数吗?
调用函数: 函数名 参数
调用函数不用大括号( ),注意的是函数首字母不能大写。 还有maxNum看不到形式参数是因为柯里化可以去掉参数,后面会介绍。
if else
haskell中 if else 表达式中的 else 部分不能省略,也就是你不能只有 if 部分
case of
case of 表达式,与其他语言的switch case 类似。
函数模式匹配
函数模式匹配的方式定义 head',以及定义阶乘函数 factorial,它本质上就是 case of 的语法糖。函数模式匹配,减少了一大堆类似 if else 的判断逻辑,是我最喜欢的特性之一。
guards 和 where
guards,类似 if else 表达式,但可读性更强,where语句定义的是局部变量表达式,它只能放在语句尾部,guards同样也是非常好的定义方式。