我正在研究 Real World Haskell(我在第 4 章),为了练习一些书外知识,我创建了以下程序来计算第 n 个素数。
import System.Environment
isPrime primes test = loop primes test
where
loop (p:primes) test
| test `mod` p == 0 = False
| p * p > test = True
| otherwise = loop primes test
primes = [2, 3] ++ loop [2, 3] 5
where
loop primes test
| isPrime primes test = test:(loop primes' test')
| otherwise = test' `seq` (loop primes test')
where
test' = test + 2
primes' = primes ++ [test]
main :: IO()
main = do
args <- getArgs
print(last (take (read (head args) :: Int) primes))
显然,因为我保存了一个素数列表,所以这不是一个恒定的空间解决方案。问题是当我尝试获得一个非常大的素数时说./primes 1000000
我收到错误:
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase
我相当确定我的尾递归是正确的;阅读http://www.haskell.org/haskellwiki/Stack_overflow和这里的各种回复让我相信这是懒惰评估的副产品,并且 thunk 正在积累直到它溢出,但到目前为止我一直没有成功修复它。我试过seq
在各个地方使用强制评估,但没有效果。我在正确的轨道上吗?还有什么我没有得到的吗?