【问题标题】:How can I factor this Haskell expression to avoid repeated computation?如何考虑这个 Haskell 表达式以避免重复计算?
【发布时间】:2010-07-10 13:22:32
【问题描述】:

我有这个函数(产生斐波那契数列):

unfoldr (\(p1, p2) -> Just (p1+p2, (p1+p2, p1)) ) (0, 1)

在这里,我注意到一个重复的表达式p1+p2,我想将其分解为只计算一次。加法本身并不是一个昂贵的计算,而是一个更通用的版本:

unfoldr (\(p1, p2) -> Just (f p1 p2, (f p1 p2, p1)) ) (0, 1)
    where f = arbitrary, possibly time-consuming function

在上述情况下,f p1 p2 被计算了两次(除非有一些我不知道的神奇编译器优化),如果f 需要大量计算,这可能会造成性能瓶颈。我不能将f p1 p2 分解为where,因为p1p2 不在范围内。分解此表达式以便 f 只计算一次的最佳方法是什么?

【问题讨论】:

    标签: haskell performance evaluation


    【解决方案1】:
    unfoldr (\(p1, p2) -> let x = f p1 p2 in Just (x, (x, p1)) ) (0, 1)
        where f = arbitrary, possibly time-consuming function
    

    【讨论】:

    • 谢谢!感谢您抽出宝贵的时间来解决这样的初学者问题(:
    【解决方案2】:

    Control.Arrow 中有(&&&) 可以用在这样的地方:

    unfoldr (\(p1,p2) -> (Just . (id &&& flip (,) p1)) (p1+p2)) (0,1)
    

    甚至:

    unfoldr (Just . (fst &&& id) . (uncurry (+) &&& fst)) (0,1)
    

    在您的示例中,p1+p2 实际上是下一个p1,因此您可以像这样重写它

    tail (unfoldr (\(p1, p2) -> Just (p1, (p1+p2, p1)) ) (0, 1))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-11
      • 2013-05-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多