モナドとトランスフォーマーをより深く直感的に理解する方法を学んでいます。当たり前のように思える多くのことは、私にはまだちょっとトリッキーです(笑)。
したがって、Rand
モナド内に存在する計算がありますが、その内部には、モナド内に存在する別の「サブ計算」(または複数)がありますST
(またはState
モナド、それはすべて重要です...ST
パフォーマンスのためだけですが、うまくいくと思いState
ますこのコンテキストでも同様です)。
計算全体がモナド内にある必要はありませんST
...そして、このサブ計算は異なる開始状態で複数回呼び出されるので、全体を に強制したくありませんST
(それが慣用的な方法でない限り) .
ランダム性がない場合、構造は次のようになります。
main = print mainComp
mainComp :: Int
mainComp = otherComp + (subComp 1) + (subComp 2)
subComp :: Int -> Int
subComp n = runST $ do
-- generate state based on n
-- ...
replicateM_ 100 mutateState
-- ...
-- eventually returns an ST s Int
mutateState :: ST s ()
mutateState = -- ...
基本的に物事はうまく機能し、 と には完全な参照透過性がmainComp
ありsubComp
ます。
これは私がこれまで使ってきた方法ですRand
-
main = (evalRandIO mainComp) >>= print
mainComp :: (RandomGen g) => Rand g Int
mainComp = do
subResultA <- subComp 1
subResultB <- subComp 2
return $ otherComp + subResultA + subResultB
subComp :: (RandomGen g) => Int -> Rand g Int
subComp = return $ runST $ do -- is this ok to just throw in return?
-- generate state based on n
-- ...
replicateM_ 100 mutateState
-- ...
-- eventually returns an ST s Int (??)
mutateState :: ??
mutateState = ??
ランダムシードとその中でモナドmutateState
を使用したい場合、 の型は何ですか? Rand
の戻り値の型を使用したいと思うかもしれませんが、それをinRandT g (ST s) ()
で期待される型に適合させるにはどうすればよいですか?runST
subComp