Haskell语言学习笔记(37)RWS, RWST
RWST Monad转换器
RWST Monad转换器是将 ReaderT, WriterT 以及 StateT 这三个Monad转换器的功能集于一体的产物。
newtype RWST r w s m a = RWST { runRWST :: r -> s -> m (a, s, w) }
instance (Monoid w, Monad m) => Monad (RWST r w s m) where
return a = RWST $ \ _ s -> return (a, s, mempty)
m >>= k = RWST $ \ r s -> do
~(a, s', w) <- runRWST m r s
~(b, s'',w') <- runRWST (k a) r s'
return (b, s'', w `mappend` w')
- newtype RWST r w s m a = RWST { runRWST :: r -> s -> m (a, s, w) }
RWST 类型是个 newtype,也就是对现有类型的封装。该类型有五个类型参数:内部 Monad 类型参数 m,环境类型参数 r,输出信息类型参数 w,状态类型参数 s 以及结果类型参数 a。
RWST r w s m a 类型封装了一个带环境和状态的转换函数 \r s -> m (a, s', w),通过 runRWST 字段可以从 RWST 类型中取出这个函数。
该函数接收一个环境参数 r 和一个状态参数 s,经过计算(转换)之后返回一个封装在内部 Monad m 中的三元组:输出信息 w,计算结果 a 以及新的状态 s'。 - instance (Monoid w, Monad m) => Monad (RWST r w s m) where
如果 w 是个 Monoid 并且 m 是个 Monad,那么 RWST r w s m 也是一个 Monad。
对比 Monad 类型类的定义,可知 return 函数的类型签名为:
return :: a -> RWST r w s m a
大致相当于 a -> r -> s -> m (a,s,w)
而 bind 函数的类型签名为:
(>>=) :: RWST r w s m a -> (a -> RWST r w s m b) -> RWST r w s m b
大致相当于 (r -> s -> m (a,s,w)) -> (a -> r -> s -> m (b,s,w)) -> (r -> s -> m (b,s,w)) - return a = RWST $ \ _ s -> return (a, s, mempty)
return 函数将 a 封装进了带环境和状态的转换函数,该函数首先把结果值设为 a,状态值 s 保持不变,输出信息为 mempty,然后把这个三元组封装进了内部 Monad m。
这里左侧的 return 是 StateT 这个 Monad 的 return,而右侧的 return 是内部 Monad m 的 return。 - m >>= k = RWST $ \ r s -> do
对比函数签名,可知 m 的类型为 RWST r w s m a,大致相当于 r -> s -> m (a,s,w)。
而 k 的类型为 a -> RWST r w s m b,大致相当于 a -> r -> s -> m (b,s,w)。
bind 操作符组合两个带环境和状态的转换函数,最终结果仍然是个带环境和状态的转换函数。 - ~(a, s', w) <- runRWST m r s
这里首先利用 runRWST 字段取出 RWST Monad m 中封装的转换函数,然后将它应用于环境参数 r 和状态值 s 之上,得到输出信息 w,结果值 a 以及新的状态值 s'。
runRWST m 让 m 脱离了 RWST 这个 Monad,而 <- 运算符让 runRWST m r s 脱离了内部 Monad m。 - ~(b, s'',w') <- runRWST (k a) r s'
根据 k 的类型 a -> RWST r w s m b,可知 k a 的类型为 RWST r w s m b,即 k a 也是一个 RWST Monad。
这里再次利用 runRWST 字段取出 RWST Monad (k a) 中封装的转换函数,然后将它应用于环境参数 r 和新的状态值 s' 之上,得到新的输出信息 w’,新的结果值 b 以及最终状态值 s''。
runRWST (k a) 让 k a 脱离了 RWST 这个 Monad,而 <- 运算符让 runRWST (k a) r s' 脱离了内部 Monad m。 - return (b, s'', w `mappend` w')
最后将状态值设为最终状态值 s'',结果值设为新的结果值 b,输出信息则设为原来的输出信息 w 与新的输出信息 w' 联结后的值。
return 函数让这个三元组重新进入内部 Monad m 之中。
证明 RWST r w s m 符合Monad法则:
1. return a >>= f ≡ f a
return a >>= f
≡ (RWST $ \ _ s -> return (a, s, mempty)) >>= f
≡ RWST $ \ r s -> do {~(a, s', w) <- runRWST (RWST $ \ _ s -> return (a, s, mempty)) r s; ~(b, s'',w') <- runRWST (f a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- (\ _ s -> return (a, s, mempty)) r s; ~(b, s'',w') <- runRWST (f a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- return (a, s, mempty); ~(b, s'',w') <- runRWST (f a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- runRWST (f a) r s; return (b, s'', empty <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- runRWST (f a) r s; return (b, s'', w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- runRWST (f a) r s; return (b, s'', w')}
≡ RWST $ \ r s -> runRWST (f a) r s
≡ RWST $ runRWST (f a)
≡ f a
2. m >>= return ≡ m
m = RWST (\r s -> n (a, s', w))
m >>= return
≡ RWST (\r s -> n (a, s', w)) >>= return
≡ RWST $ \ r s -> do {~(a, s', w) <- runRWST (RWST (\r s -> n (a, s', w))) r s; ~(b, s'',w') <- runRWST (RWST $ \ _ s -> return (a, s, mempty)) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- (\r s -> n (a, s', w)) r s; ~(b, s'',w') <- (\ _ s -> n (a, s, mempty)) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- n (a, s', w)); ~(b, s'',w') <- (\ _ s -> n (a, s, mempty)) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- (\ _ s -> n (a, s, mempty)) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- n (a, s', mempty); return (b, s'', w <> w')}
≡ RWST $ \ r s -> n (a, s', w <> empty)
≡ RWST $ \ r s -> n (a, s', w)
≡ m
3. (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
假设 m = RWST (\r s -> n (a1, s1, w1)), f a1 = RWST (\r s1 -> n (a2, s2, w2)), g a2 = RWST (\r s2 -> n (a3, s3, w3))
(m >>= f) >>= g
≡ (RWST $ \ r s -> do {~(a, s', w) <- runRWST m r s; ~(b, s'',w') <- runRWST (f a) r s'; return (b, s'', w <> w')}) >> g
≡ RWST $ \ r s -> do {~(a, s', w) <- runRWST (RWST $ \ r s -> do {~(a, s', w) <- runRWST m r s; ~(b, s'',w') <- runRWST (f a) r s'; return (b, s'', w <> w')}) r s; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- do {~(a, s', w) <- runRWST (RWST (\r s -> n (a1, s1, w1))) r s; ~(b, s'',w') <- runRWST (f a) r s'; return (b, s'', w <> w')}; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- do {~(a, s', w) <- (\r s -> n (a1, s1, w1)) r s; ~(b, s'',w') <- runRWST (f a) r s'; return (b, s'', w <> w')}; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- do {~(a, s', w) <- n (a1, s1, w1); ~(b, s'',w') <- runRWST (f a) r s'; return (b, s'', w <> w')}; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- do {~(b, s'',w') <- runRWST (f a1) r s1; return (b, s'', w1 <> w')}; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- do {~(b, s'',w') <- runRWST (RWST (\r s1 -> n (a2, s2, w2))) r s1; return (b, s'', w1 <> w')}; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- do {~(b, s'',w') <- n (a2, s2, w2); return (b, s'', w1 <> w')}; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- n (a2, s2, w1 <> w2); ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- runRWST (g a2) r s2; return (b, s'', (w1 <> w2) <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- runRWST (RWST (\r s2 -> n (a3, s3, w3))) r s2; return (b, s'', (w1 <> w2) <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- (\r s2 -> n (a3, s3, w3)) r s2; return (b, s'', (w1 <> w2) <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- n (a3, s3, w3); return (b, s'', (w1 <> w2) <> w')}
≡ RWST $ \ r s -> n (a3, s3, (w1 <> w2) <> w3)
m >>= (\x -> f x >>= g)
≡ RWST $ \ r s -> do {~(a, s', w) <- runRWST m r s; ~(b, s'',w') <- runRWST ((\x -> f x >>= g) a) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- runRWST m r s; ~(b, s'',w') <- runRWST (f a >>= g) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- runRWST m r s; ~(b, s'',w') <- runRWST (RWST $ \ r s -> do {~(a, s', w) <- runRWST (f a) r s; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- runRWST (RWST (\r s -> n (a1, s1, w1))) r s; ~(b, s'',w') <- runRWST (RWST $ \ r s -> do {~(a, s', w) <- runRWST (f a) r s; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- (\r s -> n (a1, s1, w1)) r s; ~(b, s'',w') <- (\ r s -> do {~(a, s', w) <- runRWST (f a) r s; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(a, s', w) <- n (a1, s1, w1); ~(b, s'',w') <- (\ r s -> do {~(a, s', w) <- runRWST (f a) r s; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}) r s'; return (b, s'', w <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- (\ r s -> do {~(a, s', w) <- runRWST (f a1) r s; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}) r s1; return (b, s'', w1 <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- (\ r s -> do {~(a, s', w) <- runRWST (RWST (\r s1 -> n (a2, s2, w2))) r s; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}) r s1; return (b, s'', w1 <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- do {~(a, s', w) <- runRWST (RWST (\r s1 -> n (a2, s2, w2))) r s1; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}; return (b, s'', w1 <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- do {~(a, s', w) <- (\r s1 -> n (a2, s2, w2)) r s1; ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}; return (b, s'', w1 <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- do {~(a, s', w) <- n (a2, s2, w2); ~(b, s'',w') <- runRWST (g a) r s'; return (b, s'', w <> w')}; return (b, s'', w1 <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- do {~(b, s'',w') <- runRWST (g a2) r s2; return (b, s'', w2 <> w')}; return (b, s'', w1 <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- do {~(b, s'',w') <- runRWST (RWST (\r s2 -> n (a3, s3, w3))) r s2; return (b, s'', w2 <> w')}; return (b, s'', w1 <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- do {~(b, s'',w') <- (\r s2 -> n (a3, s3, w3)) r s2; return (b, s'', w2 <> w')}; return (b, s'', w1 <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- do {~(b, s'',w') <- n (a3, s3, w3); return (b, s'', w2 <> w')}; return (b, s'', w1 <> w')}
≡ RWST $ \ r s -> do {~(b, s'',w') <- n (a3, s3, w2 <> w3); return (b, s'', w1 <> w')}
≡ RWST $ \ r s -> n (a3, s3, w1 <> (w2 <> w3))
根据 Monoid 的法则:(x <> y) <> z = x <> (y <> z)
RWST $ \ r s -> n (a3, s3, (w1 <> w2) <> w3)
≡ RWST $ \ r s -> n (a3, s3, w1 <> (w2 <> w3))
lift 函数
instance (Monoid w) => MonadTrans (RWST r w s) where
lift m = RWST $ \ _ s -> do
a <- m
return (a, s, mempty)
证明 RWST 中 lift 函数的定义符合 lift 的法则。
1. lift . return ≡ return
lift . return $ a
≡ lift (m a)
≡ RWST $ \ _ s -> do {a <- m a; return (a, s, mempty)}
≡ RWST $ \ _ s -> m (a, s, mempty)
≡ return a
2. lift (m >>= f) ≡ lift m >>= (lift . f)
假设 m = n a 并且 f a = n b
于是 m >>= f = n b
lift (m >>= f)
≡ lift (n b)
≡ RWST $ \ _ s -> do {a <- n b; return (a, s, empty)}
≡ RWST $ \ _ s -> n (b, s, empty)
lift m >>= (lift . f)
≡ (RWST $ \ _ s -> do {a <- n a; return (a, s, empty)}) >>= (\x -> RWST $ \ _ s -> do {a <- f x; return (a, s, empty)})
≡ (RWST $ \ _ s -> n (a, s, empty)) >>= (\x -> RWST $ \ _ s -> do {a <- f x; return (a, s, empty)})
≡ RWST $ \ _ s -> do {~(a, s', w) <- runRWST (RWST $ \ _ s -> n (a, s, empty)) r s; ~(b, s'',w') <- runRWST ((\x -> RWST $ \ _ s -> do {a <- f x; return (a, s, empty)} a) r s';return (b, s'', w <> w')}
≡ RWST $ \ _ s -> do {~(a, s', w) <- (\ _ s -> n (a, s, empty)) _ s; ~(b, s'',w') <- runRWST (RWST $ \ _ s -> do {a <- f a; return (a, s, empty)}) _ s';return (b, s'', w <> w')}
≡ RWST $ \ _ s -> do {~(a, s', w) <- n (a, s, empty); ~(b, s'',w') <- do {a <- n b; return (a, s', empty)};return (b, s'', w <> w')}
≡ RWST $ \ _ s -> do {~(a, s', w) <- n (a, s, empty); ~(b, s'',w') <- n (b, s', empty);return (b, s'', empty <> w')}
≡ RWST $ \ _ s -> do {~(b, s'',w') <- n (b, s, empty);return (b, s'', empty <> w')}
≡ RWST $ \ _ s -> n (b, s, empty)
RWST 是 Functor 也是 Applicative
instance (Functor m) => Functor (RWST r w s m) where
fmap f m = RWST $ \ r s ->
fmap (\ ~(a, s', w) -> (f a, s', w)) $ runRWST m r s
instance (Monoid w, Functor m, Monad m) => Applicative (RWST r w s m) where
pure a = RWST $ \ _ s -> return (a, s, mempty)
RWST mf <*> RWST mx = RWST $ \ r s -> do
~(f, s', w) <- mf r s
~(x, s'',w') <- mx r s'
return (f x, s'', w `mappend` w')
RWST 是 Alternative 也是 MonadPlus
instance (Monoid w, Functor m, MonadPlus m) => Alternative (RWST r w s m) where
empty = RWST $ \ _ _ -> mzero
RWST m <|> RWST n = RWST $ \ r s -> m r s `mplus` n r s
instance (Monoid w, MonadPlus m) => MonadPlus (RWST r w s m) where
mzero = RWST $ \ _ _ -> mzero
RWST m `mplus` RWST n = RWST $ \ r s -> m r s `mplus` n r s
RWST Monad转换器的函数
evalRWST :: (Monad m) => RWST r w s m a -> r -> s -> m (a, w)
evalRWST m r s = do
~(a, _, w) <- runRWST m r s
return (a, w)
execRWST :: (Monad m) => RWST r w s m a -> r -> s -> m (s, w)
execRWST m r s = do
~(_, s', w) <- runRWST m r s
return (s', w)
mapRWST :: (m (a, s, w) -> n (b, s, w')) -> RWST r w s m a -> RWST r w' s n b
mapRWST f m = RWST $ \ r s -> f (runRWST m r s)
withRWST :: (r' -> s -> (r, s)) -> RWST r w s m a -> RWST r' w s m a
withRWST f m = RWST $ \ r s -> uncurry (runRWST m) (f r s)
-- Reader operations
reader :: (Monoid w, Monad m) => (r -> a) -> RWST r w s m a
reader = asks
ask :: (Monoid w, Monad m) => RWST r w s m r
ask = RWST $ \ r s -> return (r, s, mempty)
local :: (r -> r) -> RWST r w s m a -> RWST r w s m a
local f m = RWST $ \ r s -> runRWST m (f r) s
asks :: (Monoid w, Monad m) => (r -> a) -> RWST r w s m a
asks f = RWST $ \ r s -> return (f r, s, mempty)
-- Writer operations
writer :: (Monad m) => (a, w) -> RWST r w s m a
writer (a, w) = RWST $ \ _ s -> return (a, s, w)
tell :: (Monad m) => w -> RWST r w s m ()
tell w = RWST $ \ _ s -> return ((),s,w)
listen :: (Monad m) => RWST r w s m a -> RWST r w s m (a, w)
listen m = RWST $ \ r s -> do
~(a, s', w) <- runRWST m r s
return ((a, w), s', w)
listens :: (Monad m) => (w -> b) -> RWST r w s m a -> RWST r w s m (a, b)
listens f m = RWST $ \ r s -> do
~(a, s', w) <- runRWST m r s
return ((a, f w), s', w)
pass :: (Monad m) => RWST r w s m (a, w -> w) -> RWST r w s m a
pass m = RWST $ \ r s -> do
~((a, f), s', w) <- runRWST m r s
return (a, s', f w)
censor :: (Monad m) => (w -> w) -> RWST r w s m a -> RWST r w s m a
censor f m = RWST $ \ r s -> do
~(a, s', w) <- runRWST m r s
return (a, s', f w)
-- State operations
state :: (Monoid w, Monad m) => (s -> (a,s)) -> RWST r w s m a
state f = RWST $ \ _ s -> let (a,s') = f s in return (a, s', mempty)
get :: (Monoid w, Monad m) => RWST r w s m s
get = RWST $ \ _ s -> return (s, s, mempty)
put :: (Monoid w, Monad m) => s -> RWST r w s m ()
put s = RWST $ \ _ _ -> return ((), s, mempty)
modify :: (Monoid w, Monad m) => (s -> s) -> RWST r w s m ()
modify f = RWST $ \ _ s -> return ((), f s, mempty)
gets :: (Monoid w, Monad m) => (s -> a) -> RWST r w s m a
gets f = RWST $ \ _ s -> return (f s, s, mempty)
以下是针对 RWST 整体的函数:
- evalRWST :: (Monad m) => RWST r w s m a -> r -> s -> m (a, w)
evalRWST函数在计算之后返回结果和输出信息。 - execRWST :: (Monad m) => RWST r w s m a -> r -> s -> m (s, w)
execRWST函数在计算之后返回状态和输出信息。 - mapRWST :: (m (a, s, w) -> n (b, s, w')) -> RWST r w s m a -> RWST r w' s n b
mapRWST函数在计算之后针对结果三元组调用函数f。 - withRWST :: (r' -> s -> (r, s)) -> RWST r w s m a -> RWST r' w s m a
evalRWST函数在计算之前针对环境参数和状态参数调用函数f。
以下是涉及 Reader 操作的函数:
- reader :: (Monoid w, Monad m) => (r -> a) -> RWST r w s m a
reader函数与asks同义。 - ask :: (Monoid w, Monad m) => RWST r w s m r
ask函数返回环境参数和状态参数。(输出信息为空) - local :: (r -> r) -> RWST r w s m a -> RWST r w s m a
local f m 通过调用函数 f 局部性地修改环境参数 r,然后调用RWST Monad m 中封装的函数。 - asks :: (Monoid w, Monad m) => (r -> a) -> RWST r w s m a
asks f 通过调用函数f修改环境参数,然后返回环境参数和状态参数。(输出信息为空)
Prelude Control.Monad.RWS> runRWST ask "abc" "!!!"
("abc","!!!",())
Prelude Control.Monad.RWS> runRWST (local (++ "def") ask) "abc" "!!!"
("abcdef","!!!",())
Prelude Control.Monad.RWS> runRWST (withRWST (\r s -> (length r, s)) ask) "abc" "!!!"
(3,"!!!",())
Prelude Control.Monad.RWS> runRWST (mapRWST (++ [("def","***",())]) ask) "abc" "!!!"
[("abc","!!!",()),("def","***",())]
Prelude Control.Monad.RWS> runRWST (asks (++ "def")) "abc" "!!!"
("abcdef","!!!",())
Prelude Control.Monad.RWS> runRWST (local (++ "def") ask >> ask) "abc" "!!!"
("abc","!!!",())
Prelude Control.Monad.RWS> let ioTask = do {a <- ask; liftIO $ print a}
Prelude Control.Monad.RWS> :t ioTask
ioTask :: (MonadReader a m, MonadIO m, Show a) => m ()
Prelude Control.Monad.RWS> runRWST ioTask "abc" "!!!"
"abc"
((),"!!!",())
Prelude Control.Monad.RWS> runRWST (local (++ "def") ioTask) "abc" "!!!"
"abcdef"
((),"!!!",())
Prelude Control.Monad.RWS> runRWST (local (++ "def") ioTask >> ioTask) "abc" "!!!"
"abcdef"
"abc"
((),"!!!",())
以下是涉及 Writer 操作的函数:
- writer :: (Monad m) => (a, w) -> RWST r w s m a
writer函数将结果值和输出信息封装进RWST Monad内带环境和状态的函数之中, - tell :: (Monad m) => w -> RWST r w s m ()
tell w 记录输出信息 w。(结果值为空)(状态值不变) - listen :: (Monad m) => RWST r w s m a -> RWST r w s m (a, w)
listen m 在计算之后将结果值设置为由结果值和输出信息组成的二元组 (a, w),输出信息不变。(状态值不变) - listens :: (Monad m) => (w -> b) -> RWST r w s m a -> RWST r w s m (a, b)
listens f m 在计算之后将结果值设置为由结果值和输出信息(调用函数 f 修改后的返回值)组成的二元组 (a, f w),输出信息不变。(状态值不变) - pass :: (Monad m) => RWST r w s m (a, w -> w) -> RWST r w s m a
pass m 在计算之后将结果值解析为结果值 a 和函数 f 组成的二元组,设置结果值 a, 然后对输出信息 w 调用函数 f。(状态值不变) - censor :: (Monad m) => (w -> w) -> RWST r w s m a -> RWST r w s m a
censor f m 在计算之后对输出信息 w 调用函数 f,结果值不变。(状态值不变)
Prelude Control.Monad.RWS> runRWST (tell "abc") "---" "!!!"
((),"!!!","abc")
Prelude Control.Monad.RWS> runRWST (tell "abc" >> tell "def") "---" "!!!"
((),"!!!","abcdef")
Prelude Control.Monad.RWS> runRWST (tell "abc" >> return 3) "---" "!!!"
(3,"!!!","abc")
Prelude Control.Monad.RWS> runRWST (tell "abc" >> listen (tell "def")) "---" "!!!"
(((),"def"),"!!!","abcdef")
Prelude Control.Monad.RWS> runRWST (listens (++ "def") $ tell "abc") "---" "!!!"
(((),"abcdef"),"!!!","abc")
Prelude Control.Monad.RWS> runRWST (pass $ tell "abc" >> return (0, (++ "def"))) "---" "!!!"
(0,"!!!","abcdef")
Prelude Control.Monad.RWS> runRWST (censor (++ "def") $ tell "abc") "---" "!!!"
((),"!!!","abcdef")
以下是涉及 State 操作的函数:
- state :: (Monoid w, Monad m) => (s -> (a,s)) -> RWST r w s m a
state f 将函数 f 封装进 Monad。(输出信息为空) - get :: (Monoid w, Monad m) => RWST r w s m s
get 将结果值设置为状态值 s,状态值 s 保持不变。(输出信息为空) - put :: (Monoid w, Monad m) => s -> RWST r w s m ()
put s 将结果值设为空,将状态值设为 s。(输出信息为空) - modify :: (Monoid w, Monad m) => (s -> s) -> RWST r w s m ()
modify f 将结果值设为空,将状态值设为 f s。(输出信息为空) - gets :: (Monoid w, Monad m) => (s -> a) -> RWST r w s m a
gets f 将结果值设为 f s,状态值 s 保持不变。(输出信息为空)
Prelude Control.Monad.RWS> runRWST (return 15) "---" 1
(15,1,())
Prelude Control.Monad.RWS> runRWST get "---" 1
(1,1,())
Prelude Control.Monad.RWS> runRWST (put 3) "---" 1
((),3,())
Prelude Control.Monad.RWS> runRWST (modify (+1)) "---" 1
((),2,())
Prelude Control.Monad.RWS> runRWST (gets (+1)) "---" 1
(2,1,())
Prelude Control.Monad.RWS> evalRWST (gets (+1)) "---" 1
(2,())
Prelude Control.Monad.RWS> execRWST (gets (+1)) "---" 1
(1,())
Prelude Control.Monad.RWS> runRWST (do put 3; return 15) "---" 1
(15,3,())
Prelude Control.Monad.RWS> runRWST (put 3 >> return 15) "---" 1
(15,3,())
综合利用三者的功能:
Prelude Control.Monad.RWS> runRWST (ask >>= tell) "abc" 0
((),0,"abc")
Prelude Control.Monad.RWS> runRWST (local (++ "def") ask >>= tell) "abc" 0
((),0,"abcdef")
Prelude Control.Monad.RWS> runRWST (asks (++ "def") >>= tell) "abc" 0
((),0,"abcdef")
Prelude Control.Monad.RWS> runRWST (listen $ ask >>= tell) "abc" 0
(((),"abc"),0,"abc")
Prelude Control.Monad.RWS> runRWST (listens (++ "def") $ ask >>= tell) "abc" 0
(((),"abcdef"),0,"abc")
Prelude Control.Monad.RWS> runRWST (censor (++ "def") $ ask >>= tell) "abc" 0
((),0,"abcdef")
Prelude Control.Monad.RWS> runRWST (get >>= tell) 0 "abc"
((),"abc","abc")
Prelude Control.Monad.RWS> runRWST (get >>= tell >> tell "def") 0 "abc"
((),"abc","abcdef")
Prelude Control.Monad.RWS> runRWST (get >>= tell >> put "def") 0 "abc"
((),"def","abc")
Prelude Control.Monad.RWS> runRWST (get >>= tell >> return "def") 0 "abc"
("def","abc","abc")
RWS Monad
type RWS r w s = RWST r w s Identity
rws :: (r -> s -> (a, s, w)) -> RWS r w s a
rws f = RWST (\ r s -> Identity (f r s))
runRWS :: RWS r w s a -> r -> s -> (a, s, w)
runRWS m r s = runIdentity (runRWST m r s)
evalRWS :: RWS r w s a -> r -> s -> (a, w)
evalRWS m r s = let
(a, _, w) = runRWS m r s
in (a, w)
execRWS :: RWS r w s a -> r -> s -> (s, w)
execRWS m r s = let
(_, s', w) = runRWS m r s
in (s', w)
mapRWS :: ((a, s, w) -> (b, s, w')) -> RWS r w s a -> RWS r w' s b
mapRWS f = mapRWST (Identity . f . runIdentity)
withRWS :: (r' -> s -> (r, s)) -> RWS r w s a -> RWS r' w s a
withRWS = withRWST
RWS Monad 是 RWST Monad(转换器) 的一个特例。
Haskell语言学习笔记(37)RWS, RWST的更多相关文章
- Haskell语言学习笔记(88)语言扩展(1)
ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...
- Haskell语言学习笔记(79)lambda演算
lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...
- Haskell语言学习笔记(69)Yesod
Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...
- Haskell语言学习笔记(20)IORef, STRef
IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...
- Haskell语言学习笔记(39)Category
Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...
- Haskell语言学习笔记(72)Free Monad
安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...
- Haskell语言学习笔记(44)Lens(2)
自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...
- Haskell语言学习笔记(38)Lens(1)
Lens Lens是一个接近语言级别的库,使用它可以方便的读取,设置,修改一个大的数据结构中某一部分的值. view, over, set Prelude> :m +Control.Lens P ...
- Haskell语言学习笔记(25)MonadState, State, StateT
MonadState 类型类 class Monad m => MonadState s m | m -> s where get :: m s get = state (\s -> ...
随机推荐
- Linux如何用yum安装软件或服务
百度百科: Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器.基于RPM包管理,能够从指定的服 ...
- WinForm下ComboBox设定SelectedValue总结 (SelectedValue==null解决办法)[转]
http://www.cnblogs.com/qqflying/archive/2013/05/23/3096050.html 实践发现:以SelectedIndex赋值让ComboBox自动选中时能 ...
- go get中的...
go get命令是go自带的包下载工具. 如果配置了GOPATH,下载的文件放置于GOPATH/src下面 例如 $ go get github.com/garyburd/redigo/redis $ ...
- 【python】网络编程-套接字常用函数
- 【转】ORACLE Dataguard安装
ORACLE Dataguard安装 标签: oracledatabasearchivesql数据库list 2011-08-01 09:40 5548人阅读 评论(1) 收藏 举报 分类: ORA ...
- 如何在UltraEdit中高亮显示PB代码
打开UE,从菜单中选择高级->配置… 点击打开按钮,注意文件WordFile.txt最后一个高亮显示语言的编号,格式为“ /L(number) ”,假设最后一个高亮显示语言的编号是15,修改UE ...
- Sigar简介
大家好,我是Sigar.也许好多人还不认识我.下面就介绍一下我自己,好让大家对我有一个大致的了解. 我的全名是System Information Gatherer And Reporter,中文名是 ...
- C++中reinterpret_cast、const_cast、static_cast、dynamic_cast的作用与区别
1.reinterpret_cast 作用及原理:将一个类型的指针,转换为另一个类型的指针,这种转换不用修改指针变量值数据存放格式(不改变指针变量值),只需在编译时重新解释指针的类型就可以,当然他也可 ...
- spring Boot使用AOP统一处理Web请求日志记录
1.使用spring boot实现一个拦截器 1.引入依赖: <dependency> <groupId>org.springframework.boot</grou ...
- AJAX XML 实例
AJAX XML 实例 下面的例子将演示网页如何使用 AJAX 来读取来自 XML 文件的信息 <!DOCTYPE html> <html> <head> < ...