查找素数的Haskell列表理解

时间:2011-05-22 00:44:39

标签: haskell syntax syntax-error list-comprehension primes

我正在尝试使用列表推导尽可能简洁地找到小于某个整数n的所有素数。我正在学习Haskell,这只是一个练习。我想写一些类似的东西:

isqrt :: Integral a => a -> a   
isqrt = floor . sqrt . fromIntegral

primes :: Integral a => a -> [a]  
primes n = [i | i <- [1,3..n], mod i k /= 0 | k <- primes (isqrt i)]

当然不起作用。有没有办法在列表理解中使用列表理解?

这是我得到的错误:

exercise-99-1.hs:138:39: Not in scope: `k'

exercise-99-1.hs:138:46:
    Illegal parallel list comprehension: use -XParallelListComp

exercise-99-1.hs:138:68: Not in scope: `i'

但是 - 我真的不希望语法甚至是合法的: - )

目的是尽可能直接翻译:primes n =奇数整数i小于n的集合,使i不可分割任何k,对于集合中的所有kprimes (isqrt i) - 或多或少。 (我希望我做对了吗?)

谢谢!

2 个答案:

答案 0 :(得分:0)

我在以下方面取得了一些进展:

primes :: Integral a => a -> [a]  
primes 2 = [2]  
primes n = 2:[i | i <- [3,5..n], all (\k -> if (mod i k /= 0) then True else False) 
                                     (primes (isqrt i))]

是否有更短的方法来编写lambda谓词?

编辑:是的,感谢评论中的评论!

primes :: Integral a => a -> [a]  
primes 2 = [2]  
primes n = 2:[i | i <- [3,5..n], all ((/= 0) . mod i) (primes (isqrt i))]

答案 1 :(得分:0)

你的代码,

primes n = [i | i <- [1,3..n], mod i k /= 0 
              | k <- primes (isqrt i)]

被解释为 parallel 列表理解;即,不是以通常的嵌套方式组合两个生成器,而是将它们并行组合:

primes n = [i | (i,k) <- zip [i | i <- [1,3..n], mod i k /= 0]
                                    -- not in scope: k ^
                             [k | k <- primes (isqrt i)] ]
                                  -- not in scope: i ^

相反,为了表达你的意图,它可以写成

primes 1 = []
primes n = 2:[i | i <- [3,5..n], and [mod i k /= 0 | k <- primes (isqrt i)]]
因此在列表理解中具有列表理解 - 但作为警卫的一部分,而不是发电机。函数and :: [Bool] -> Bool使这成为可能。

顺便说一下,为每个新候选人primes递归调用i会使其运行缓慢,运行时间增长得太快,empirically

 > length $ primes 10000     -- => 1229    (0.50 secs)

 > length $ primes 20000     -- => 2262    (1.40 secs)

 > logBase (2262/1229) (1.4/0.5)      -- => 1.6878      ~ n^1.69

 > length $ primes 40000     -- => 4203    (4.07 secs)

 > logBase (4203/2262) (4.07/1.4)     -- => 1.7225      ~ n^1.72

最佳试验分区通常在 ~n 1.4..1.45 ,基于列表的Eratosthenes筛, 1.2..1.25 < / sup> ,如果在可变数组上最佳实现,则在 ~n 1.0..1.1 n 的数量为产生的素数,上限。)