pie*_*fou 4 recursion haskell lazy-evaluation
运行以下程序将打印"空间溢出:当前大小8388608字节".我已经读过这个和这个,但仍然不知道如何解决我的问题.我正在使用foldr,不应该保证它是"尾递归"吗?
到目前为止,我对Haskell感觉很棒,直到我知道在使用强大的递归时我应该防止"空间溢出".:)
module Main where
import Data.List
value a b =
let l = length $ takeWhile (isPrime) $ map (\n->n^2 + a * n + b) [0..]
in (l, a ,b)
euler27 = let tuple_list = [value a b | a <-[-999..999] , b <- [-999..999]]
in foldr (\(n,a,b) (max,v) -> if n > max then (n , a * b) else (max ,v) ) (0,0) tuple_list
main = print euler27
Run Code Online (Sandbox Code Playgroud)
编辑:isPrime为简单起见删除定义
yai*_*chu 11
正如皮尔回答的那样,你应该使用foldl'.更多细节:
foldl' 在将其放入折叠步骤之前计算其"左侧".foldr给你的折叠步骤一个右侧值的"thunk".这个"thunk"将在需要时计算.让我们总结foldr并看看它如何评估:
foldr (+) 0 [1..3]
1 + foldr (+) 0 [2..3]
1 + 2 + foldr (+) 0 [3]
1 + 2 + 3 + foldl (+) 0 [] -- this is a big thunk..
1 + 2 + 3 + 0
1 + 2 + 3
1 + 5
6
Run Code Online (Sandbox Code Playgroud)
并使用foldl':(代码中省略了标签,因为SO不能很好地显示它)
foldl (+) 0 [1..3]
-- seq is a "strictness hint".
-- here it means that x is calculated before the foldl
x `seq` foldl (+) x [2..3] where x = 0+1
foldl (+) 1 [2..3]
x `seq` foldl (+) x [3] where x = 1+2
foldl (+) 3 [3]
x `seq` foldl (+) x [] where x = 3+3
foldl (+) 6 []
6
Run Code Online (Sandbox Code Playgroud)
用途好foldr,不泄漏."步骤"必须:
良好foldr用法的例子:
-- in map, the step returns the structure head
-- without evaluating the "right-side"
map f = foldr ((:) . f) []
filter f =
foldr step []
where
step x rest
| f x = x : rest -- returns structure head
| otherwise = rest -- returns right-side as is
any f =
foldr step False
where
-- can use "step x rest = f x || rest". it is the same.
-- version below used for verbosity
step x rest
| f x = True -- ignore right-side
| otherwise = rest -- returns right-side as is
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2594 次 |
| 最近记录: |