我正在学习haskell并且我有以下代码:
fib a b =
a : fib b (a + b)
findFibSum =
sum [x | x <- fib 1 2, mod x 2 == 0 && x < 100]
如果我跑findFibSum
没有任何反应,它只是坐在那里。不应该评估fib
并返回每个项目吗?我猜测这与懒惰评估有关。
如果我先拨打take
并让findFibSum
接受如下所列的列表:
findFibSum $ take 100 $ fib 1 2
它起作用了。如何制作它以便我可以检索并检查每个项目?我可以通过批量使用take
来逃避,但我想首先理解这一点。
更新
感谢@amalloy,我终于得到了它:
findFibSum xs =
sum [x | x <- takeWhile (<4000000) xs, mod x 2 == 0]
takeWhile
确保一旦获得&gt; = 4m就停止从fib中检索值。
答案 0 :(得分:6)
考虑总结前100个正整数的简单问题:
sum [x | x <- [1,2..], x <= 100]
这也不起作用。作为一个人,你知道一旦x <= 100
返回False,它将永远不会再返回True,因为x
变大了。但是Haskell并不知道这一点!因此,这个列表理解产生前100个整数,然后尝试101并发现它不起作用,然后尝试102并发现它不起作用...... sum
无法确定没有列表中的更多元素,因此它永远不会为您返回一个数字。
您对fib 1 2
的列表理解存在同样的问题。您可以分别致电take
或takeWhile
来解决问题,而不是在每个元素上使用警示,如您在问题中所示。