on master help sign in
The MonadWriter class
fa604acIndex Int
ether.cabal+1
@@ -31,6 +31,7 @@ library
31 Control.Monad.Trans.Ether.State
31 Control.Monad.Trans.Ether.State
32 Control.Monad.Trans.Ether.Except
32 Control.Monad.Trans.Ether.Except
33 Control.Monad.Ether.Reader
33 Control.Monad.Ether.Reader
34+ Control.Monad.Ether.Writer
34 Control.Monad.Ether.State
35 Control.Monad.Ether.State
35 Control.Monad.Ether.Except
36 Control.Monad.Ether.Except
36 Control.Monad.Ether.Implicit.Reader
37 Control.Monad.Ether.Implicit.Reader
src/Control/Monad/Ether/Except.hs+15−9
@@ -27,13 +27,15 @@ module Control.Monad.Ether.Except
27import Data.Proxy (Proxy(Proxy))
27import Data.Proxy (Proxy(Proxy))
28import Control.Monad.Trans (lift)
28import Control.Monad.Trans (lift)
29
29
30−import qualified Control.Monad.Trans.Ether.Reader as Reader
31−import qualified Control.Monad.Trans.Ether.State as State
32import Control.Monad.Trans.Ether.Except hiding (throw, catch)
30import Control.Monad.Trans.Ether.Except hiding (throw, catch)
33import qualified Control.Monad.Trans.Ether.Except as E
31import 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
34
36
35-- for mtl instances
37-- for mtl instances
36−import qualified Control.Monad.Trans.Except as Trans (ExceptT(..), runExceptT)
38+import qualified Control.Monad.Trans.Except as Trans.E
37import qualified Control.Monad.Trans.Identity as Trans.I
39import qualified Control.Monad.Trans.Identity as Trans.I
38import qualified Control.Monad.Trans.List as Trans.L
40import qualified Control.Monad.Trans.List as Trans.L
39import qualified Control.Monad.Trans.Maybe as Trans.M
41import 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
62
64
63-- Instances for other tagged transformers
65-- Instances for other tagged transformers
64
66
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
66 throw t = lift . throw t
68 throw t = lift . throw t
67− catch t = Reader.liftCatch Proxy (catch t)
69+ catch t = R.liftCatch Proxy (catch t)
68
70
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
70 throw t = lift . throw t
72 throw t = lift . throw 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
71− catch t = State.liftCatch Proxy (catch t)
77+ catch t = S.liftCatch Proxy (catch t)
72
78
73
79
74-- Instances for mtl transformers
80-- Instances for mtl transformers
75
81
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
77 throw t = lift . throw t
83 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)
79
85
80instance MonadExcept tag e m => MonadExcept tag e (Trans.I.IdentityT m) where
86instance MonadExcept tag e m => MonadExcept tag e (Trans.I.IdentityT m) where
81 throw t = lift . throw t
87 throw t = lift . throw t
src/Control/Monad/Ether/Reader.hs+5
@@ -28,6 +28,7 @@ module Control.Monad.Ether.Reader
28import Data.Proxy (Proxy(Proxy))
28import Data.Proxy (Proxy(Proxy))
29import Control.Monad.Trans (lift)
29import Control.Monad.Trans (lift)
30
30
31+import Control.Monad.Trans.Ether.Writer (WriterT, mapWriterT)
31import Control.Monad.Trans.Ether.State (StateT , mapStateT)
32import Control.Monad.Trans.Ether.State (StateT , mapStateT)
32import Control.Monad.Trans.Ether.Except (ExceptT, mapExceptT)
33import Control.Monad.Trans.Ether.Except (ExceptT, mapExceptT)
33import Control.Monad.Trans.Ether.Reader hiding (reader, ask, local)
34import 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
90
91
91-- Instances for other tagged transformers
92-- Instances for other tagged transformers
92
93
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+
93instance (MonadReader tag r m) => MonadReader tag r (StateT tag' s m) where
98instance (MonadReader tag r m) => MonadReader tag r (StateT tag' s m) where
94 ask t = lift (ask t)
99 ask t = lift (ask t)
95 local t = mapStateT Proxy . local t
100 local t = mapStateT Proxy . local t
src/Control/Monad/Ether/State.hs+6
@@ -33,6 +33,7 @@ module Control.Monad.Ether.State
33import Control.Monad.Trans (lift)
33import Control.Monad.Trans (lift)
34
34
35import Control.Monad.Trans.Ether.Reader (ReaderT)
35import Control.Monad.Trans.Ether.Reader (ReaderT)
36+import Control.Monad.Trans.Ether.Writer (WriterT)
36import Control.Monad.Trans.Ether.Except (ExceptT)
37import Control.Monad.Trans.Ether.Except (ExceptT)
37import Control.Monad.Trans.Ether.State hiding (state, get, put)
38import Control.Monad.Trans.Ether.State hiding (state, get, put)
38import qualified Control.Monad.Trans.Ether.State as S
39import 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
94 put t = lift . put t
95 put t = lift . put t
95 state t = lift . state t
96 state t = lift . state t
96
97
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+
97instance (MonadState tag s m) => MonadState tag s (ExceptT tag' e m) where
103instance (MonadState tag s m) => MonadState tag s (ExceptT tag' e m) where
98 get t = lift (get t)
104 get t = lift (get t)
99 put t = lift . put t
105 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
22 , mapWriterT
22 , mapWriterT
23 -- * Writer operations
23 -- * Writer operations
24 , tell
24 , tell
25+ , listen
26+ , pass
25 -- * Lifting other operations
27 -- * Lifting other operations
26 , liftCallCC
28 , liftCallCC
27 , liftCatch
29 , liftCatch
30+ , liftListen
31+ , liftPass
28 ) where
32 ) where
29
33
30import Data.Proxy (Proxy(Proxy))
34import Data.Proxy (Proxy(Proxy))
@@ -114,6 +118,12 @@ mapWriterT t f m = tagged t $ Trans.mapWriterT f (coerce m)
114tell :: Monad m => proxy tag -> w -> WriterT tag w m ()
118tell :: Monad m => proxy tag -> w -> WriterT tag w m ()
115tell t w = writer t ((), w)
119tell t w = writer t ((), w)
116
120
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+
117-- | Lift a @catchE@ operation to the new monad.
127-- | Lift a @catchE@ operation to the new monad.
118liftCatch :: proxy tag -> Sig.Catch e m (a, w) -> Sig.Catch e (WriterT tag w m) a
128liftCatch :: proxy tag -> Sig.Catch e m (a, w) -> Sig.Catch e (WriterT tag w m) a
119liftCatch t f m h = tagged t $ Trans.liftCatch f (coerce m) (coerce h)
129liftCatch t f m h = tagged t $ Trans.liftCatch f (coerce m) (coerce h)