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' []

但这看起来也不是很干净。有没有更好的方法来编写这段代码?

4

1 回答 1

8

另一个类似的模式是当您请求一系列命名随机数时:

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

这正是使用 state monad 的正确方法:

import Control.Monad.State

对于所有类型的随机数生成器,(RandomGen g) => g都有一个状态 monad 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

您可以State使用runState或运行计算:evalStateexecState

runState (liftA2 (\x y -> x^2 + y^2) (state random) (state random))
         (mkStdGen 0)
于 2013-03-17T03:24:06.423 回答