根据单子定律,
a >> b >> c >> d
-- is equivalent to
-- (values) (computations)
do a do { a do { _x <- a
b ; b ; _y <- b
c ; c ; _z <- c
d ; r <- d ; r <- d
; return r ; return r
} }
并用 Monad Comprehensions 编写它——这对于列表而言,非巧合地,与 List Comprehensions 完全相同——它变成了
[ r | _x <- a, _y <- b, _z <- c, r <- d ]
这意味着,在伪代码中,
for each _x in a: for each _x in a:
for each _y in b: for each _y in b:
for each _z in c: for each _z in c:
for each r in d: do d
do yield r
所以我们只是“做”同样的d,一遍又一遍,以嵌套的方式上面操作的每个结果组合。
对于列表,这意味着将d 的元素重复拼接到结果列表中。
在某种意义上,广义(嵌套)循环是(monads)/applicative/functors是,描述了从最深层次产生最终结果的组合计算: (*)
Functor Applicative Monad
for x in a: for x in a for x in a:
do yield (foo x) and y in b: for y in (bar x):
do yield (foo x y) do yield (foo x y)
"loop" "loops" "nested loops"
(created on the fly)
(*) 无论有多少层,从整体上看,“循环”组合都会一个接一个地产生结果,就像每个“循环”在分离中产生它的枚举一样,逐个。它是如此微不足道,我们甚至在命令式循环中都不会注意到它。
每种特定类型的 Functor 赋予上述“for”、“in”和“do yield”其含义。对于列表,这意味着在结果中进行拼接,通过concat/concatMap 实现。