2015-01-07 27 views
2

Haskell/Understanding monads/State有一个代码片段:在使用State Monad时理解符号“< - ”?

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

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

我们采取了伪随机发生器<-连同GET 。用状态覆盖monadic值(a,m a),将生成器绑定到状态。 (如果有疑问,请回顾上面的get和>>=的定义)。

我不明白:(1)generator对应第一个参数定义State? (2)为什么generator只是State这两个参数中的一个,而不是两个?当然,从上下文来看,答案很明显,但我不知道关于<-的具体规则。

据我所知,评估evalState rollDie (mkStdGen 600)时,get将被State (mkStdGen 0) (mkStdGen 0)这里所取代,并根据RWH的描述“<-翻出东西拿出单子”,事情没有(mkStdGen 0) (mkStdGen 0)

回答

5

我不完全确定你的问题的措辞,所以纠正我,如果我误解了。

语法语法<-的语法糖与重载的绑定操作符(>>=)之间存在等价关系。

do { a <- f ; m } ≡ f >>= \a -> do { m } 

所以,如果你是desugar的结合,它看起来像:

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

如果你理解了国家单子是如何工作的,在执行其线程在一个隐含参数围绕国家每个绑定(即>>=)。简化的实现可能是这样的:

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) 

所以,当专门到这个国家的具体单子绑定运营商的类型为:

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

功能get很简单,就是返回的状态作为参数的函数所以你可以检查它,所以它必须匹配它所在的单元的s类型。

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

谢谢!对不起,我几乎忘记了符号和'>> =''RWH'之间的等价关系,并没有完全理解“国家行为”作为一个整体! – abelard2008