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的更多相关文章

  1. Haskell语言学习笔记(88)语言扩展(1)

    ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...

  2. Haskell语言学习笔记(79)lambda演算

    lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...

  3. Haskell语言学习笔记(69)Yesod

    Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...

  4. Haskell语言学习笔记(20)IORef, STRef

    IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...

  5. Haskell语言学习笔记(39)Category

    Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...

  6. Haskell语言学习笔记(72)Free Monad

    安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...

  7. Haskell语言学习笔记(44)Lens(2)

    自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...

  8. Haskell语言学习笔记(38)Lens(1)

    Lens Lens是一个接近语言级别的库,使用它可以方便的读取,设置,修改一个大的数据结构中某一部分的值. view, over, set Prelude> :m +Control.Lens P ...

  9. Haskell语言学习笔记(25)MonadState, State, StateT

    MonadState 类型类 class Monad m => MonadState s m | m -> s where get :: m s get = state (\s -> ...

随机推荐

  1. Linux如何用yum安装软件或服务

    百度百科: Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器.基于RPM包管理,能够从指定的服 ...

  2. WinForm下ComboBox设定SelectedValue总结 (SelectedValue==null解决办法)[转]

    http://www.cnblogs.com/qqflying/archive/2013/05/23/3096050.html 实践发现:以SelectedIndex赋值让ComboBox自动选中时能 ...

  3. go get中的...

    go get命令是go自带的包下载工具. 如果配置了GOPATH,下载的文件放置于GOPATH/src下面 例如 $ go get github.com/garyburd/redigo/redis $ ...

  4. 【python】网络编程-套接字常用函数

  5. 【转】ORACLE Dataguard安装

    ORACLE Dataguard安装 标签: oracledatabasearchivesql数据库list 2011-08-01 09:40 5548人阅读 评论(1) 收藏 举报  分类: ORA ...

  6. 如何在UltraEdit中高亮显示PB代码

    打开UE,从菜单中选择高级->配置… 点击打开按钮,注意文件WordFile.txt最后一个高亮显示语言的编号,格式为“ /L(number) ”,假设最后一个高亮显示语言的编号是15,修改UE ...

  7. Sigar简介

    大家好,我是Sigar.也许好多人还不认识我.下面就介绍一下我自己,好让大家对我有一个大致的了解. 我的全名是System Information Gatherer And Reporter,中文名是 ...

  8. C++中reinterpret_cast、const_cast、static_cast、dynamic_cast的作用与区别

    1.reinterpret_cast 作用及原理:将一个类型的指针,转换为另一个类型的指针,这种转换不用修改指针变量值数据存放格式(不改变指针变量值),只需在编译时重新解释指针的类型就可以,当然他也可 ...

  9. spring Boot使用AOP统一处理Web请求日志记录

    1.使用spring boot实现一个拦截器 1.引入依赖: <dependency>   <groupId>org.springframework.boot</grou ...

  10. AJAX XML 实例

    AJAX XML 实例 下面的例子将演示网页如何使用 AJAX 来读取来自 XML 文件的信息 <!DOCTYPE html> <html> <head> < ...