0%

Start to learn Haskell 01

惯例闲话

昨天加班到比较晚,回家后基本上就11点多了,洗漱完毕基本上也就十二点了,不过还是坚持了一下,看了几页书,今天再接着写写。这次学的主要内容就是部分列表相关的操作,和区间以及列表推导式。由于每次都是睡觉前看上几页书并测试一下代码第二天才写BLOG,所以可能难免有些错误和遗漏,但是我仍然认为这样做是合理的,经过一段时间的理解和遗忘再加上回忆并记录下来,这可能更有利于掌握吧。

列表函数

  • null [1,2,3] 检查列表是否为空,返回TrueFalse
  • take 2 [1,2,3] 获取前n个元素组成的列表,当n为0时返回空列表,当n大于列表长度时返回整个列表
  • drop 2 [1,2,3] 删除前n个元素,并返回剩余元素组成的列表,当n等于0时返回整个列表,当n大于列表长度时返回空
  • maximum [1,4,7,3,6] 返回列表中最大的元素
  • minimum [1,4,7,3,6] 返回列表中最小的元素
  • sum [3,6,9] 对列表中的元素进行求和
  • product [3,6,9] 对列表中的元素求积
  • elem 3 [5,4,3,2,1] 检查给定数据是否为列表中的元素,返回TrueFalse

区间

简单区间

所谓区间,实际上是利用列表元素的规律以简单的方式生成较大列表的一种方法。例如,按之间所学习的,如果要定义一个从1到10所有整数的列表,就需要这样[1,2,3,4,5,6,7,8,9,10],但是如果使用区间则可以简化成[1..10],当然了,如果要生成字母A-Z的列表,同样可以使用类似的方法['A'..'Z']

自定义步长的区间

我们当然不可能只使用这种简单的+1+1+1的列表,可能我们还需要+2+2或+3+3这样的列表,那么,这样需要更改步长的区间的需求如何利用Haskell的区间生成哪,其实也很简单,确定列表最前面的两个连续元素,然后在..的后面加上最大值或最小值对列表进行限制,如[2,5..10],这样就定义了一个[2,5,8]这样的列表,由2和5决定了本列表的步长,由10限制了列表的最大值。

递减区间

上面的所有示例都是递增的区间,递减的区间实现方法跟上面的示例非常相似,比如,[10,9..1],需要特别注意的一点是,递减的区别不能用类似[10..1]这样的方式定义,因为在不没有步长因素的情况下,Haskell会认为这是递增区别,从10开始递增元素并寻找不大于1的元素,这当然是找不到的,所以用[10..1]定义的列表是个空列表。

无限列表

关于区间,我学到的最后的部分是关于无限列表的内容,所谓无限列表即是这个列表中的元素是无穷尽的,比如[1,2..],这就是一个无限列表,它的元素就是从1开始,一直递增,没有终点。当然,无需对这个列表是否会占用太多计算机资源担心,Haskell是惰性语言,表达式就在那里,你不使用的时候它就是一个表达式,而当要使用这个列表时,系统才对其进行计算,比如take 10 [1,5..],由于此表达式只是从无限列表中取10个元素出来,所以,系统只会计算到第10个元素即终止。

几个常见操作无限列表的方法

  • cycle [1,2,3] 无限循环列表
  • repeat 5 生成只有参数组成的无限列表
  • replicate 5 10 本语句生成的不是无限列表,而是由5个10组成的列表,与上一条有点相似,只不过上一条是无限列表,大多数时候可用本语句。

列表推导式

不管是直接定义简单的列表或是用区间生成列表,现在看来都过于简单,也许还需要更复杂的列表生成规则,于是现在就用到了列表推导式,列表推导式可以由一个简单的列表进行过滤或计算生成一个更适用的列表。
先来个简单的

1
[x * 2 | x <- [1..10]]

其中,|前面是要输出元素,后面是导入的列表,此表达式会将列表[1..10]中的每一个元素赋值给x传递到输出部分进行计算。还可以再给本推导式增加一个谓语,以对输出的元素进行过滤,如:

1
[x * 2 | x <- [1..10], odd x]

其中odd x是对x进行判断,如为奇数返回True,否则返回False,因此,以上推导式只会将奇数传递到输出部分进行计算。在Haskell的列表推导式中是可以增加多个谓语的,所以,还可以有如下的示例:

1
[x * 2 | x <- [1..10], odd x, x >= 5]

此示例又在前面的基础上限制了x必须大于等于5,除此之外,还可以在谓语中还可以使用自定义的函数,唯一的要求就是函数需要返回TrueFalse,如:

1
2
3
4
byThree x = if x `mod` 3 == 0
then True
else False
[x * 2 | x <- [1..10], byThree x]

本示例使用了自定义的过滤函数byThree,只使用能被3整除了元素。
除了在增加谓语对元素进行过滤外,还可以在输出中对数据进行整理,如

1
[ if x*2 < 15 then "Big" else "Bang" | x <- [1..10], byThree x]

另外,推导式还可以支持多个输入,如:

1
[ x + y | x <- [1..10], y <- [11..20]]

此表达式将输出一个对两个列表中的每个元素分别相加的列表,至于输出结果,因为比较长,写出来太难看,所以就免了。

此外,输入的列表还可以是列表的列表,在这里就不详细说了。

结尾

本来感觉昨天只看了不到半个小时的书,可写的内容应该没有多少的,结果万万没想到,竟然也让我罗嗦的那么半天,不过似乎还挺有意思的。
今天下午4点去了一趟医院,看时间也不算早,再加上最近一段时间一直加班,今天就偷懒一下,早点回家休息休息,希望加班的兄弟们不要羡慕。
因为今天回来的比较早,王爷看到我好开心的样子,哈哈,这一个人在家里学习工作是有多寂寞啊,据王爷说最近一段时间,虽然合租在一套房子里,每天跟我的交流就是听到我打呼噜的节奏,不要误会,我俩不是住在同一个房间里,只不过是房间中间就隔了一堵墙。

Welcome to my other publishing channels