[英]What kind of optimizations does Haskell do here?
因此,我当然是Haskell Newbie的成员,但是到目前为止,我非常喜欢它,因为我最近一直在进行素数激增。 (这是让我着迷的原因)
我有这个相对基本的脚本。 即使它效率不高,它也可以正常工作。 那不是我的问题。 这是我的脚本:
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
从3
到sqrt(p)
奇数,如果它是p的因数,则将其添加到列表中。
primes
调用2^x -1
上的oddFactor
,并检查结果列表是否等于空列表。
奇怪的是,它似乎已经被优化了。 对于primes
,例如61,我的程序需要49秒才能运行并返回True。 但是,如果我执行60或62,则需要运行0.005秒并返回False。 这些是正确的返回值,但是我很好奇它是否经过某种方式的优化,因为它知道它只是在寻找一个匹配[]的列表,并且在找到一个列表之后,它会返回false,因为列表永远不会是[]
冗长的问题,但到目前为止,我也愿意对我的代码提出任何建议。 我大约两个小时前就接过Haskell,所以要好:)
编辑 :我当然知道我可以使用更好的东西作为初等性测试,例如Miller-Rabin,但这不是重点;)
测试list == []
将评估list
作为需要检查的空虚只有尽可能多的list
。 从技术上讲,尽可能多地发现list
的最外层构造函数(可以是:
或[]
),使list
成为弱头范式(WHNF)。
例如, (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
(或更确切地说,整个列表spine )之前强制执行整个列表的计算。
Haskell懒惰地评估函数调用。 这意味着它首先在求值时尝试找出==
“ call”,例如说prime 60
它试图找到1152921504606846975
的奇数因子。 在评估时,它会归入==
定义,对于一个空列表,它仅试图找出是否存在至少一个元素。 所以有效地它只会评估
1152921504606846975 `mod` 3 == 0
由于这是真的,所以它甚至不评估列表的其余部分:它已经知道3:(stuff) == []
为False
,而不管(stuff)
可能会得出什么结果。
当您将其传递给61
,它会尝试找到一个为质数的2305843009213693951
的奇数因子,因此它必须扩展对孔列表的理解,才能确定其为空。 这就是为什么要花这么长时间的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.