独立记忆参数

时间:2015-03-22 12:23:49

标签: haskell memoization

我有一个模拟,其中包含对type F = A -> B -> C -> D函数的大量调用,其中A .. D是具体类型。

A类型的对象具有中等生命周期。 (它是codegolf's ratrace的基因组。)

最昂贵的计算来自参数A。我可以像这样容易地回忆:

f1 :: F
f1 a = let expensive = trace "expensive computation!" $ expensiveComputation a
        in \b c -> expensive

并通过部分应用保留一些预处理的expensive值:

preProz :: [B -> C -> D]
preProz = [f1 [], f1 [False], f2 []]

跟踪表明preProz <*> [[],[[]]] <*> [1,2]不会重新计算我喜欢的值。

现在我发现我的一些F也会受益于预处理B。此预处理与A 独立,事实上,这样的记忆没有任何好处

f2 a = let expensive = trace "expensive computation!" $ expensiveComputation a
        in \b -> let dear = trace "expensive computation!" $ expensiveComputation b
                  in expensive + dear

因为dear被重新计算,即使b相等。

我需要的是:

(B -> e) -> A -> e -> C -> D

应该记住ee的类型在这里是存在的类型。 但这迫使我重新计算每个A的所有值B,这同样糟糕,我无法保存e s,这是函数的私有。

如何独立记忆2个参数?

1 个答案:

答案 0 :(得分:1)

您需要一个同时记忆ab的功能:

f12 a b = ...
    in \c -> ...

如果您想要记住a而不是b,则可以使用f1 a,当您想要记忆时,请使用f12 a b

f1f12之间分享一些实现当然会很好。但是,只有通过使用预先计算结果取代原始值的私有函数,才能实现此目的:

f1 a = privateA (precomputeA a)
f12 a b = privateAB (precomputeA a) (precomputeB b)
privateA a' b = privateAB a' (precomputeB b)
private AB a' b' c = ...

如果b的预计算取决于a的预计算,则:

f1 a = privateA (precomputeA a)
f12 a b = let a' = precomputeA a in privateAB a' (precomputeB a' b)
privateA a' b = privateAB a' (precomputeB a' b)
private AB a' b' c = ...

我故意不使用功能组合和eta-reduction,以使事情更清晰。我还遗漏了您可能想用来控制评估时间的任何严格注释。

或许回忆起来并不是一个非常正确的术语。你的意思是&#34;部分应用程序也有一些预计算。&#34;