模式匹配的性能

Ari*_*stu 3 performance haskell pattern-matching

我正在读" 了解你一个Haskell",特别是有关模式匹配的章节.这是教程中提供的用于计算列表长度的代码:

length' :: (Num b) => [a] -> b  
length' [] = 0  
length' (_:xs) = 1 + length' xs
Run Code Online (Sandbox Code Playgroud)

我的问题是,反转递归的顺序(通过放置基本情况下)显示任何显着的性能提升?

length' :: (Num b) => [a] -> b
length' (_:xs) = 1 + length' xs
length' [] = 0
Run Code Online (Sandbox Code Playgroud)

Thr*_*eFx 7

不,这没有提供任何性能提升.在这两种情况下,编译器必须评估它的WHNF参数,以检查它是否为空列表.

实际上,在编译期间很可能会重写此函数,生成代码与您编写的代码完全不同(假设您使用优化编译).

查看生成的核心(未经优化编译):

(letrec {
   f1_aLn [Occ=LoopBreaker] :: [Integer] -> Integer
   [LclId, Arity=1, Str=DmdType]
   f1_aLn =
     \ (ds_d1gX :: [Integer]) ->
       case ds_d1gX of _ [Occ=Dead] {
         [] -> fromInteger @ Integer GHC.Num.$fNumInteger 0;
         : ds1_d1h4 xs_at0 ->
           + @ Integer
             GHC.Num.$fNumInteger
             (fromInteger @ Integer GHC.Num.$fNumInteger 1)
             (f1_aLn xs_at0)
       }; } in
f1_aLn (enumFromTo @ Integer GHC.Enum.$fEnumInteger 1 100))

(letrec {
   f2_aBk [Occ=LoopBreaker] :: [Integer] -> Integer
   [LclId, Arity=1, Str=DmdType]
   f2_aBk =
     \ (ds_d1gP :: [Integer]) ->
       case ds_d1gP of _ [Occ=Dead] {
         [] -> fromInteger @ Integer GHC.Num.$fNumInteger 0;
         : ds1_d1gW xs_aBh ->
           + @ Integer
             GHC.Num.$fNumInteger
             (fromInteger @ Integer GHC.Num.$fNumInteger 1)
             (f2_aBk xs_aBh)
       }; } in
f2_aBk (enumFromTo @ Integer GHC.Enum.$fEnumInteger 1 100))
Run Code Online (Sandbox Code Playgroud)

我们可以看到编译器生成等效语句.只是fyi,这是代码:

main = do
         print $ f1 [1..100]
         print $ f2 [1..100]

f1 [] = 0
f1 (_:xs) = 1 + f1 xs
f2 (_:xs) = 1 + f2 xs
f2 [] = 0
Run Code Online (Sandbox Code Playgroud)

用.编译 ghc -ddump-simpl file.hs

  • 还有一个必要的原因,它无关紧要:模式匹配(在GHC中)是[模式数量的恒定时间](http://stackoverflow.com/q/9027384/2751851). (3认同)