Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell的评估速度比我想象的快得多(没有抱怨)_Haskell_Lazy Evaluation - Fatal编程技术网

Haskell的评估速度比我想象的快得多(没有抱怨)

Haskell的评估速度比我想象的快得多(没有抱怨),haskell,lazy-evaluation,Haskell,Lazy Evaluation,我写了以下内容来检查一个数字是否为素数: factorsOf :: Int -> [Int] factorsOf n = [factor | factor <- [2..sqrtOfN], n `rem` factor == 0] where sqrtOfN = round . sqrt $ fromIntegral $ n+1 isPrime :: Int -> Bool isPrime n | factorsOf n == [] = True |

我写了以下内容来检查一个数字是否为素数:

factorsOf :: Int -> [Int]
factorsOf n = [factor | factor <- [2..sqrtOfN], n `rem` factor == 0]
    where sqrtOfN = round . sqrt $ fromIntegral $ n+1

isPrime :: Int -> Bool
isPrime n
    | factorsOf n == [] = True
    | otherwise = False
factorsOf::Int->[Int]
factorsOf n=[因子|因子布尔
isPrime n
|因子n==[]=True
|否则=假

它是有效的,但我注意到了一些奇怪的事情。如果我在一个大的数字上运行factorsOf(比如10000001),计算所有的因子需要几秒钟。但是,如果我在同一个数字上运行isPrime,如果它找到一个因子,它几乎会立即返回。Haskell真的跟踪函数返回到支持的条件吗(我假设)懒惰评估?如果这是真的,那就太棒了。

懒惰的基本原则是,除非真的需要,否则不会评估任何东西。在你的例子中,真的需要意味着第一个函数必须返回,以便另一个函数得到它的输入。你可以阅读更多关于Haskell懒惰的信息,如注释中所述,
isPrime
只需深入评估
factorsOf
的结果,以确定它是否为空列表。您可以更习惯地这样编写
isPrime

isPrime = null . factorsOf
其中null是

null (_:_) = False
null _ = True
请注意,只要
null
可以在
(:)
构造函数上进行模式匹配,它就会返回一个结果,而不计算列表的其余部分


这意味着只有
factorsOf
只需要计算
isPrime
返回的第一个因子,而
factorsOf
本身将计算整个列表。

isPrime中的守卫只关心
factorsOf
是否包含任何元素。一旦找到一个因子,r
isPrime
的结果是可以确定的。不需要评估整个因素列表。尝试将性能与大素数(如100000007)作为输入进行比较。@Xeo这是我的想法;这很酷。如果我想了解更多信息,关于延迟评估的文章可以吗,或者是特例?@Nikl如B所示。我假设只要factorsOf call?
factorsOf 10000001
[17]
,它就可以立即计算。如果你在烤面包机上运行,那么也许,但在现代台式计算机上,没有32位的数字是“大”的。想要一个大的因子列表吗?试试
factorsOf$product[1..17]
,但将
Int
替换为
Integer
,以获得任意精度的算术。对于非常大的列表,请尝试
product[1..20]