我试图理解memoization的Haskell实现,但我不明白它是如何工作的:
memoized_fib :: Int -> Integer
memoized_fib = (map fib [0..] !!)
where fib 0 = 0
fib 1 = 1
fib n = memoized_fib(n - 2) + memoized_fib(n - 1)
首先,我什至不明白为什么“map”函数获取三个参数(函数 - fib、列表 [0..] 和 ||),而不是两个参数。
Updated:
我尝试重写代码,但得到不同的结果:
f' :: (Int -> Int) -> Int -> Int
f' mf 0 = 0
f' mf 1 = 1
f' mf n = mf(n - 2) + mf(n - 1)
f'_list :: [Int]
f'_list = map (f' faster_f') [0..]
faster_f' :: Int -> Int
faster_f' n = f'_list !! n
为什么?我的推理有什么错误吗?
第一:Haskell 支持运算符部分。所以(+ 2)
等于\ x -> x + 2
。这意味着表达式map
等于\ x -> map fib [0..] !! x
.
其次,它是如何工作的:这是利用 Haskell 的按需要致电评估策略(其惰性)。
最初,该列表由map
不予评价。然后,当您需要访问某个特定索引时,将评估该点之前的所有元素。但是,一旦某个元素被求值,它就不会再次被求值(只要您引用的是同一个元素)。这就是让你记忆的原因。
基本上,Haskell 的惰性求值策略涉及记忆强制值。这个记下来了fib
函数仅依赖于该行为。
这里“强制”一个值意味着评估一个称为 thunk 的延迟表达式。因此,列表最初基本上存储为列表的“承诺”,并强制将“承诺”转变为实际值,以及更多值的“承诺”。 “承诺”只是重击,但我希望称其为承诺更有意义。
我稍微简化了一点,但这应该可以澄清实际的记忆是如何工作的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)