on master help sign in
The MonadWriter class
commitfa604ace907439926efe83a912b838ffa6de9e6c authorIndex Int <vlad.z.4096@gmail.com> dateSat 13 Jun 2015, 01:59 (11 years ago) parentee5e65c
6 files changed+193−9
ether.cabal+1 src/Control/Monad/Ether/Except.hs+15−9 src/Control/Monad/Ether/Reader.hs+5 src/Control/Monad/Ether/State.hs+6 src/Control/Monad/Ether/Writer.hs+156 src/Control/Monad/Trans/Ether/Writer.hs+10
ether.cabal+1
@@ -31,6 +31,7 @@ library
3131 Control.Monad.Trans.Ether.State
3232 Control.Monad.Trans.Ether.Except
3333 Control.Monad.Ether.Reader
34+ Control.Monad.Ether.Writer
3435 Control.Monad.Ether.State
3536 Control.Monad.Ether.Except
3637 Control.Monad.Ether.Implicit.Reader
src/Control/Monad/Ether/Except.hs+15−9
@@ -27,13 +27,15 @@ module Control.Monad.Ether.Except
2727import Data.Proxy (Proxy(Proxy))
2828import Control.Monad.Trans (lift)
2929
30−import qualified Control.Monad.Trans.Ether.Reader as Reader
31−import qualified Control.Monad.Trans.Ether.State as State
3230import Control.Monad.Trans.Ether.Except hiding (throw, catch)
3331import qualified Control.Monad.Trans.Ether.Except as E
32+import qualified Control.Monad.Trans.Ether.Reader as R
33+import qualified Control.Monad.Trans.Ether.Writer as W
34+import qualified Control.Monad.Trans.Ether.State as S
35+import qualified Control.Ether.Util as Util
3436
3537-- for mtl instances
36−import qualified Control.Monad.Trans.Except as Trans (ExceptT(..), runExceptT)
38+import qualified Control.Monad.Trans.Except as Trans.E
3739import qualified Control.Monad.Trans.Identity as Trans.I
3840import qualified Control.Monad.Trans.List as Trans.L
3941import qualified Control.Monad.Trans.Maybe as Trans.M
@@ -62,20 +64,24 @@ instance MonadExcept tag e m => MonadExcept tag e (ExceptT tag' e' m) where
6264
6365-- Instances for other tagged transformers
6466
65−instance MonadExcept tag e m => MonadExcept tag e (Reader.ReaderT tag' r m) where
67+instance MonadExcept tag e m => MonadExcept tag e (R.ReaderT tag' r m) where
6668 throw t = lift . throw t
67− catch t = Reader.liftCatch Proxy (catch t)
69+ catch t = R.liftCatch Proxy (catch t)
6870
69−instance MonadExcept tag e m => MonadExcept tag e (State.StateT tag' s m) where
71+instance (Monoid w, MonadExcept tag e m) => MonadExcept tag e (W.WriterT tag' w m) where
7072 throw t = lift . throw t
71− catch t = State.liftCatch Proxy (catch t)
73+ catch t = W.liftCatch Proxy (catch t)
74+
75+instance MonadExcept tag e m => MonadExcept tag e (S.StateT tag' s m) where
76+ throw t = lift . throw t
77+ catch t = S.liftCatch Proxy (catch t)
7278
7379
7480-- Instances for mtl transformers
7581
76−instance MonadExcept tag e m => MonadExcept tag e (Trans.ExceptT e' m) where
82+instance MonadExcept tag e m => MonadExcept tag e (Trans.E.ExceptT e' m) where
7783 throw t = lift . throw t
78− catch t m h = Trans.ExceptT $ catch t (Trans.runExceptT m) (Trans.runExceptT . h)
84+ catch t = Util.liftCatch_ExceptT (catch t)
7985
8086instance MonadExcept tag e m => MonadExcept tag e (Trans.I.IdentityT m) where
8187 throw t = lift . throw t
src/Control/Monad/Ether/Reader.hs+5
@@ -28,6 +28,7 @@ module Control.Monad.Ether.Reader
2828import Data.Proxy (Proxy(Proxy))
2929import Control.Monad.Trans (lift)
3030
31+import Control.Monad.Trans.Ether.Writer (WriterT, mapWriterT)
3132import Control.Monad.Trans.Ether.State (StateT , mapStateT)
3233import Control.Monad.Trans.Ether.Except (ExceptT, mapExceptT)
3334import Control.Monad.Trans.Ether.Reader hiding (reader, ask, local)
@@ -90,6 +91,10 @@ instance MonadReader tag r m => MonadReader tag r (ReaderT tag' r' m) where
9091
9192-- Instances for other tagged transformers
9293
94+instance (Monoid w, MonadReader tag r m) => MonadReader tag r (WriterT tag' w m) where
95+ ask t = lift (ask t)
96+ local t = mapWriterT Proxy . local t
97+
9398instance (MonadReader tag r m) => MonadReader tag r (StateT tag' s m) where
9499 ask t = lift (ask t)
95100 local t = mapStateT Proxy . local t
src/Control/Monad/Ether/State.hs+6
@@ -33,6 +33,7 @@ module Control.Monad.Ether.State
3333import Control.Monad.Trans (lift)
3434
3535import Control.Monad.Trans.Ether.Reader (ReaderT)
36+import Control.Monad.Trans.Ether.Writer (WriterT)
3637import Control.Monad.Trans.Ether.Except (ExceptT)
3738import Control.Monad.Trans.Ether.State hiding (state, get, put)
3839import qualified Control.Monad.Trans.Ether.State as S
@@ -94,6 +95,11 @@ instance (MonadState tag s m) => MonadState tag s (ReaderT tag' r m) where
9495 put t = lift . put t
9596 state t = lift . state t
9697
98+instance (Monoid w, MonadState tag s m) => MonadState tag s (WriterT tag' w m) where
99+ get t = lift (get t)
100+ put t = lift . put t
101+ state t = lift . state t
102+
97103instance (MonadState tag s m) => MonadState tag s (ExceptT tag' e m) where
98104 get t = lift (get t)
99105 put t = lift . put t
src/Control/Monad/Ether/Writer.hsnew file+156
@@ -0,0 +1,156 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE UndecidableInstances #-}
6+{-# LANGUAGE DataKinds #-}
7+{-# LANGUAGE ConstraintKinds #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE FunctionalDependencies #-}
10+{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE RankNTypes #-}
12+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
13+module Control.Monad.Ether.Writer
14+ (
15+ -- * MonadWriter class
16+ MonadWriter(..)
17+ , listens
18+ , censor
19+ -- * The Writer monad
20+ , Writer
21+ , runWriter
22+ , execWriter
23+ -- * The WriterT monad transformer
24+ , WriterT
25+ , writerT
26+ , runWriterT
27+ , execWriterT
28+ , mapWriterT
29+ ) where
30+
31+import Data.Proxy (Proxy(Proxy))
32+import Control.Monad.Trans (lift)
33+
34+import Control.Monad.Trans.Ether.Writer hiding (writer, tell, listen, pass)
35+import qualified Control.Monad.Trans.Ether.Reader as R
36+import qualified Control.Monad.Trans.Ether.State as S
37+import qualified Control.Monad.Trans.Ether.Except as E
38+import qualified Control.Monad.Trans.Ether.Writer as W
39+import qualified Control.Ether.Util as Util
40+
41+-- for mtl instances
42+import qualified Control.Monad.Trans.Except as Trans.E
43+import qualified Control.Monad.Trans.Identity as Trans.I
44+import qualified Control.Monad.Trans.Maybe as Trans.M
45+import qualified Control.Monad.Trans.Reader as Trans.R
46+import qualified Control.Monad.Trans.State.Lazy as Trans.S.Lazy
47+import qualified Control.Monad.Trans.State.Strict as Trans.S.Strict
48+import qualified Control.Monad.Trans.Writer.Lazy as Trans.W.Lazy
49+
50+class (Monoid w, Monad m) => MonadWriter tag w m | m tag -> w where
51+
52+ {-# MINIMAL (writer | tell), listen, pass #-}
53+
54+ -- | Embed a simple writer action.
55+ writer :: proxy tag -> (a, w) -> m a
56+ writer t ~(a, w) = do
57+ tell t w
58+ return a
59+
60+ -- | Append a value to the accumulator within the monad.
61+ tell :: proxy tag -> w -> m ()
62+ tell t w = writer t ((),w)
63+
64+ -- | Execute an action and add its accumulator
65+ -- to the value of the computation.
66+ listen :: proxy tag -> m a -> m (a, w)
67+
68+ -- | Execute an action which returns a value and a function,
69+ -- and return the value, applying the function to the accumulator.
70+ pass :: proxy tag -> m (a, w -> w) -> m a
71+
72+listens :: MonadWriter tag w m => proxy tag -> (w -> b) -> m a -> m (a, b)
73+listens t f m = do
74+ ~(a, w) <- listen t m
75+ return (a, f w)
76+
77+censor :: MonadWriter tag w m => proxy tag -> (w -> w) -> m a -> m a
78+censor t f m = pass t $ do
79+ a <- m
80+ return (a, f)
81+
82+instance {-# OVERLAPPING #-} (Monoid w, Monad m) => MonadWriter tag w (WriterT tag w m) where
83+ writer = W.writer
84+ tell = W.tell
85+ listen = W.listen
86+ pass = W.pass
87+
88+instance (Monoid w', MonadWriter tag w m) => MonadWriter tag w (WriterT tag' w' m) where
89+ writer t = lift . writer t
90+ tell t = lift . tell t
91+ listen t = W.liftListen Proxy (listen t)
92+ pass t = W.liftPass Proxy (pass t)
93+
94+-- Instances for other tagged transformers
95+
96+instance (MonadWriter tag w m) => MonadWriter tag w (R.ReaderT tag' r m) where
97+ writer t = lift . writer t
98+ tell t = lift . tell t
99+ listen t = R.mapReaderT Proxy (listen t)
100+ pass t = R.mapReaderT Proxy (pass t)
101+
102+instance (MonadWriter tag w m) => MonadWriter tag w (E.ExceptT tag' e m) where
103+ writer t = lift . writer t
104+ tell t = lift . tell t
105+ listen t = E.liftListen Proxy (listen t)
106+ pass t = E.liftPass Proxy (pass t)
107+
108+instance (MonadWriter tag w m) => MonadWriter tag w (S.StateT tag' e m) where
109+ writer t = lift . writer t
110+ tell t = lift . tell t
111+ listen t = S.liftListen Proxy (listen t)
112+ pass t = S.liftPass Proxy (pass t)
113+
114+-- Instances for mtl transformers
115+
116+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.E.ExceptT e m) where
117+ writer t = lift . writer t
118+ tell t = lift . tell t
119+ listen t = Trans.E.liftListen (listen t)
120+ pass t = Trans.E.liftPass (pass t)
121+
122+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.I.IdentityT m) where
123+ writer t = lift . writer t
124+ tell t = lift . tell t
125+ listen t = Trans.I.mapIdentityT (listen t)
126+ pass t = Trans.I.mapIdentityT (pass t)
127+
128+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.M.MaybeT m) where
129+ writer t = lift . writer t
130+ tell t = lift . tell t
131+ listen t = Trans.M.liftListen (listen t)
132+ pass t = Trans.M.liftPass (pass t)
133+
134+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.R.ReaderT r m) where
135+ writer t = lift . writer t
136+ tell t = lift . tell t
137+ listen t = Trans.R.mapReaderT (listen t)
138+ pass t = Trans.R.mapReaderT (pass t)
139+
140+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.S.Lazy.StateT s m) where
141+ writer t = lift . writer t
142+ tell t = lift . tell t
143+ listen t = Trans.S.Lazy.liftListen (listen t)
144+ pass t = Trans.S.Lazy.liftPass (pass t)
145+
146+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.S.Strict.StateT s m) where
147+ writer t = lift . writer t
148+ tell t = lift . tell t
149+ listen t = Trans.S.Strict.liftListen (listen t)
150+ pass t = Trans.S.Strict.liftPass (pass t)
151+
152+instance (Monoid w', MonadWriter tag w m) => MonadWriter tag w (Trans.W.Lazy.WriterT w' m) where
153+ writer t = lift . writer t
154+ tell t = lift . tell t
155+ listen t = Util.liftListen_WriterT (listen t)
156+ pass t = Util.liftPass_WriterT (pass t)
src/Control/Monad/Trans/Ether/Writer.hs+10
@@ -22,9 +22,13 @@ module Control.Monad.Trans.Ether.Writer
2222 , mapWriterT
2323 -- * Writer operations
2424 , tell
25+ , listen
26+ , pass
2527 -- * Lifting other operations
2628 , liftCallCC
2729 , liftCatch
30+ , liftListen
31+ , liftPass
2832 ) where
2933
3034import Data.Proxy (Proxy(Proxy))
@@ -114,6 +118,12 @@ mapWriterT t f m = tagged t $ Trans.mapWriterT f (coerce m)
114118tell :: Monad m => proxy tag -> w -> WriterT tag w m ()
115119tell t w = writer t ((), w)
116120
121+listen :: (Monoid w, Monad m) => proxy tag -> WriterT tag w m a -> WriterT tag w m (a, w)
122+listen t m = tagged t $ Trans.listen (coerce m)
123+
124+pass :: (Monoid w, Monad m) => proxy tag -> WriterT tag w m (a, w -> w) -> WriterT tag w m a
125+pass t m = tagged t $ Trans.pass (coerce m)
126+
117127-- | Lift a @catchE@ operation to the new monad.
118128liftCatch :: proxy tag -> Sig.Catch e m (a, w) -> Sig.Catch e (WriterT tag w m) a
119129liftCatch t f m h = tagged t $ Trans.liftCatch f (coerce m) (coerce h)