读[作“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. 由于在(例如)[]上消除了空列表,因此从最终输出中消除了所有未通过测试的元素。concatconcat [[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],其中所有的Nothingsls都被悄悄地忽略了。