问题描述
我试图了解模式匹配的时间复杂度。我认为,像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
进行编译并观察输出。