使用 State Monad 时理解符号“<-”?

Understanding the symbol "<-" when using State Monad?

Haskell/Understanding monads/State中有一段代码:

type GeneratorState = State StdGen
rollDie :: GeneratorState Int
rollDie = do generator <- get
         let (value, newGenerator) = randomR (1,6) generator
         put newGenerator
         return value

关于上面第三行的符号<-,有一个解释:

我们用<-结合get取出伪随机生成器。 get 用状态覆盖 monadic 值(m a 中的 a),将生成器绑定到状态。 (如果有疑问,请回忆上面的 get 和 >>= 的定义)。

不明白:(1)generator对应定义的第一个类型参数State? (2)为什么generator只是State的两个参数之一,而不是两个?当然,从上下文来看,答案是显而易见的,但我不知道<-.

的具体规则

据我所知,在评估 evalState rollDie (mkStdGen 600) 时,get 将被替换为 State (mkStdGen 0) (mkStdGen 0) ,并且根据 RWH 的描述“<- 从 monad 中提取内容” , 这里的东西不是(mkStdGen 0) (mkStdGen 0) ?

我不是很确定你问题的措辞,如果我理解有误,请纠正我。

do-notation 语法的语法糖 <- 和重载绑定运算符 (>>=).

之间存在等价关系
do { a <- f ; m } ≡ f >>= \a -> do { m }

因此,如果您要对绑定进行脱糖处理,它将看起来像:

rollDie' :: GeneratorState Int
rollDie' =
  get >>= \generator ->
    let (value, newGenerator) = randomR (1,6) generator in
    put newGenerator >>= \_ ->
      return value

如果您了解 State monad 的工作原理,在实现中它会在每个绑定的隐式参数中围绕状态进行线程化(即 >>=)。简化的实现可能如下所示:

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

instance Monad (State s) where
  return a = State $ \s -> (a, s)

  State act >>= k = State $ \s ->
    let (a, s') = act s
    in runState (k a) s'

get :: State s s
get = State $ \s -> (s, s)

put :: s -> State s ()
put s = State $ \_ -> ((), s)

因此绑定运算符专门用于此特定状态 monad 时具有以下类型:

(>>=) :: State s a -> (a -> State s b) -> State s b

函数 get 只是 returns 状态作为参数的函数,因此您可以检查它,因此它必须匹配它所在的 monad 的 s 类型英寸

--           +--- State
--           | +- Return value (inner state)
--           | |
get :: State s s