Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell递归列表理解导致C堆栈溢出_Haskell_Recursion_Stack Overflow_List Comprehension_Hugs - Fatal编程技术网

Haskell递归列表理解导致C堆栈溢出

Haskell递归列表理解导致C堆栈溢出,haskell,recursion,stack-overflow,list-comprehension,hugs,Haskell,Recursion,Stack Overflow,List Comprehension,Hugs,因此,我正在制作一个素数列表,以帮助我使用简单的试算除法学习haskell(在我更好地掌握这门语言之前,没有什么特别的东西)。我正在尝试使用以下代码: primes = 2 : [ x | x <- [3..], all (\p -> (mod x p) /= 0) primes] 我在嵌套列表理解中尝试了同样的方法。它不起作用。我猜我做了太多的递归调用,但如果我只计算一个素数,情况就不应该是这样。在我看来,延迟求值应该使取2个素数按照以下方式进行: primes = 2 : [

因此,我正在制作一个素数列表,以帮助我使用简单的试算除法学习haskell(在我更好地掌握这门语言之前,没有什么特别的东西)。我正在尝试使用以下代码:

primes = 2 : [ x | x <- [3..], all (\p -> (mod x p) /= 0) primes]
我在嵌套列表理解中尝试了同样的方法。它不起作用。我猜我做了太多的递归调用,但如果我只计算一个素数,情况就不应该是这样。在我看来,延迟求值应该使
取2个素数
按照以下方式进行:

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

这是拥抱,如果这有什么区别的话

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


primes=2:[x | x(mod xp)/=0)(takeWhile(Hugs)不应该这样做,但是代码已经被破坏了,所以这无关紧要。考虑一下:

primes = 2 : [ x | x <- [3..], all (\p -> (mod x p) /= 0) primes]
primes=2:[x | x(mod xp)/=0)primes]

如何确定3是否为素数?好的,
mod 3 2==0
?否。
mod 3???==0
?哎呀!两个素数之后的下一个元素是什么?我们不知道,我们正在尝试计算它。您需要添加一个顺序约束,添加3(或任何其他
x
)一旦测试了所有小于sqrt x的p
elem
素数。

所有的文档都说“要使结果为真,列表必须是有限的”
前面的答案解释了为什么原始理解不起作用,但没有解释如何写出一个有效的理解

下面是一个列表理解,它递归地、惰性地(尽管效率不高)计算所有素数:

let primes = [x | x <- 2:[3,5..], x == 2 || not (contains (\p -> 0 == (mod x p)) (takeWhile (\b -> (b * b) < x) primes))]
let primes=[x | x0==(mod xp))(takeWhile(\b->(b*b)
显然,我们不需要检查所有素数的mod xp,我们只需要检查小于潜在素数sqrt的素数。这就是takeWhile的目的。请原谅
(\b->(b*b)
,这应该等同于
,但Haskell类型的系统不喜欢这样


x==2
在我们向列表中添加任何元素之前,阻止takeWhile执行。

all(\p->(mod xp)/=0)primes
不会终止,因为
primes
是一个无限序列。但在对斐波那契序列的规范列表理解中使用了相同的思想(如果我理解正确的话)
fibonacci=1:1:[a+b |(a,b)问题不在于使用无限列表,而是在无限列表中使用
all
…验证任意无限列表的每个元素都满足某个谓词是不可能的,而不是使用
x“最佳”这样做的方法是。但“审判分庭”方法(也在论文中描述)通常情况下,对于Haskell来说已经足够好了。我相信你应该仔细看看…3是素数,因为这是一个不相等的值。他的评论是正确的。代码将尝试读取所有素数,以确定3是否是素数。但当它试图确定3是否为素数时,它还没有计算所有素数,所以它会递归到自身中。这是无限递归,它给了你你看到的错误。@Robert我想你应该仔细看一下……我不是说3不是素数,我是在浏览给定的代码如何计算列表中的第二个元素,以显示代码是如何被破坏的。谢谢你的帮助。很抱歉,我不明白你的意思。我来自M C++,(错误地)假设在列表理解中,列表将被视为有限的,也就是说,当你构建列表时,如果你要求列表,你会得到列表中已完成构建的部分。显然,我的回答假设了更多。我没有意识到列表理解的另一个概念。显然不是(b*b)primes = 2 : [ x | x <- [3..], all (\p -> (mod x p) /= 0) primes]
let primes = [x | x <- 2:[3,5..], x == 2 || not (contains (\p -> 0 == (mod x p)) (takeWhile (\b -> (b * b) < x) primes))]