我正在阅读有关State monad的内容,在编写下面的代码后,我无法理解初始状态(mkStdGen 42
)是如何传递到rollDice
函数的?
get
如何处理该初始值?
我理解rollDice
函数是如何工作的,但我无法想象初始状态如何被提升到monad中。
import Control.Monad.Trans.State
import System.Random
rollDice :: State StdGen Int
rollDice = do
generator <- get
let (x, s) = randomR (1,6) generator
put s
return x
main :: IO ()
main = putStrLn . show $ evalState rollDice (mkStdGen 42)
答案 0 :(得分:4)
为了简单起见,请将State s a
视为一个函数,它采用初始状态s
并返回一个值和一个新状态(a , s)
,就像在wikibook中一样:
newtype State s a = S { runState :: s -> (s , a) }
现在让我们使用rollDicePure = runState rollDice
。什么是rollDicePure
类型?鉴于runState
仅删除State
新类型,它应该是
rollDicePure :: StdGen -> (Int, StdGen)
所以runState
(或evalState
/ execState
)只需将有状态计算转换为一个简单函数,其参数为初始状态。
如果您想知道get
如何获得此状态,请将其视为
getPure :: s -> (s, s)
getPure st = (st, st)
实际定义比这更复杂,但语义仍然存在。