读[
作“list of”、|
“for”、<-
“in”、,
“and”。
枚举以嵌套方式完成。[ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]
是真的
for c from 1 to 10 step 1:
for b from 1 to c step 1:
for a from 1 to b step 1:
if (a^2 + b^2 == c^2):
emit (a,b,c)
不过,在 Haskell 中,上述内容是通过以下翻译实现的
[1..10] >>= (\c-> -- (a function of 'c', producing ...
[1..c] >>= (\b-> -- (a function of 'b', producing ...
[1..b] >>= (\a-> -- (a function of 'a', producing ...
if a^2+b^2==c^2 then [(a,b,c)] else []
-- or: [(a,b,c) | a^2+b^2==c^2]
)))
所以你真的可以在这里看到嵌套结构。(>>=)
也没什么神秘的。读>>=
作“fed into”或“pushed through”,虽然它的正式名称是“bind”。它被定义(对于列表)为
(xs >>= f) = concatMap f xs = concat (map f xs)
f
这里按顺序map
在 的每个元素上调用 (by ) 。xs
它必须生成列表,以便它们可以与concat
. 由于在(例如)[]
上消除了空列表,因此从最终输出中消除了所有未通过测试的元素。concat
concat [[1], [], [3]] == [1,3]
有关完整翻译,请参阅Haskell 98 报告的第 3.11 节,列表理解。一般来说,列表推导可能包含一个模式,而不仅仅是一个变量名。理解力
[e | pat <- ls, ...]
被翻译为
ls >>= (\x -> case x of pat -> [e | ...] ;
_ -> [] )
哪里pat
是一些模式,并且x
是一个新鲜的变量。当存在模式不匹配时,将生成一个空列表(而不是运行时错误),并且跳过该元素x
。ls
这对于附加的基于模式的过滤很有用,例如[x | Just x <- ls, even x]
,其中所有的Nothing
sls
都被悄悄地忽略了。