Haskell递归列表理解导致C Stack Overflow

Rob*_*son 2 stack-overflow recursion haskell list-comprehension hugs

因此,我正在制作一个素数列表,以帮助我使用简单的试验部门学习haskell(直到我的语言变得更好,没有花哨的东西).我正在尝试使用以下代码:

primes = 2 : [ x | x <- [3..], all (\p -> (mod x p) /= 0) primes]
Run Code Online (Sandbox Code Playgroud)

加载时没有错误.然而:

>take 2 primes
[2ERROR - C stack overflow
Run Code Online (Sandbox Code Playgroud)

我使用嵌套列表推导尝试了同样的事情.它不起作用.我猜我会做太多的递归调用,但如果我只计算一个素数,那就不应该这样了.在我看来,懒惰的评估应该使它做到take 2 primes以下几点:

primes = 2 : [ 3 | all (\p -> (mod 3 p) /= 0) [2] ]
Run Code Online (Sandbox Code Playgroud)

这不需要那么多计算 - mod 3 2 == True所以all (\p -> (mod 3 p) /= 0) == True,这意味着take 2 primes == [2, 3],对吧?我不明白为什么这不起作用.希望有更多精通函数式编程黑魔法的人可以帮助我......

这是在HUGS,如果这有任何区别.

编辑 - 我能够提出这个解决方案(不漂亮):

primes = 2 : [ x | x <- [3..], all (\p -> (mod x p) /= 0) (takeWhile (<= (ceiling (sqrt (fromIntegral x)))) primes)]
Run Code Online (Sandbox Code Playgroud)

EDIT2-当通过HUGS或GHCi解释时程序工作正常,但是当我尝试用GHC编译它时,它会输出test: <<loop>>.有谁知道问题是什么?

Tho*_*son 7

拥抱不应该这样做,但无论如何代码都被打破,所以无所谓.考虑:

primes = 2 : [ x | x <- [3..], all (\p -> (mod x p) /= 0) primes]
Run Code Online (Sandbox Code Playgroud)

你如何确定3是否是素数?好吧,mod 3 2 == 0好吗?没有mod 3 ??? == 0.OOPS!两个之后素数的下一个要素是什么?我们不知道,我们正在努力计算它.您需要添加一个排序约束,x一旦所有p质量elem小于sqrt x已测试,就会增加3(或任何其他).

  • 他的评论是对的.该代码将尝试读取*ALL*的素数以确定3是否为素数.但是当它试图确定3是否为素数时,它尚未计算所有质数,因此它会自行计算.它是无限递归,它会给你你看到的错误. (4认同)