【发布时间】:2013-04-22 16:52:07
【问题描述】:
我的foldl 阻止它终止或产生输出的具体问题是什么?
首先,我实现了一个素数筛。这不是最好的,但它就像(例如)take 20 primesA 一样工作得很好。
primesA :: [Integer]
primesA = sieve 2 []
sieve :: Integral a => a -> [a] -> [a]
sieve i [] = (i:) $ sieve (i + 1) $ map (*i) [i ..]
sieve i composites@(h : t)
| i == h = sieve (i + 1) t
| otherwise = (i:) $ sieve (i + 1) $ unionIncreasing composites $ map (*i) [i ..]
unionIncreasing :: Ord a => [a] -> [a] -> [a]
unionIncreasing [] b = b
unionIncreasing a [] = a
unionIncreasing a@(ah:at) b@(bh:bt) | ah < bh = ah : at `unionIncreasing` b
| ah == bh = ah : at `unionIncreasing` bt
| otherwise = bh : a `unionIncreasing` bt
然后我认为使用foldl 消除计数器i 会更Haskell-y,如下所示。但这并不有效。
primesB :: [Integer]
primesB = [2..] `differenceIncreasing` composites
composites :: [Integer]
composites = foldl f [] [2..]
where f [] i = map (*i) [i ..]
f knownComposites@(h:t) i | i == h = knownComposites
| otherwise = (h:) $ unionIncreasing t $ map (*i) [i ..]
differenceIncreasing :: Ord a => [a] -> [a] -> [a]
differenceIncreasing [] b = []
differenceIncreasing a [] = a
differenceIncreasing (x:xs) (y:ys) | x < y = x : xs `differenceIncreasing` (y:ys)
| x == y = xs `differenceIncreasing` ys
| otherwise = (x:xs) `differenceIncreasing` ys
当我运行(例如)head primesB 时,它既不会终止也不会产生任何输出。
据推测,ghci 正在查看无限多的素数倍数列表,试图获得列表头部的值。
但它为什么专门这样做呢?
【问题讨论】:
-
sacundim 的回答回答了您的具体问题,但您可能想看看这个:gist.github.com/nisstyre56/4699275 和论文cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf
-
@Wes - 啊哈,谢谢! M. O'Neill 论文的第 11 页显示了我所瞄准的筛子。我花了更多时间尝试自己实现这一目标,但这对我来说并不容易。现在我可以仔细研究了。
标签: haskell primes lazy-evaluation sieve