只是学习如何更直观地掌握单子和转换器;很多看起来很明显的事情对我来说仍然有点棘手哈哈。
所以我有一个存在于Rand
monad 中的计算,但在其中,还有另一个“子计算”(或多个)存在于一个ST
monad(或State
monad,对于所有重要的事情......ST
仅用于性能但我认为State
有效)在这种情况下也是如此)。
整个计算不需要在ST
monad 内部......并且这个子计算将以不同的起始状态多次调用,所以我不想将整个事情强制转换为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
单子,应该是什么类型?我想我可能想要使用的返回类型RandT g (ST s) ()
,但我如何使它适合 in 中预期的runST
类型subComp
?