Heskell与函数式编程

导语 :这个系列打算分为三部分,由浅入深地介绍所谓的函数式编程 1)Haskell入门 2)Monad介绍 3)函数式编程的思想

Haskell简介

Haskell诞生于1990年,是一门纯函数式编程语言,和我们经常使用的JAVA不一样,JAVA是一门命令式编程语言。函数式编程和命令式编程有本质上的区别,命令式编程是基于冯诺依曼体系的抽象,通俗点来说就是像电脑运作般思考,而函数式编程更多是数学抽象上函数的概念,也就是输入和输出的映射关系。

我们来举个简单里例子,一个价格的集合,大于20块的打9折,然后相加。

下面是JAVA的示例:

这里的写法非常清晰明了,循环价格的集合,找出其中大于20的价钱,打九折,然后加到价格总数里面,实际上计算器内部使用寄存器和跳转指令执行的流程也是相差无几,这就是用计算机执行的思维去写代码。

然后看下Haskell对这个问题的处理:

就一行代码,涉及了三个函数

1)filter :从价格集合中筛选出大于20的价格,形成新的集合

2)map:对1中产生的新集合进行变换处理,这里的处理是每个元素*0.9,也就是打九折

3)sum:对2中产生集合进行求和处理

从这里可以看到,Haskell的基本处理单位是函数(函数是一等公民),一个函数可以成为另外一个函数的输入,函数和数学范畴的映射是一样的。

因此掌握Haskell对理解函数式编程具有很大的作用。

编写第一个Haskell

编写Haskell之前需要把Haskell Platform下载下来(https://www.haskell.org/platform/),安装后使用ghci就可以进行Haskell编程了。

我的电脑是Windows,在Windows下打开cmd,输入ghci,就能进入编程界面,在这个界面能够进行简单的编码,比如下面:

这里简单的进行了一次 3+5的求和操作。

但是我们更加习惯于用编辑器进行编码,下面使用文本编辑器来写一段代码。

这段代码定义了一个函数findMax,输入两个数字x和y,输出x和y的最大值,这里要注意下haskell内if else语句else是不可或缺的,不像JAVA可以只写if不写else。

写完保存成文件(这里保存为cal.hs),以.hs作为后缀,在对应目录的命令行下面输入 :l 文件名

调用自定义的函数findMax,输入参数1 3,然后就能够看到输出最大值3了。

类型和函数

Haskell是静态类型,也就是编译器在编译过程中就能够明确每个值的类型,当发现类型不匹配的时候,在编译过程中就会报错。比如输入这样一个函数:

== 是个表达式,编译的时候会进行1和”2“的类型判断,1是Int类型,”2“是[Char]类型,因此会报编译错误。

Haskell 可以使用 :t 命令来查看数值的类型,下面来看下一些常见的类型。

可以看到一些基础的类型

True ,Char,[Char]

然后对于  :t 0 的理解   ( 0 :: Num a => a ),表明 0是一种Num类族(typeclass)的a,Num类族这里可以先简单理解为JAVA的interface,Integer,Double等都是它的”实现“,和在之后的篇章再详细介绍到typeclass的概念。

我们先看下函数的类型是怎么样的,之前我们定义过一个函数findMax,这里看下

这里Ord也是一个typeclass,一个他的实例的类型能够使用>来比较大小,然后后面跟着三个a,这里简单做下括号就能够区分了。

( a -> a ) -> a ,最后一个参数输出,前面两个a是入参,用文字来描述就是:

输入两个Ord类族的参数,输出一个Ord类族的输出。

这里对findMax对下简单的变形,让它更能突显问题:

这里看下type

用文字来表述:

入参是(Ord , Ord , (Eq , Fractional) )类族的三个参数,出参是一个Boolean值,其中z具有Eq和Fractional两个特性,Eq的作用是能够做==比较,Fractional表示z能够被分解为分数。

未完待续

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Petrichor的专栏

tensorflow: Shapes and Shaping 探究

591
来自专栏Golang语言社区

Go语言中反射的正确使用

介绍 反射是元数据编程的一种形式,指的是程序获得本身结构的一种能力。不同语言的反射模型实现不一样,本文中的反射,仅仅指的是Go语言中的反射模型。 反射有两个问题...

3408
来自专栏Python小屋

Python计算前n个自然数的阶乘和

本文来源于粉丝私信的问题,目的在于计算result = 1!+2!+3!+...+n!,因为代码比较简单,没加注释,有问题可以留言交流。文中给出了2段代码,在实...

2905
来自专栏日常分享

通过回车键来结束一段不定长度的数组的输入。

以回车键结束一串数据的录入,则所有需要录入的数据肯定为一行,则可用nextline()函数来获取全部。

743
来自专栏aCloudDeveloper

大神洗礼第一讲——防御性编程相关

Author:bakari           Date:2012.10.18 这段时间非常有幸能够跟着一个非常牛的学长学习编程,现将每次学到的内容作为整理,方...

17610
来自专栏程序猿的那些趣事

H5学习从0到1-H5列表(8)

1.无序列表:使用标签 ul,li 属性:disc(默认实心圆) circle (空心圆)square (方块)

603
来自专栏Golang语言社区

Go语言中反射的正确使用

介绍 反射是元数据编程的一种形式,指的是程序获得本身结构的一种能力。不同语言的反射模型实现不一样,本文中的反射,仅仅指的是Go语言中的反射模型。 反射有两个问题...

33416
来自专栏calmound

D3DXCreateTexture

HRESULT D3DXCreateTexture( __in LPDIRECT3DDEVICE9 pDevice, __in UINT...

3288
来自专栏用户2442861的专栏

限制QLineEdit的数值输入范围

QLineEdit *lineEdit = new QLineEdit(this);

611
来自专栏C/C++基础

C++IO流简介

输入输出(IO)是指计算机同任何外部设备之间的数据传递。常见的输入输出设备有文件、键盘、打印机、屏幕等。数据可以按记录(或称数据块)的方式传递,也可以 流的方式...

913

扫码关注云+社区