Reputation: 45826
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.
Upvotes: 3
Views: 224
Reputation: 6778
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.
Upvotes: 5