|
1 | 1 | -- | This module defines the reader-writer-state monad transformer, `RWST`.
|
2 | 2 |
|
3 |
| -module Control.Monad.RWS.Trans |
4 |
| - ( See(), mkSee |
| 3 | +module Control.Monad.RWS.Trans |
| 4 | + ( RWSResult(..) |
5 | 5 | , RWST(..), runRWST, evalRWST, execRWST, mapRWST, withRWST
|
6 | 6 | , module Control.Monad.Trans
|
7 | 7 | , module Control.Monad.RWS.Class
|
8 | 8 | ) where
|
9 | 9 |
|
10 | 10 | import Prelude
|
11 | 11 |
|
| 12 | +import Data.Either |
12 | 13 | import Data.Monoid
|
13 | 14 | import Data.Tuple
|
14 | 15 |
|
15 |
| -import Control.Monad.Trans |
16 | 16 | import Control.Monad.Eff.Class
|
17 | 17 | import Control.Monad.Error.Class
|
| 18 | +import Control.Monad.RWS.Class |
| 19 | +import Control.Monad.Rec.Class |
18 | 20 | import Control.Monad.Reader.Class
|
19 |
| -import Control.Monad.Writer.Class |
20 | 21 | import Control.Monad.State.Class
|
21 |
| -import Control.Monad.RWS.Class |
22 |
| - |
23 |
| -type See s a w = |
24 |
| - { state :: s |
25 |
| - , result :: a |
26 |
| - , log :: w |
27 |
| - } |
| 22 | +import Control.Monad.Trans |
| 23 | +import Control.Monad.Writer.Class |
28 | 24 |
|
29 |
| -mkSee :: forall s a w. (Monoid w) => s -> a -> w -> See s a w |
30 |
| -mkSee s a w = { state: s, result: a, log: w } |
| 25 | +data RWSResult state result writer = RWSResult state result writer |
31 | 26 |
|
32 | 27 | -- | The reader-writer-state monad transformer, which combines the operations
|
33 | 28 | -- | of `ReaderT`, `WriterT` and `StateT` into a single monad transformer.
|
34 |
| -newtype RWST r w s m a = RWST (r -> s -> m (See s a w)) |
| 29 | +newtype RWST r w s m a = RWST (r -> s -> m (RWSResult s a w)) |
35 | 30 |
|
36 | 31 | -- | Run a computation in the `RWST` monad.
|
37 |
| -runRWST :: forall r w s m a. RWST r w s m a -> r -> s -> m (See s a w) |
| 32 | +runRWST :: forall r w s m a. RWST r w s m a -> r -> s -> m (RWSResult s a w) |
38 | 33 | runRWST (RWST x) = x
|
39 | 34 |
|
40 | 35 | -- | Run a computation in the `RWST` monad, discarding the final state.
|
41 | 36 | evalRWST :: forall r w s m a. (Monad m) => RWST r w s m a -> r -> s -> m (Tuple a w)
|
42 |
| -evalRWST m r s = runRWST m r s >>= \see -> return (Tuple see.result see.log) |
| 37 | +evalRWST m r s = runRWST m r s >>= \(RWSResult _ result writer) -> return (Tuple result writer) |
43 | 38 |
|
44 | 39 | -- | Run a computation in the `RWST` monad, discarding the result.
|
45 | 40 | execRWST :: forall r w s m a. (Monad m) => RWST r w s m a -> r -> s -> m (Tuple s w)
|
46 |
| -execRWST m r s = runRWST m r s >>= \see -> return (Tuple see.state see.log) |
| 41 | +execRWST m r s = runRWST m r s >>= \(RWSResult state _ writer) -> return (Tuple state writer) |
47 | 42 |
|
48 | 43 | -- | Change the result and accumulator types in a `RWST` monad action.
|
49 |
| -mapRWST :: forall r w1 w2 s m1 m2 a1 a2. (m1 (See s a1 w1) -> m2 (See s a2 w2)) -> RWST r w1 s m1 a1 -> RWST r w2 s m2 a2 |
| 44 | +mapRWST :: forall r w1 w2 s m1 m2 a1 a2. (m1 (RWSResult s a1 w1) -> m2 (RWSResult s a2 w2)) -> RWST r w1 s m1 a1 -> RWST r w2 s m2 a2 |
50 | 45 | mapRWST f m = RWST \r s -> f $ runRWST m r s
|
51 | 46 |
|
52 | 47 | -- | Change the context type in a `RWST` monad action.
|
53 | 48 | withRWST :: forall r1 r2 w s m a. (r2 -> s -> Tuple r1 s) -> RWST r1 w s m a -> RWST r2 w s m a
|
54 | 49 | withRWST f m = RWST \r s -> uncurry (runRWST m) (f r s)
|
55 | 50 |
|
56 |
| -instance functorRWST :: (Functor m) => Functor (RWST r w s m) where |
57 |
| - map f m = RWST \r s -> (\see -> see{result = f see.result}) <$> runRWST m r s |
| 51 | +instance functorRWST :: (Functor m, Monoid w) => Functor (RWST r w s m) where |
| 52 | + map f m = RWST \r s -> (\(RWSResult state result writer) -> RWSResult state (f result) writer) <$> runRWST m r s |
58 | 53 |
|
59 | 54 | instance applyRWST :: (Bind m, Monoid w) => Apply (RWST r w s m) where
|
60 | 55 | apply f m = RWST \r s ->
|
61 |
| - runRWST f r s >>= \{state = s', result = f', log = w'} -> |
62 |
| - runRWST m r s' <#> \{state = s'', result = a'', log = w''} -> |
63 |
| - mkSee s'' (f' a'') (w' ++ w'') |
| 56 | + runRWST f r s >>= \(RWSResult s' f' w') -> |
| 57 | + runRWST m r s' <#> \(RWSResult s'' a'' w'') -> |
| 58 | + RWSResult s'' (f' a'') (w' ++ w'') |
64 | 59 |
|
65 | 60 | instance bindRWST :: (Bind m, Monoid w) => Bind (RWST r w s m) where
|
66 | 61 | bind m f = RWST \r s ->
|
67 |
| - runRWST m r s >>= \{result = a, state = s', log = l} -> |
68 |
| - runRWST (f a) r s' <#> \see' -> |
69 |
| - see' { log = l ++ see'.log } |
| 62 | + runRWST m r s >>= \(RWSResult s' a w) -> |
| 63 | + runRWST (f a) r s' <#> \(RWSResult state result writer) -> |
| 64 | + RWSResult state result (w ++ writer) |
70 | 65 |
|
71 | 66 | instance applicativeRWST :: (Monad m, Monoid w) => Applicative (RWST r w s m) where
|
72 |
| - pure a = RWST \_ s -> pure $ mkSee s a mempty |
| 67 | + pure a = RWST \_ s -> pure $ RWSResult s a mempty |
73 | 68 |
|
74 | 69 | instance monadRWST :: (Monad m, Monoid w) => Monad (RWST r w s m)
|
75 | 70 |
|
76 | 71 | instance monadTransRWST :: (Monoid w) => MonadTrans (RWST r w s) where
|
77 |
| - lift m = RWST \_ s -> m >>= \a -> return $ mkSee s a mempty |
| 72 | + lift m = RWST \_ s -> m >>= \a -> return $ RWSResult s a mempty |
78 | 73 |
|
79 | 74 | instance monadEffRWS :: (Monad m, Monoid w, MonadEff eff m) => MonadEff eff (RWST r w s m) where
|
80 | 75 | liftEff = lift <<< liftEff
|
81 | 76 |
|
82 | 77 | instance monadReaderRWST :: (Monad m, Monoid w) => MonadReader r (RWST r w s m) where
|
83 |
| - ask = RWST \r s -> pure $ mkSee s r mempty |
| 78 | + ask = RWST \r s -> pure $ RWSResult s r mempty |
84 | 79 | local f m = RWST \r s -> runRWST m (f r) s
|
85 | 80 |
|
86 | 81 | instance monadStateRWST :: (Monad m, Monoid w) => MonadState s (RWST r w s m) where
|
87 |
| - state f = RWST \_ s -> case f s of Tuple a s' -> pure $ mkSee s' a mempty |
| 82 | + state f = RWST \_ s -> case f s of Tuple a s' -> pure $ RWSResult s' a mempty |
88 | 83 |
|
89 | 84 | instance monadWriterRWST :: (Monad m, Monoid w) => MonadWriter w (RWST r w s m) where
|
90 |
| - writer (Tuple a w) = RWST \_ s -> pure $ { state: s, result: a, log: w } |
91 |
| - listen m = RWST \r s -> runRWST m r s >>= \{ state: s', result: a, log: w} -> pure { state: s', result: Tuple a w, log: w } |
92 |
| - pass m = RWST \r s -> runRWST m r s >>= \{ result: Tuple a f, state: s', log: w} -> pure { state: s', result: a, log: f w } |
| 85 | + writer (Tuple a w) = RWST \_ s -> pure $ RWSResult s a w |
| 86 | + listen m = RWST \r s -> runRWST m r s >>= \(RWSResult s' a w) -> pure $ RWSResult s' (Tuple a w) w |
| 87 | + pass m = RWST \r s -> runRWST m r s >>= \(RWSResult s' (Tuple a f) w) -> pure $ RWSResult s' a (f w) |
93 | 88 |
|
94 | 89 | instance monadRWSRWST :: (Monad m, Monoid w) => MonadRWS r w s (RWST r w s m)
|
95 | 90 |
|
96 | 91 | instance monadErrorRWST :: (MonadError e m, Monoid w) => MonadError e (RWST r w s m) where
|
97 | 92 | throwError e = lift (throwError e)
|
98 | 93 | catchError m h = RWST $ \r s -> catchError (runRWST m r s) (\e -> runRWST (h e) r s)
|
| 94 | + |
| 95 | +instance monadRecRWST :: (Monoid w, MonadRec m) => MonadRec (RWST r w s m) where |
| 96 | + tailRecM k a = RWST \r s -> tailRecM (k' r) (RWSResult s a mempty) |
| 97 | + where |
| 98 | + k' r (RWSResult state result writer) = do |
| 99 | + RWSResult state' result' writer' <- runRWST (k result) r state |
| 100 | + return case result' of |
| 101 | + Left a -> Left (RWSResult state' a (writer <> writer')) |
| 102 | + Right b -> Right (RWSResult state' b (writer <> writer')) |
0 commit comments