該splitAt
功能可以被實現爲以下的(https://wiki.haskell.org/Lazy_pattern_match):爲什麼lazy模式匹配splitAt函數的版本更快?
import Prelude hiding (splitAt)
splitAt :: Int -> [a] -> ([a], [a])
splitAt n xs =
if n<=0
then ([], xs)
else
case xs of
[] -> ([], [])
y:ys ->
case splitAt (n-1) ys of
~(prefix, suffix) -> (y : prefix, suffix) -- Here using lazy pattern match
main :: IO()
main = do
let r = splitAt 1000000 $ repeat 'a'
print $ length $ fst r
並且採用嚴格的模式匹配可以非常慢的速度。
time ./lazy -- 0.04s user 0.00s system 90% cpu 0.047 total
time ./strict -- 0.12s user 0.02s system 96% cpu 0.147 total
我找不到原因。根據文章,嚴格的版本可能需要更多的內存和所有遞歸調用來檢查模式是否合適。但我認爲懶惰版本也需要所有遞歸調用,並且需要內存來包含遞歸函數調用的結果。是什麼使這種差異?