我已经意识到以下程序
fibMap :: [Integer] -> [Integer]
fibMap xs = 1 : 1 : (zipWith (+) xs $ tail xs)
fix :: (b -> b) -> b
fix f = f $ fix f
> take 100 $ fix fibMap
速度惊人。它比递归定义快得多:
fib 0 = 1
fib 1 = 1
fib k = fib (k-1) + fib (k-2)
> fib 100
我很难理解定点定义实际上归结为哪种程序算法。仅仅是因为 Haskell 的编译器做了一些巧妙的优化,还是它本质上很快?
让我们稍微解开固定点:
x = fix fibMap = fibMap $ fix fibMap
= 1:1:(zipWith (+) y $ tail y)
where y = fix fibMap = fibMap $ fix fibMap
Haskell 编译器是否识别 x = y 和“short-fuse”?它会更多地了解列表 x,还是会从头开始重新计算 y 的所有内容?
我觉得短融合会产生一个快速的算法,而重新计算 y 会给出大致相当于递归算法的东西?
是否有任何技巧/思维方式可以更轻松地确定使用固定点的算法的复杂性?它对编译器的评估策略敏感吗?