Haskell:列表理解谓词顺序
在网上阅读了列表理解的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
[(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)