Haskell:`reverse`或right`cons`,效率更高

时间:2014-06-21 17:31:54

标签: list haskell

自从我前一段时间学习Haskell以来,我不断看到人reverse列表,只是稍后反过来。以下用于使用分隔符拆分字符串的函数是一个示例:

splitOn ::Eq a => a -> [a] -> [[a]]
splitOn sep str = s_word str []
   where s_word []     w = [reverse w]
         s_word (c:cs) w = if (c == sep) then reverse w : s_word cs []
                           else s_word cs (c:w)

我认为原因是“缺乏”正确/反向利弊运算符,如:

rcons xs x = xs ++ [x]

当然,rcons的效率远低于cons运算符(:)。

但是上面的代码似乎通过使用reverse来介绍它自己的低效率。我想知道它是否比以下变体更有效或效率更低:

splitOn' ::Eq a => a -> [a] -> [[a]]
splitOn' sep str = s_word str []
   where s_word []     w = [w]
         s_word (c:cs) w = if (c == sep) then w : s_word cs []
                           else s_word cs (rcons w c)

这两个功能似乎都达到了同样的效果。我认为第二个版本似乎更直观(虽然可能不那么聪明)。使用这样的rcons是否有任何陷阱? (无限名单,懒惰等)。

感谢。

P.S。输出:

*Main> splitOn' ',' "a,b,"
["a","b",""]

1 个答案:

答案 0 :(得分:6)

如果使用“double reverse”来添加单个元素,rcons可能会更有效率,因为它只会遍历输入列表一次,而每个reverse一次只会遍历输入列表遍历遍历。

但是,在您提供的splitOn'示例中,reverse仅在每个输出字中使用一次,因为该值以反向形式开始累积。更重要的是,(:)将在调用reverse之前多次使用。

在使用rcons的替代方案中,每个新元素都会对列表进行线性遍历,而对于reverse,一旦结果准备好,就会只进行一次线性遍历。