我有一個計算量很大的向量,我想在函式內部進行索引,但由于該表從未在其他任何地方使用,我不想傳遞向量,而是像記憶函式一樣訪問預先計算的值。
這個想法是:
cachedFunction :: Int -> Int
cachedFunction ix = table ! ix
where table = <vector creation>
我注意到的一個方面是我見過的所有記憶示例都處理遞回,即使使用表來記憶,表中的值也依賴于表中的其他值。這不是我的情況,計算值是使用試錯法找到的,但每個元素都獨立于另一個元素。
如何在函式中實作快取表?
uj5u.com熱心網友回復:
你幾乎是對的。問題是,你的例子基本上是這樣的:
┌────────────────────────────────┐
cachedFunction ix = │ table ! ix │
│where table = <vector creation> │
└────────────────────────────────┘
ietable不在不同的ix. 這與它碰巧不依賴的事實無關ix(這在這個例子中很明顯,但不是一般情況下)。因此,將它保存在記憶體中是沒有用的,而 Haskell 不會這樣做。
但是您可以通過將ix引數與其關聯的 where 塊一起拉入結果中來更改它:
cachedFunction = \ix -> table ! ix
where table = <vector creation>
IE
┌────────────────────────────────┐
cachedFunction = │ \ix -> table ! ix │
│where table = <vector creation> │
└────────────────────────────────┘
或更短,
cachedFunction = (<vector creation> !)
在這種形式中,cachedFunction是一個常量應用形式,即盡管具有函式型別,但編譯器將其視為常量值。它不是您可以評估為正常形式的值,但是當使用它來評估內部的 lambda 函式時,它將保持同一個表(不能依賴于ix;它不在范圍內)。
uj5u.com熱心網友回復:
根據這個答案,GHC 永遠不會重新計算在模塊頂層宣告的值。因此,通過將您table提升到模塊的頂層,它將在第一次需要時被延遲評估(一次),然后再也不會被請求。我們可以直接看到行為Debug.Trace(為簡單起見,示例使用簡單的整數而不是向量)
import Debug.Trace
cachedFunction :: Int -> Int
cachedFunction ix = table ix
table = traceShow "Computed" 0
main :: IO ()
main = do
print 0
print $ cachedFunction 1
print $ cachedFunction 2
輸出:
0
"Computed"
1
2
我們看到直到table被呼叫才cachedFunction計算它,并且它只計算一次,即使我們呼叫cachedFunction了兩次。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/528497.html
標籤:哈斯克尔记忆
