我有一个模拟,其中包含对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
应该记住e
。 e
的类型在这里是存在的类型。
但这迫使我重新计算每个A
的所有值B
,这同样糟糕,我无法保存e
s,这是函数的私有。
如何独立记忆2个参数?
答案 0 :(得分:1)
您需要一个同时记忆a
和b
的功能:
f12 a b = ...
in \c -> ...
如果您想要记住a
而不是b
,则可以使用f1 a
,当您想要记忆时,请使用f12 a b
。
在f1
和f12
之间分享一些实现当然会很好。但是,只有通过使用预先计算结果取代原始值的私有函数,才能实现此目的:
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;