【发布时间】:2019-09-30 19:38:53
【问题描述】:
我正在学习 Haskell,我试图生成一个无限的素数列表,但我无法理解我的函数做错了什么。
功能:
prime = 2:3:filter (\x -> all (\y -> (mod x y) > 0) (init prime)) [5..]
我认为是init prime,但奇怪的是,即使我设置了范围的上限(例如5..10),函数也会永远循环,并且永远不会得到prime !! 2 的任何结果
你能告诉我我做错了什么吗?
【问题讨论】:
-
您正在尝试过滤列表以仅保留那些不能被
init prime的任何元素整除的元素。为了检查init prime的每个元素,Haskell 需要找出prime的所有元素(“最后一个”除外)。现在你能看出问题了吗?当您需要完整的数据结构来计算中间结果时,惰性求值对您没有帮助。 -
您可以通过将
(init prime)替换为(takeWhile (\z -> z * z <= x) prime)来挽救您的想法,因为每个非质数的质因数都不大于其平方根。 -
您对
init primes的调用表明您认为每次迭代只会看到到目前为止构建的列表。如果这是您的信念,那么它是错误的,primes列表根本没有完全计算。避免使用您正在生成的列表部分,如 ShreevatsaR 的评论中所做的那样。 -
是的,这当然可行,谢谢,我只是想了解是否可以通过使用列表本身的一部分来递归地扩展无限列表来计算下一个元素。
-
绝对是;这就是@ShreevatsaR 的评论所建议的。您的不起作用的唯一原因是使用的无限列表部分(
init)与正在生成的列表部分重叠。如果您通过使用适当的takeWhile来防止重叠,则没有问题。
标签: haskell primes lazy-evaluation