【问题标题】:Generalized recursion doesn't work for Haskell memoization广义递归不适用于 Haskell 记忆
【发布时间】:2022-01-04 04:35:56
【问题描述】:

在阅读了几个资料后,我想出了以下 memo 函数,用于在 Haskell 中使用“广义递归”进行记忆。但它不起作用。为什么?!

fib f 0 = 1
fib f 1 = 1
fib f n = fib f (n - 1) + fib f (n - 2)

memo f n = fList !! n
  where fList = map (f (fList !!)) [0..]

没有记忆的递归运行

λ> fix fib 30
1346269
(1.65 secs, 962,135,992 bytes)

与“记忆化”版本所用的时间相同:

λ> memo fib 30
1346269
(1.62 secs, 962,141,192 bytes)

但是,以下工作:

fibMemoDirect n = fibList !! n
  where fibList = map fib [0..]
        fib 0 = 1
        fib 1 = 1
        fib n = fibList !! (n - 1) + fibList !! (n - 2)
λ> fibMemoDirect 30
1346269
(0.01 secs, 93,728 bytes)

考虑到两者都使用 CAF,为什么上面的 memo fib 的工作速度不如 fibMemoDirect

来源:

【问题讨论】:

  • !!O(n),与其他语言中的 O(1) 不同。不过我不确定这是唯一的问题。
  • @user1984,是的,它确实不是最理想的。但是fibMemoDirect 也使用!! 并且工作速度快了约200 倍。
  • 为了确保它们渐近地不同并且差异不仅仅是一些恒定的,我建议运行 (30 * 5) 和 (30 * 10) 的代码,看看时间是如何变化的。
  • fibMemoDirect 3000 在 0.13 秒内完成。 memo fib 3000 永远不会完成。
  • 您的 fib 函数是直接递归的,不使用它的 f 参数。所以你也可以在没有fix 的情况下运行它,你会在同一时间得到相同的结果。这就是为什么用memo 替换fix 没有区别。

标签: haskell memoization


【解决方案1】:

你几乎得到它,但你的第三行需要

fib f n = f (n-1) + f (n-2)

...否则你甚至没有使用f,而只是编写一个正常的、递归的、指数斐波那契函数。

【讨论】:

    猜你喜欢
    • 2018-09-08
    • 2019-11-29
    • 1970-01-01
    • 2017-06-25
    • 2012-11-12
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多