使用 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
在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