模式匹配时间复杂度Haskell

问题描述

我试图了解模式匹配的时间复杂度。我认为,像foo这样的匹配类型将花费固定的时间,而像bar这样的匹配类型将花费O(n),但是我无法通过逐步调试程序来解决。 / p>

module Main where

data Foo = Bar | Baz | Cat

main :: IO ()
main =
  do
  print $ foo Baz
  line <- getLine
  let x = read line :: Int
  print $ bar [x,2,3]

-- Constructors of Foo kNown in advance 
-- So this can be a jump table
foo :: Foo -> Int
foo Bar = 1
foo Baz = 2
foo Cat = 3

-- Elements of list can't be kNown in advance
-- So this should take O(n) ???
bar :: [Int] -> Int
bar [] = 0
bar (x:[]) = 1
bar (1:x:xs) = 2
bar (y:x:xs) = 3

这种模式的时间复杂度是多少?

解决方法

我用bar编译了您的-O2并生成了此Core。注释是我的,并显示了编译器生成的其他标识符的定义。

bar
  = \ (ds_d35K :: [Int]) ->
      case ds_d35K of {
        [] -> Main.bar4;            -- GHC.Types.I# 0#
        : x_a13j ds1_d35U ->
          case ds1_d35U of {
            [] -> Main.bar3;        -- GHC.Types.I# 1#
            : ipv_s3na ipv1_s3nb ->
              case x_a13j of { GHC.Types.I# ds2_d35V ->
              case ds2_d35V of {
                __DEFAULT -> Main.bar2;  -- GHC.Types.I# 3#
                1# -> Main.bar1          -- GHC.Types.I# 2#
              }
              }
          }
      }

我们可以看到,编译器先测试了第一个构造函数([]:),然后测试了第二个,依此类推。它没有对同一块中的相同构造函数执行重复测试。

据我所知,Haskell报告本身并未规定模式匹配的特定复杂性。取决于Haskell的实现方式(例如GHC)能否提供良好的优化水平。鉴于模式匹配是语言的最基本和最普遍的构造之一,因此可以期望它以一种相当有效的方式进行编译。

要重现此内容,可以使用-O2 -ddump-simpl进行编译并观察输出。