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

もう 1 つの同様のパターンは、一連の名前付き乱数を要求する場合です。

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関数は単純に type の関数を取り、それs -> (a, s)を type の計算に変換しますState s a。この場合:

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

、またはStateを使用して計算を実行できます。runStateevalStateexecState

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