【问题标题】:Initial state of state monad and how it first gets passed alongstate monad 的初始状态以及它是如何传递的
【发布时间】:2014-08-09 11:05:16
【问题描述】:

我正在阅读有关 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)

【问题讨论】:

    标签: haskell state monads


    【解决方案1】:

    为简单起见,将State s a 视为一个函数,它接受初始状态s 并返回一个值和一个新状态(a , s),就像在wikibook 中一样:

    newtype State s a = S { runState :: s -> (s , a) }
    

    现在让我们使用rollDicePure = runState rollDicerollDicePure 是什么类型?鉴于runState 只删除了State 新类型,它应该是

    rollDicePure :: StdGen -> (Int, StdGen)
    

    所以runState(或evalState/execState)只是将有状态计算转换为一个简单函数,其参数是初始状态。

    如果你想知道get 是如何得到这个状态的,可以把它想象成

    getPure :: s -> (s, s)
    getPure st = (st, st)
    

    实际的定义比这要复杂一些,但语义是成立的。

    【讨论】:

    • 我认为你的这部分答案让一切都到位:“鉴于runState 只删除了State 新类型”。我仍然不习惯 State 类型实际上是一个函数,这就是参数的来源。
    猜你喜欢
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    相关资源
    最近更新 更多