14

考虑wordsPrelude 函数;这真的很容易,可以用以下方式编写它:

words' :: String -> [String]
words' [] = []
words' str = before : words' (dropWhile isSpace after) where
    (before, after) = break isSpace str

但是,我注意到它的原始 Prelude 代码似乎少了很多......自然:

words                   :: String -> [String]
words s                 =  case dropWhile {-partain:Char.-}isSpace s of
                                "" -> []
                                s' -> w : words s''
                                      where (w, s'') =
                                             break {-partain:Char.-}isSpace s'

我认为有与优化相关的原因。问题是:我期望编译器应该words'像它的 Prelude 版本一样优化函数,我错了吗?我确实使用了相同的功能(break, dropWhile, isSpace)。

我曾经很惊讶 GHC 没有执行一些最简单的低级优化:

C vs Haskell Collat​​z 猜想速度对比

但除了这些{-partain:Char.-}位(编译器的这个提示在这种情况下 IMO 似乎没有多大帮助)words对于高级语言来说,代码似乎不必要地臃肿。在这种情况下,背后的原因是什么?

4

1 回答 1

12

This is nearly exactly the same code. The only difference is if we're doing the dropWhile isSpace before every call or only the recursive call. Neither is more complex than the other, but rather the latter (Prelude) version seems more verbose because the pattern matching isn't directly in the function.

You can observe the difference (and why the Prelude version has better behavior) like so:

*Main> words "    "
[]
*Main> words' "     "
[""]

Note that you can quickly verify if your "improved" versions are the same as the originals using QuickCheck.

于 2013-05-08T17:29:31.013 回答