Haskell学习-函数式编程初探

原文地址:Haskell学习-函数式编程初探
  为什么要学习函数式编程?为什么要学习Haskell?
  .net到前端,C#和JavaScript对我来说如果谈不上精通,最起码也算是到了非常熟悉的程度。这两门语言就像是我的盾牌和宝剑,给我保驾护航,开山劈石,伴随着我不断成长。同时C#和JavaScript它们本身也在不断地进化,不断出现越来越多方便的语法糖,但追根到底很多都是从函数式语言汲取的精华。比如高阶函数,lambada表达式,柯里化等。
  于是从探险的角度,以好奇的心态开始学习函数式语言,探索这个宝库,拾取可供临摹的珍宝。最起码它能让你多一个不同的角度看待编程语言,影响你的思考方式。 学习的对象当然选择函数式语言的集大成者-Haskell。

什么是Haskell和函数式编程

  Haskell 是一门纯粹函数式的语言。
  函数式编程是面向数学的抽象,将计算描述为一种表达式求值。命令式编程是关于解决问题的步骤,函数式编程是关于数据的映射。在纯粹函数式程式语言中,你不是像命令式语言那样命令计算机「要做什么」,而是通过用函数来描述出问题「是什么」,也就是所谓范畴论中的映射关系。函数式语言有以下的特性:

函数是一等公民,可以在任何地方定义,在函数内或函数外,可以作为函数的参数和返回值,可以对函数进行组合

变量的值是不可变的(immutable),也就是说不允许像命令式编程语言中那样多次给一个变量赋值。

函数式语言的条件语句,循环语句等也不是命令式编程语言中的控制语句,而是函数的语法糖

抽象数据类型

灵活的多态

高阶函数(Higher-order function)

柯里化(Currying)

闭包(Closure)

函数式编程的优点

  函数式的最主要的好处主要是不可变性带来的。没有可变的状态,函数就是引用透明(Referential transparency)的和没有副作用(No Side Effect)。

函数即不依赖外部的状态也不修改外部的状态,函数调用的结果不依赖调用的时间和位置,这样写的代码容易进行推理,不容易出错。这使得单元测试和调试都更容易。

由于(多个线程之间)不共享状态,不会造成资源争用(Race condition),也就不需要用锁来保护可变状态,也就不会出现死锁,这样可以更好地并发,能够更好地利用多个处理器(核)提供的并行处理能力。

Haskell基本语法

变量和函数
一起介绍是因为在我看来,haskell中变量和函数是没有区别的。它们都是表达式,根据表达式的不同形式,分别对应到命令式语言中变量和函数的概念。 而且 haskell变量 赋值后就是不可变的,该 变量 就等于被赋予的值,与命令式语言中 变量 是内存地址的引用是完全不同的概念。 硬要对应的话它更像是 C# 中的不可变量 conststatic readonly
你能从下面代码中区分出哪些是变量,哪些是函数吗?

a = 1 -- 变量 arr = map (*2) [1,2,3] -- 变量还是函数? maxNum = foldr max 0 -- 函数 --执行 a > 1 arr > [2,4,6] maxNum [3,5,1] > 5 定义函数: 函数名 参数 = 代码
调用函数: 函数名 参数
调用函数不用大括号( ),注意的是函数首字母不能大写。 还有maxNum看不到形式参数是因为柯里化可以去掉参数,后面会介绍。

if else
haskell中 if else 表达式中的 else 部分不能省略,也就是你不能只有 if 部分

-- 等于小于大于0 分别对应 0,-1,1 sign x = if x == 0 then 0 else if x < 0 then -1 else 1

case of
case of 表达式,与其他语言的switch case 类似。

-- 求出列表第一项 head' xs = case xs of [] -> "No head for empty lists!" (x:_) -> show x -- 执行 head' "hello" >'h' head' [3,2,1] > 3

函数模式匹配
函数模式匹配的方式定义 head',以及定义阶乘函数 factorial,它本质上就是 case of 的语法糖。函数模式匹配,减少了一大堆类似 if else 的判断逻辑,是我最喜欢的特性之一。

-- 求出列表第一项 head' [] = "No head for empty lists!" head' (x:_) = show x -- 阶乘 factorial 0 = 1 factorial n = n * factorial (n - 1) --执行 head' [3,2,1] > 3 factorial 5 > 120

guardswhere
guards,类似 if else 表达式,但可读性更强,where语句定义的是局部变量表达式,它只能放在语句尾部,guards同样也是非常好的定义方式。

bmiTell weight height | bmi <= 18.5 = "You're underweight,you emo,you!" | bmi <= 25.0 = "You're supposedly normal. Pffft,I bet you're ugly!" | bmi <= 30.0 = "You're fat! Lose some weight,fatty!" | otherwise = "You're a whale,congratulations!" where bmi = weight / height ^ 2

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzdzz.html