我正在Haskell学习。
我一直在实现一个列出除数的函数。
我的第一个代码在这里:
码:
divisors :: Integral a => a -> [a]
divisors n
| n < 1 = []
| otherwise = filter ((== 0) . (mod n)) [1..n]
此代码与Making a list of divisors in Haskell几乎相同。
它有效但是很慢。
我觉得除以每个
[1..n]
效率不高。是否有另一种聪明的方法来列出除数列表?
更新:
对于
n < 1
,[1..n]
与[]
相同。因此,根本不需要警卫:
divisors :: Integral a => a -> [a]
divisors n = filter ((== 0) . (mod n)) [1..n]
最佳答案
强制性单子代码:
import Control.Monad
divisors = map product . mapM (scanl (*) 1) . group . factors
factors
与您其他链接的问题相同。您已经在使用List monad中的
sequence
,无需显式调用concatMap
(mapM f
等效于sequence . map f
)。不过,该列表不会被排序,就像您最初按顺序划分的O(n)代码生成的列表一样,您可以通过简单的技巧将其设置为O(sqrt(n)),尽管它仍然可以平均而言,它比此代码要慢得多。