2013-03-17 66 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)