我想,我正在测试partition
列表函数的性能,得到了一些奇怪的结果。
我们有那个partition p xs == (filter p xs, filter (not . p) xs)
但我们选择了第一个实现,因为它只对列表执行一次遍历。然而,我得到的结果表明,使用使用两次遍历的实现可能会更好。
这是显示我所看到内容的最小代码
import Criterion.Main
import System.Random
import Data.List (partition)
mypartition :: (a -> Bool) -> [a] -> ([a],[a])
mypartition p l = (filter p l, filter (not . p) l)
randList :: RandomGen g => g -> Integer -> [Integer]
randList gen 0 = []
randList gen n = x:xs
where
(x, gen') = random gen
xs = randList gen' (n - 1)
main = do
gen <- getStdGen
let arg10000000 = randList gen 10000000
defaultMain [
bgroup "filters -- split list in half " [
bench "partition100" $ nf (partition (>= 50)) arg10000000
, bench "mypartition100" $ nf (mypartition (>= 50)) arg10000000
]
]
-O
我在有和没有它的情况下都运行了测试,两次我都认为双遍历更好。
我正在ghc-7.10.3
使用criterion-1.1.1.0
我的问题是:
这是预期的吗?
我是否正确使用了标准?我知道惰性可能很棘手,
(filter p xs, filter (not . p) xs)
如果使用元组的两个元素,只会进行两次遍历。这是否与 Haskell 中处理列表的方式有关?
非常感谢!