2013-03-17 68 views
3

我現在正在運行多個類似的模式,這種模式很容易出錯(拼寫錯誤可能會跳過一些緩存),並且對我看起來並不好。有沒有更好的方式來寫這樣的東西?緩存結果的更好模式

sum_with_cache' result cache ((p1,p2,p3,p4):partitions) = let 
     (cache_p1, sol1) = count_noncrossing' cache p1 
     (cache_p2, sol2) = count_noncrossing' cache_p1 p2 
     (cache_p3, sol3) = count_noncrossing' cache_p2 p3 
     (cache_p4, sol4) = count_noncrossing' cache_p3 p4 
    in sum_with_cache' (result+(sol1*sol2*sol3*sol4)) cache_p4 partitions 

那麼基本上N個可以更新緩存的操作呢?

我也寫的是這樣的:

process_with_cache' res cache _ [] = (cache, res) 
process_with_cache' res cache f (x:xs) = 
    let (new_cache, r) = f cache x 
    in process_with_cache' (r:res) new_cache f xs 
process_with_cache = process_with_cache' [] 

但看起來不很乾淨要麼。有沒有更好的方式來編寫這段代碼?

+1

如果你想在函數調用之間保持一個隱式狀態,看看'Control.Monad.State'。 – Koterpillar 2013-03-17 02:13:37

+0

你想製作備忘錄表嗎? http://www.haskell.org/haskellwiki/Memoization – 2013-03-17 11:29:41

回答

8

另一個類似的模式是,當你申請了一系列名爲隨機數:

let (x, rng') = random rng'' 
    (y, rng) = random rng' 
in (x^2 + y^2, rng) 

這正是使用狀態單子的時候是正確的方式去:

import Control.Monad.State 

對於所有隨機(RandomGen g) => g類型的數字發生器存在狀態單元State g,其隱式地顯示狀態:

do x <- state random 
    y <- state random 
    return (x^2 + y^2) 

state功能只是需要s -> (a, s)類型的函數,並把它變成State s a類型的計算,在這種情況下:

state :: (RandomGen g) => (g -> (a, g)) -> State g a 

您可以通過使用runStateevalStateexecState運行State計算:

runState (liftA2 (\x y -> x^2 + y^2) (state random) (state random)) 
     (mkStdGen 0)