【问题标题】:Why is it a memoization function?为什么它是一个记忆功能?
【发布时间】:2019-07-05 09:52:15
【问题描述】:

谁能给我解释一下,为什么下面的代码是备忘录:

fib_mem :: Int -> Integer
fib_mem = (map fib [0..] !!)
where fib 0 = 1
      fib 1 = 1
      fib n = fib_mem (n-2) + fib_mem (n-1) 

【问题讨论】:

  • 你是什么意思为什么?!
  • 这个函数使用了记忆技术,中间结果被保存起来,以后可以重复使用。
  • 还不清楚你在问什么。
  • 更简单的定义是let fib :: Int -> Integer; fib = (fib' !!) where fib' = 1 : 1 : zipWith (+) fib' (tail fib')
  • 这是this question 的副本。由于技术原因,我现在无法将其作为骗子关闭。

标签: haskell


【解决方案1】:

我假设您是在询问这是如何记忆 fib 的。 fib 本身只是一个普通的函数。真正的魔法发生在fib_mem = (map fib [0..] !!),它记住了fib。这个表达式相当于说fib_mem x = (map fib [0..]) !! x。让我们分解一下,看看它在做什么:

  • [0..] 是一个无限列表,从 [0,1,2,3,..] 开始并继续ad infinitum
  • map fib [0..]fib 应用于此列表的每个元素,生成一个列表,其中每个元素是对应于该元素索引的斐波那契数,例如8 位于索引 5这是重要的一步;它通过将fib 应用于每个数字来记忆fib,因此一旦强制特定索引处的值,就不必重新计算。
  • 然后!! 用于从列表中获取相应索引处的值。

【讨论】:

  • 我想说当“普通函数”fib 在其实现中使用fib_mem 时也有一点魔力。或者至少,这是技术的一部分。
  • @bradrn it memoizes fib by applying it to every number 为什么它会记忆?
  • 因为一旦它被应用到一个特定的数字上,编译器就知道该值在列表中的那个索引处,因此下次可以简单地在列表中查找该值。所以例如如果您请求了fib_mem 5,编译器会在列表中查找索引5,结果是它计算的值fib 5。下次您请求fib 5 时,编译器会再次在列表中查找索引5,但是该列表现在存储的不是[.., fib 5, ...],而是[..., 8, ...],因此它可以简单地查找先前计算的价值。
【解决方案2】:

如果您的意思是“为什么它是一个记忆功能”,the answer is因为它是CAF (constant applicative form)has a monomorphic type

【讨论】:

    猜你喜欢
    • 2018-05-02
    • 2010-12-28
    • 2015-12-07
    • 2014-08-29
    • 1970-01-01
    • 2011-04-26
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多