Performance 模式匹配中的性能
我正在阅读,特别是关于模式匹配的章节。以下是教程中提供的用于计算列表长度的代码:Performance 模式匹配中的性能,performance,haskell,pattern-matching,Performance,Haskell,Pattern Matching,我正在阅读,特别是关于模式匹配的章节。以下是教程中提供的用于计算列表长度的代码: length' :: (Num b) => [a] -> b length' [] = 0 length' (_:xs) = 1 + length' xs 我的问题是,反转递归顺序(通过将基本情况放在下面)是否会显示任何显著的性能提高 length' :: (Num b) => [a] -> b length' (_:xs) = 1 + length' xs length' []
length' :: (Num b) => [a] -> b
length' [] = 0
length' (_:xs) = 1 + length' xs
我的问题是,反转递归顺序(通过将基本情况放在下面)是否会显示任何显著的性能提高
length' :: (Num b) => [a] -> b
length' (_:xs) = 1 + length' xs
length' [] = 0
不,这不会带来任何性能提升。在这两种情况下,编译器都必须对其WHNF的参数求值,以检查它是否为空列表 实际上,这个函数很可能会在编译过程中被重写,生成与您编写的代码完全不同的代码(假设您使用优化编译) 查看生成的核心(编译时未进行优化): 我们可以看到编译器生成了等价的语句。仅供参考,代码如下:
main = do
print $ f1 [1..100]
print $ f2 [1..100]
f1 [] = 0
f1 (_:xs) = 1 + f1 xs
f2 (_:xs) = 1 + f2 xs
f2 [] = 0
使用
ghc-ddump siml file.hs编译
仅使用两种情况,顺序并不重要。对于三种情况,顺序不会影响性能,但可以简化代码。例如,假设您有一个函数,它对空列表或单例列表执行大致相同的操作,但在包含2个或更多项的列表上递归。您可以编写从最简单到最复杂的模式:
foo [] = []
foo [x] = [x]
foo (x:y:rest) = x+y : foo (y:rest)
或者,您可以通过先处理更复杂的一个案例,将其减少为两个案例:
foo (x:y:rest) = x+y : foo (y:rest)
foo short = short
由于
foo=id
适用于这两种短情况。还有一个不重要的必要原因:模式匹配(在GHC中)非常重要。
foo (x:y:rest) = x+y : foo (y:rest)
foo short = short