Haskell语言学习笔记(9)State Monad
2017-02-08 14:57
701 查看
State Monad
旧的定义newtype State s a = State { runState :: s -> (a,s) } instance Monad (State s) where return x = State $ \s -> (x,s) (State h) >>= f = State $ \s -> let (a, newState) = h s (State g) = f a in g newState这里旧的定义是指API更改之前的定义,也就是Learn You a Haskell for Great Good!(中文版Haskell趣学指南)这本书中的定义。
newtype State s a = State { runState :: s -> (a,s) }
State 类型是个 newtype,也就是对现有类型的封装。该类型有两个类型参数:表示状态的类型参数 s 以及表示结果的类型参数 a。
State 类型封装的是一个状态转换函数:\s -> (a,s'),通过 runState 字段可以从 State 类型中取出这个函数。
该函数接收一个状态参数 s,经过计算(转换)之后返回一对值:计算结果 a 以及新的状态 s‘。
instance Monad (State s) where
State s 类型是 Monad 类型类的一个实例。
对比 Monad 类型类的定义,可知 return 函数的类型签名为:
return :: x -> State s x
大致相当于 x -> s -> (x,s)
而 bind 函数的类型签名为:
(>>=) :: State s a -> (a -> State s b) -> State s b
大致相当于 (s -> (a,s)) -> (a -> s -> (b,s)) -> (s -> (b,s))
return x = State $ \s -> (x,s)
return 函数将 x 封装进了状态转换函数,该函数把结果值设为 x,状态值 s 则保持不变。
(State h) >>= f = State $ \s ->
对比函数签名,可知 h 的类型为 s -> (a,s)。
而 f 的类型为 a -> State s b,大致相当于 a -> s -> (b,s)
bind 函数组合两个状态转换函数,最终结果仍然是个状态转换函数。
let (a, newState) = h s
这里将状态转换函数 h 应用于状态 s 上,得到结果值 a 以及新的状态值 newState。
(State g) = f a
根据 f 的类型 a -> State s b(大致相当于 a -> s -> (b,s)),可知 g 的类型为 s -> (b,s),这里 g 是第二个状态转换函数。
in g newState
这里将状态转换函数 g 应用于状态 newState 上,从而得出最终的结果值以及更新的状态值。
新的定义
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) } instance (Monad m) => Monad (StateT s m) where return a = StateT $ \s -> return (a, s) m >>= k = StateT $ \s -> do ~(a, s') <- runStateT m s runStateT (k a) s' instance (Functor m) => Functor (StateT s m) where fmap f m = StateT $ \s -> fmap (\ ~(a, s') -> (f a, s')) $ runStateT m s type State s = StateT s Identity根据新的定义,State 类型只是 StateT 类型的一个特例。
State Monad 函数
state f:将函数 f 封装进State Monad。runState m X:将函数 f 从State Monad中提取出来,调用 f X,同时返回结果值 a 和状态值 s。
evalState m X:将函数 f 从State Monad中提取出来,调用 f X,但是仅返回结果值 a。
execState m X:将函数 f 从State Monad中提取出来,调用 f X,但是仅返回状态值 s。
return X:结果值 a 设为 X,状态值 s 不变。
get:结果值 a 设为状态值 s,状态值 s 不变。
put X:状态值 s 设为 X,结果值 a 设为空。
modify f:状态值 s 设为 f s,结果值 a 设为空。
gets f:结果值 a 设为 f s,状态值 s 不变。
Prelude Control.Monad.State> runState (return 15) 1 (15,1) Prelude Control.Monad.State> runState get 1 (1,1) Prelude Control.Monad.State> runState (put 3) 1 ((),3) Prelude Control.Monad.State> runState (modify (+1)) 1 ((),2) Prelude Control.Monad.State> runState (gets (+1)) 1 (2,1) Prelude Control.Monad.State> evalState (gets (+1)) 1 2 Prelude Control.Monad.State> execState (gets (+1)) 1 1 Prelude Control.Monad.State> runState (do put 3; return 15) 1 (15,3) Prelude Control.Monad.State> runState (put 3 >> return 15) 1 (15,3)
随机数
Prelude Control.Monad.State System.Random> let r = state $ randomR (1, 10) Prelude Control.Monad.State System.Random> do {gen <- newStdGen; return $ evalState r gen} 4 Prelude Control.Monad.State System.Random> newStdGen >>= \gen -> return $ evalState r gen 3
阶乘
fact_state :: State Int Int fact_state = get >>= \x -> if x <= 1 then return 1 else (put (x - 1) >> fmap (*x) fact_state) factorial :: Int -> Int factorial = evalState fact_state Prelude Control.Monad.State.Strict Control.Applicative> factorial <$> [1..10] [1,2,6,24,120,720,5040,40320,362880,3628800]
斐波那契数列
fibs_state :: State (Int, Int, Int) Int fibs_state = get >>= \(x1, x2, n) -> if n == 0 then return x1 else (put (x2, x1+x2, n-1) >> fibs_state) fibonacci n = evalState fibs_state (0, 1, n) Prelude Control.Monad.State.Strict Control.Applicative> fibonacci <$> [1..10] [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
参考链接
Confusion over the State Monad code on “Learn you a Haskell”The State Monad: A Tutorial for the Confused?
Three Useful Monads
Where is the data constructor for 'State'?
Implementing factorial and fibonacci using State monad (as a learning exercise)
相关文章推荐
- Haskell语言学习笔记(25)MonadState, State, StateT
- Haskell语言学习笔记(10)Writer Monad
- Haskell语言学习笔记(17)MonadPlus
- Haskell语言学习笔记(30)MonadCont, Cont, ContT
- Haskell语言学习笔记(6)Monad
- Monad State in Haskell 笔记
- Haskell语言学习笔记(4)Functor
- Haskell语言学习笔记(12)Data.Function
- Haskell语言学习笔记(16)Alternative
- Haskell语言学习笔记(7)IO 与随机数
- Haskell语言学习笔记(24)MonadWriter, Writer, WriterT
- Haskell语言学习笔记(18)Traversable
- Haskell语言学习笔记(5)Applicative
- Haskell语言学习笔记(29)CPS
- Haskell语言学习笔记(27)Endo, Dual, Foldable
- Haskell语言学习笔记(31)ListT
- Haskell语言学习笔记(23)MonadReader, Reader, ReaderT
- Haskell语言学习笔记(8)Monoid
- Haskell语言学习笔记(14)Foldable
- Haskell语言学习笔记(15)Data.List