![0bcb5d2862756ae5c6f6bb7f1852b1a0.png](https://i-blog.csdnimg.cn/blog_migrate/874582fb3f893cbe1f8238bd398381e6.png)
列表
Haskell里列表是保存相同类型的线性表,比如[1, 2, 3]
就是一个整数列表。字符串"hello"
只是一个语法糖,即它其实就是字符列表['h','e','l','l','o']
。
Prelude> [1, 2, 3, 4] ++ [9, 10, 11, 12]
[1,2,3,4,9,10,11,12]
Prelude> 1:[2, 3]
[1,2,3]
Prelude> "Steve Buscemi" !! 6
'B'
你可以用++
连接两个列表,可以用:
在列表前加入一个元素,可以用!!
从列表中去对应下表的元素。:
和[]
构造了列表的值,[1, 2, 3]
不过是1:2:3:[]
的语法糖。列表的比较就像字符串那样是按字典序排序的。
Prelude> [3, 2, 1] > [2, 1, 0]
True
Prelude> [3, 4, 2] > [3, 4]
True
Prelude> [3, 4, 2] == [3, 4, 2]
True
列表也有一些函数可以用,原文列了很多,就不多说了。
范围
数数是在常见不过的操作了,你当然不能笨笨地一个一个敲进去。Haskell提供了一个语法糖来帮你
Prelude> [1..5]
[1,2,3,4,5]
Prelude> [5,-1 .. 1]
[5]
Prelude> [5, 4 .. 1]
[5,4,3,2,1]
Prelude> [1,3 .. 5]
[1,3,5]
[first..end]
从first
递增到end
,而[first,second..end]
构成了等差数列。
特别地,列表可以有无穷多元素,很像很像数学中的集合
Prelude> [1..]
-- 所有正整数
Prelude> [1,3 ..]
-- 所有正奇数
Prelude> length [1..]
-- 数不过来的,亲
怎么可能产生无穷元素的元素呢,内存不就爆炸了么?嗯,如果一口气都算出来是这样。但是这种方式只是求值策略的一种。求值策略大概有两种
- 及早求值 表达式一被绑定就求值。见到
[1..]
就把所有项都算出来。这是很多语言的默认方式,但不能处理无穷、递归的情况。 - 惰性求值 表达式只有等到需要它的值的时候才会被求值。见到
[1..]
不会立刻求值,你之后用当才会。比如说输出[1..]
时会边算边输出。Haskell默认是惰性求值的。
列表推导式
数学中表示集合更常用的方式应该是这样,在Haskell里也有类似的语法糖
Prelude> [2 * x | x <- [1 ..], x <= 10]
[2,4,6,8,10,12,14,16,18,20
他们都具有这样的形式[exp | q, ..., q]
,其中
q
只可能有两种- 生成式
p <- e
表示从列表e
中提取各项 - 布尔表达式,
True
则计算exp
- 生成式
exp
计算输出列表每一项的表达式
有时候你可能并不需要具体的项
Prelude> length' xs = sum [1 | _ <- xs]
我们自己实现了函数length
并命名为length'
加以区分。*'
也可以作为标识符的一部分,通常在最后表示一点小小的变化,跟数学老师写的板书差不多。*其中我们取xs
每一项,但列表推导里面的exp
并不用,所以用_
就很不错。_
不是一个标识符,它就表示“不在乎”,不像Python那样。
惰性求值可以让length'
有几分神奇
Prelude> xs = [error "0 evaluated!", error "1 evaluated!"]
Prelude> xs !! 0
*** Exception: 0 evaluated!
Prelude> xs !! 1
*** Exception: 1 evaluated!
Prelude> length' xs
2 -- 每一项都不求值的,因为length'并不用
元组
元组与列表都是线性表,但是
- 元组各个元素可以是不同类型
- 元组没有
:
和++
运算,甚至不能!!
那怎么取元素呢 - 元组长度至少是2,列表可以为
[]
- 同类元素不同长度列表是一个类型的列表,但长度也决定了元组类型。我们还没提类型
Prelude> [1, 'a']
-- 类型不同不能构成列表
Prelude> (1, 'a')
(1,'a')
Prelude> 1 : [2, 3]
[1,2,3]
Prelude> 1 : (2, 3)
-- 没这操作
Prelude> [1] < [1, 2]
True
Prelude> (1, 2) < (1, 2, 3)
-- type ‘(Integer, Integer)’ 和 type ‘(Integer, Integer, Integer)’不同
Prelude> (1, 'a') < (1, 'c')
True
类型错误跟惰性求值不矛盾,静态类型语言不管咋求值,类型总是要能定下来。综上,元组往往用于已知个数和类型的时候,比如函数多个返回值。