Haskell'计数发生'功能

时间:2013-10-24 00:52:29

标签: haskell

我在Haskell中实现了一个count函数,我想知道这会在大型列表上表现得很糟糕:

count   :: Eq a => a -> [a] -> Int
count x =  length . filter (==x)

我相信length函数在线性时间内运行,这是正确的吗?

编辑:@Higemaru建议的重构

3 个答案:

答案 0 :(得分:9)

长度以线性时间运行到列表大小,是的。

通常,您会担心您的代码必须在列表中进行两次传递:第一次过滤,然后一次计算结果列表的长度。但是,我相信这不会发生在这里,因为过滤器对列表的结构并不严格。相反,长度函数在它过程中强制过滤列表的元素,在一次传递中执行实际计数。

答案 1 :(得分:4)

我认为你可以稍微缩短一下

count :: Eq a => a -> [a] -> Int
count x = length . filter (x==)

(如果可以的话,我会写一篇(低评论)

答案 2 :(得分:0)

这真的取决于清单。对于我计算机上Int的正常,懒惰评估列表,我看到这个函数在10 ^ 9个元素中运行大约2秒,10 ^ 8运行0.2秒,10 ^ 7运行0.3秒,所以它似乎以线性时间运行。您可以在命令行运行时将标志+RTS -s -RTS传递给可执行文件,从而自行检查。

我也尝试使用更多内核运行它,但它似乎没有做任何事情,只是稍微增加了内存使用量。

懒惰计算的另一个好处是你只能在列表上进行一次传递。 filterlength由编译器转换为单个循环(打开优化),因此可以节省内存和效率。