Section: 2.5.1 List Comprehensions and Arithmetic Sequences

第 2.5.1 节 列表推导与算术序列

Warning: brackets in Haskell are used in three different sorts of expressions: lists, as in [a,b,c], sequences (distinguished by the ..), as in [1..2], and list comprehensions (distinguished by the bar: |), as in [x+1 | x <- xs, x > 1].

警告:Haskell 中的方括号用于三种不同的表达式:列表,如 [a,b,c];

序列(以 .. 区分),如 [1..2];以及列表推导(以竖线 | 区分),如

[x+1 | x <- xs, x > 1]。

Before list comprehensions, consider sequences:

在讲列表推导之前,先看序列:

e1 :: [Int]
e1 = [1..10]   -- Step is 1
e2 :: [Int]
e2 = [1,3..10] -- Step is 3 - 1
e3 :: [Int]
e3 = [1,-1.. -10]  -- The space before - is necessary!
e4 :: [Char]
e4 = ['a'..'z']   -- This works on chars too

We'll avoid infinite sequences like [1..] for now. If you print one, use C-c i to interrupt the Haskell program.

我们暂时避开 [1..] 这样的无限序列。如果你打印了一个,可以用 C-c i

中断 Haskell 程序。

List comprehensions are very similar to nested loops. They return a list of values generated by the expression inside the loop. The filter expressions are similar to conditionals in the loop.

列表推导与嵌套循环非常相似。它们返回由循环内的表达式生成的一系列值

组成的列表。过滤表达式类似于循环中的条件判断。

This function does nothing at all! It just scans through a list and copies it into a new one.

这个函数什么都没做!它只是扫描一遍列表,把它复制到一个新列表里。

doNothing :: [a] -> [a]
doNothing l = [x | x <- l]

Adding a filter to the previous function allows only selected elements to be generated. This is similar to what is done in quicksort.

在前一个函数中加入过滤条件,就只会生成被选中的元素。这类似于快排中

的做法。

positives :: [Int] -> [Int]
positives l = [x | x <- l, x > 0]
e5 = positives [2,-4,5,6,-5,3]

Now the full quicksort function.

现在是完整的快排函数。

quicksort :: [Char] -> [Char]  -- Use Char just to be different!
quicksort [] = []
quicksort (x:xs) = quicksort [y | y <- xs, y <= x] ++
                   [x] ++
                   quicksort [y | y <- xs, y > x]
e6 = quicksort "Why use Haskell?"

Now for some nested loops. Each generator, <-, adds another level of nesting to the loop. The variable introduced by each generator can be used in each following generator; all variables can be used in the generated expression:

现在来看一些嵌套循环。每个生成器 <- 给循环增加一层嵌套。每个生成器

引入的变量可以在其后的生成器中使用;所有变量都可以在生成的表达式中

使用:

e7 :: [(Int,Int)]
e7 = [(x,y) | x <- [1..5], y <- [x..5]]

Now add some guards: (the /= function is not equal)

现在再加上一些守卫条件:(/= 函数表示"不等于")

e8 :: [(Int,Int)]
e8 = [(x,y) | x <- [1..7], x /= 5, y <- [x..8] , x*y /= 12]

This is the same as the loop: (going to a psuedo Algol notation) for x := 1 to 7 do if x <> 5 then for y := x to 8 do if x*y <> 12 generate (x,y)

这与下面的循环等价:(用伪 Algol 记法表示)

for x := 1 to 7 do

if x <> 5 then

for y := x to 8 do

if x*y <> 12

generate (x,y)

Section: 2.5.2 Strings

第 2.5.2 节 字符串

e9 = "hello" ++ " world"