Haskell:列表理解谓词顺序

Haskell:列表理解谓词顺序,haskell,list-comprehension,Haskell,List Comprehension,在网上阅读了列表理解的Haskell语法之后,我感觉谓词总是排在最后。例如: [(x,y) | x <- [1..10000], y <- [1..100], x==2000, odd y] [(x,y)| x它们在生成多少中间结果/列表的方式上有所不同 您可以通过一些跟踪将其可视化-注意,我对其进行了一些修改,以给出合理的结果-同时,我将返回值替换为(),以使其更清晰: comprehension1 = [ () | x <- [1..3], trace' 'x' x, y

在网上阅读了列表理解的Haskell语法之后,我感觉谓词总是排在最后。例如:

[(x,y) | x <- [1..10000], y <- [1..100], x==2000, odd y]

[(x,y)| x它们在生成多少中间结果/列表的方式上有所不同

您可以通过一些
跟踪将其可视化-注意,我对其进行了一些修改,以给出合理的结果-同时,我将返回值替换为
()
,以使其更清晰:

comprehension1 = [ () | x <- [1..3], trace' 'x' x, y <- [1..3], trace' 'y' y, x==2, odd y]
comprehension2 = [ () | x <- [1..3], trace' 'x' x, x==2, y <- [1..3], trace' 'y' y, odd y]

trace' :: Show a => Char -> a -> Bool
trace' c x = trace (c : '=' : show x) True
现在你注意到什么了吗

显然,在第一个示例中,
x=1,2,3
y=1,2,3
的每个
(x,y)
对在应用过滤器之前生成


但在第二个示例中,
y
s仅在
x=2
时生成,因此您可以说它更好/性能更好

[(x,y) | x <- [1..10000], y <- [1..100], x==2000, odd y]

具体地说,将列表理解传递给类似
mapM_uuu-print
的内容在操作上与在命令式版本中将
yield
替换为
print
相同


显然,如果可能的话,在生成器中为
浮动一个保护/
(很少的例外是生成器实际上是一个空列表,并且保护条件的计算代价很高)

一个很好的起点您的链接给了我一个尝试无限列表的想法,并且确实产生了结果。
取10[(x,y)| x对于列表理解的去除,请参见是核心语言问题的规范、全面的资源。我现在没有跟踪可以这样使用,谢谢!这也很有趣,因为它没有明确地写在任何地方,我可以很容易地想象掉进了将谓词放在最后的陷阱,并以一个有趣的结果结束永远不会结束的动作。不仅如此,在执行的计算数量上似乎存在显著差异。我对定义做了一些更改,我认为您现在可以看到发生了更好的事情-但是的,您仍然需要仔细考虑;)使用
trace'cx=trace(c:'=':show x)True
因此
跟踪“x”x
跟踪“y”y
会使行更短,可能更容易阅读。
λ> comprehension1
x=1
y=1
y=2
y=3
x=2
y=1
[()y=2
y=3
,()x=3
y=1
y=2
y=3
]
λ> comprehension2
x=1
x=2
y=1
[()y=2
y=3
,()x=3
]
[(x,y) | x <- [1..10000], y <- [1..100], x==2000, odd y]
for x in [1..10000]:
    for y in [1..100];
        if x == 2000:
            if odd y:
                yield (x,y)
[(x,y) | x <- [1..10000], x==2000, y <- [1..100], odd y]
for x in [1..10000]:
    if x == 2000;
        for y in [1..100]:
            if odd y:
                yield (x,y)