Haskell is evaluating much faster then I thought it would (no complaints)

本秂侑毒 提交于 2019-12-23 17:43:48

问题


I wrote the following to check if a number is prime:

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

and it works, but I noticed something weird. If I run factorsOf on a large number (say 100000001), it takes a few seconds to calculate all the factors. If I run isPrime on the same number though, it will return almost immediately if it finds a factor. Does Haskell actually keep track of the condition that a function will return to to support (I'm assuming) lazy evaluation? Thats awesome if it's true.


回答1:


As noted in the comments, isPrime only needs to evaluate the result of factorsOf deeply enough to determine if it is an empty list or not. You could write isPrime more idiomatically like this:

isPrime = null . factorsOf

where null is simply

null (_:_) = False
null _ = True

Note that as soon as null can pattern match on a (:) constructor, it returns a result without evaluating the rest of the list.

This means only the factorsOf only needs to compute the first factor for isPrime to return, whereas factorsOf by itself will compute the entire list.




回答2:


The basic principle of laziness is that nothing is evaluated unless it is really really needed. Really needed in your case means that the first function must return so that the other function gets its input. You can read more about Haskell's Laziness here



来源:https://stackoverflow.com/questions/24263611/haskell-is-evaluating-much-faster-then-i-thought-it-would-no-complaints

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!