理解Haskell中的列表理解

时间:2013-06-01 22:08:25

标签: haskell

这是Euler项目任务#3的破坏者!如果您想自己解决,请不要继续阅读。

我正在尝试通过为Project Euler编写程序来学习Haskell。目前我正在尝试解决任务#3,它要求数字600851475143的最大素数因子。

为此,我创建了一个列表liste,其中包含所有数字,这些数字是此数字的除数(直至其平方根)。我现在的策略是,计算这些数字的除数,以决定它们是否为素数。

number = 600851475143
-- sn = sqrt number
sn = 775146

liste = [x | x <- [1..sn],  (mod number x == 0)]
-- liste = [1,71,839,1471,6857,59569,104441,486847]

primelist :: Int -> [Int]
primelist z = [y | y <- [1..z], mod z y == 0] 

main = print [primelist x | x <- liste]

此处应显示的结果应该是一个包含8个列表的列表,其中包含liste元素的除数。相反,列表

[[1],[1,3],[1,29],[1,3,29,87]]
打印

如何解释这种行为?

2 个答案:

答案 0 :(得分:6)

问题是类型声明primelist :: Int -> [Int]。它强制Haskell使用本机整数,即32位平台上的32位整数。但是,如果将其遗漏,Haskell会将函数类型推断为Integer -> [Integer]。整数允许以任意精度进行计算,但比本机类型慢一点。

引用Haskell FAQ中的&#34; What's the difference between Integer and Int"

  

Int上的操作比Integer上的操作要快得多,但是   溢出和下溢会导致奇怪的错误

现在不是真相。

答案 1 :(得分:0)

我不确定这是否会对你有所帮助,但我也正在通过Project Euler帮助自己教Haskell,我设计了以下解决方案:

defacto :: Integer -> Integer -> Integer
defacto x p | x == p = 1
            | x`mod`p==0 = defacto (x`div`p) p
            | otherwise = x

gpf :: Integer -> Integer
gpf = \x -> prim (x,primes)

prim :: (Integer,[Integer]) -> Integer
prim (x,(p:ps)) | p > x = 1
                | (defacto x p) == 1 = p
                | otherwise = prim((defacto x p),ps)

n :: Integer
n = 600851475143

此处,defacto将数字中的素数除去,因此defacto 2 12返回4,defacto 5 14返回14. gpf是查找最大素数的函数因素,尽管它要求最多x的素数列表在范围内。关键组件是prim,如果数字小于下一个素数,则返回1,如果x是该素数的完美幂,则返回其主要列表中的第一个素数(即,如果所有其他素数小于p)已经从x)中分解出来,否则对未定义的x和截断的素数列表执行递归调用。这具有在线性遍历素数列表的同时连续收缩x的效果,因此我们不需要测试任何不能分解为x的素数,并且我们不需要在x的减少值上重新测试相同的素数。希望这会对你有所帮助。