lists在概念上是递归的。一个lists要么为空,要么为另一个lists加上一个元素。
build a list
ghci> 1:[]
[1]
ghci> 1:[2,3,4]
[1,2,3,4]
值得注意的是,在Haskell中,字符串就只是字符的列表而已。
ghci> 'h':'e':'l':'l':'o':[]
"hello"
ghci> 'h':"ello"
"hello"
但是ghci> "h":"ello"
就会报错。事实上,在Haskell总,所有的lists都是以这种冒号连接的形式存储的,[. . .]这种形式只是语法糖而已。
-- "h" is ['h']
-- "ello" is ['e','l','l','o']
-- 两个列表可以使用++运算符联合
ghci> "h" ++ "ello"
"hello"
ghci> [1] ++ [2,3,4]
[1,2,3,4]
关于惰性求值
ghci> [1 .. 10]
[1,2,3,4,5,6,7,8,9,10]
ghci> [1,3 .. 10]
[1,3,5,7,9]
ghci> [1 .. ]
[1,2,3,4,5,6,7,8,9,10,11,12 ..
--它生成了一个无限长的列表!
这就引出了Haskell中一个重要的特性,惰性求值,你可以在函数中使用这个无限长的列表而不会编译报错,因为程序只会在你需要值的时候才进行求值!虽然惰性求值会给你编写程序带来一定的方便,但我觉得它同时会带来性能方面的劣势。
list上常用的函数
head
和tail
,head取一个列表的第一个元素,tail取除过第一个元素剩下的元素。
ghci> head [1,2,3]
1
ghci> head [[1,2], [3,4], [5,6]]
[1,2]
ghci> tail [1,2,3]
[2,3]
ghci> tail [3]
[]
-- []列表和其它列表不同,对空列表调用head或者tail程序会报错。
!!
运算符,取列表的特定下标值。
ghci> [1,2,3] !! 0
1
ghci> [1 .. 10] !! 3
4
ghci> (!!) [1,2,3] 0
1
-- 中缀运算符可以加上括号变为前缀运算符。
length
,reverse
,elem
ghci> length [1 .. 20]
20
ghci> reverse [1,2,3]
[3,2,1]
ghci> elem 13 [1,13 .. 100]
True
ghci> elem 2 [1,3,5]
False
ghci> 8 `elem` [3,5,7]
False
take
and drop
ghci> take 5 [2,4 .. ]
[2,4,6,8,10]
ghci> take 3 "wonderful"
"won"
ghci> take 10000 [1]
[1]
ghci> drop 2 [1,2,3,4,5]
[3,4,5]
zip
ghci> zip [1,2,3] [4,5,6]
[(1,4), (2,5), (3,6)]
ghci> zip "dog" "rabbit"
[('d','r'), ('o','a'), ('g','b')]
cycle
,它使用惰性求值创造了一个无穷序列,给一个列表,cycle
重复这个列表直到无穷无尽!
ones n = take n (cycle [1])
ghci> ones 4
[1,1,1,1]
ghci> ones 2
[1,1]
网友评论