(Monad m) => m a >> m b = m a >>= \_ -> m b
每次都会被>>是简版的>>=,这一点迷惑
其实心中要记住的是,说是简版,只能说是逻辑上忽略>>左边的action的值,而直接bind后面的monad,与其说是简版,还不如说是wrap版的,因为最后拆开里面还是一个>>=........
所以当一些Monad的实例,定义了复杂的>>=,那么>>的逻辑会远比用 do 语法糖的时候,来的复杂,
State就是如此,
每次看到rollDie的定义的时候,都会怀疑为什么state会被传递,一眼真的开不出来:
import Controll.Monad.Trans.State
import System.Random
type DiceState = State StdGen
rollDie :: DiceState Int
rollDie = do
gen <- get
let (value, gen') = randomR(1, 6) gen
put gen'
return value
如果改写成bind的话,
get >>= \gen ->
let (val, gen') = randomR(1, 6) gen
in put gen' >> return val
那么,再把最后一句的>>打开
put gen' >>= \_ -> return val
再套用State的>>=的定义:
state $ \st ->
let (xxx, st') = runState (put gen') st
in runState ((\_ -> return val) xxx) st'
可以看到,put gen'产生的state $ \st -> ((), st),由此获得的xxx会被 "\_" 忽略(本身就是空()),然后
runState ((\_ -> return val) xxx)
得到
\st'' -> (val, st'')
这样状态st'就被打包在最终生成的State的状态函数中,实现了传递
说实在的,自己也看不懂了,哇哈哈哈哈哈哈