Haskell在这做什么样的优化?

时间:2014-06-23 22:14:09

标签: haskell

所以,我确实是一个Haskell新手,但我到目前为止很喜欢它,因为我最近一直在使用素数挥霍。 (这是让我接受它的原因)

我有这个相对基本的脚本。即使它没有尽可能高效,它也能正常工作。但这不是我的问题。这是我的剧本:

import System.Environment


oddFactors p = [x | x<- [3,5..floor (sqrt (fromIntegral p))], p `mod` x == 0]
prime x = oddFactors (2^x -1) == []

main = do
    args <- getArgs
    print (prime (read (head args) :: Int))
像我说的那样简单。 oddFactors会从3sqrt(p)查看奇数,如果它是p的因子,则会将其添加到列表中。

primesoddFactor上调用2^x -1并检查结果列表是否等于空列表。

奇怪的是,它似乎已经被优化了。如果我要做primes,例如61,我的程序需要49秒才能运行并返回True。但是,如果我执行60或62,则需要运行.005s并返回False。这些是正确的返回值,但我很好奇,如果它以某种方式进行优化,因为它知道它只查找匹配[]的列表,并且在找到它之后,它返回false,因为列表永远不会是[]

冗长的问题,但我也愿意对我的代码提出任何建议。大约两个小时前我选择了Haskell,所以要好看:)

编辑:我当然知道我可以使用更好的东西作为素性测试,例如Miller-Rabin,但这不是重点;)

2 个答案:

答案 0 :(得分:5)

测试list == []将仅根据检查list空虚所需的内容评估list。从技术上讲,尽可能多地发现list的最外层构造函数(可能是:[]),将list置于弱头正常形式(WHNF)。< / p>

例如,(error "hello" : error "world") == []将在不评估False表达式的情况下返回error

这是由于表达式被懒惰地评估,而(==)的定义是以自然的方式使用模式匹配:

[]     == []     = True
[]     == _      = False
_      == []     = False
(x:xs) == (y:ys) = x==y && xs==ys

相比之下,如果定义是

[]     == []     = True
[]     == (y:ys) = []==ys && False
(x:xs) == []     = xs==[] && False
(x:xs) == (y:ys) = x==y && xs==ys

然后list == []会强制计算整个列表,然后再返回False(或者更确切地说,整个list spine)。

答案 1 :(得分:3)

Haskell懒惰地评估函数调用。这意味着它首先试图找出==&#34;电话&#34;评估时,说prime 60它试图找到1152921504606846975的奇数因子。在对此进行评估时,它将下降到==定义,对于空列表,该定义仅尝试确定是否存在至少一个元素。所以有效它只评估是否

1152921504606846975 `mod` 3 == 0

由于这是真的,它甚至不会评估列表的其余部分:它已经知道3:(stuff) == []False,无论(stuff)可能评估什么。

当你传递它61时,它试图找到2305843009213693951的奇数因子,这是一个素数,所以它必须扩展孔列表理解,以便弄清楚它是空。这就是为什么需要这么长时间。