1- {-# LANGUAGE Safe #-}
1+ {-# LANGUAGE Trustworthy #-}
22{-# LANGUAGE FlexibleInstances #-}
33{-# LANGUAGE FunctionalDependencies #-}
44{-# LANGUAGE MultiParamTypeClasses #-}
55{-# LANGUAGE UndecidableInstances #-}
6+ {-# LANGUAGE StandaloneKindSignatures #-}
7+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
8+ {-# LANGUAGE TupleSections #-}
9+ {-# LANGUAGE ViewPatterns #-}
10+ {-# OPTIONS_GHC -Wno-name-shadowing #-}
611-- Search for UndecidableInstances to see why this is needed
712
813-----------------------------------------------------------------------------
@@ -28,6 +33,7 @@ module Control.Monad.Writer.Class (
2833 MonadWriter (.. ),
2934 listens ,
3035 censor ,
36+ LiftingWriter (.. ),
3137 ) where
3238
3339import Control.Monad.Trans.Except (ExceptT )
@@ -47,7 +53,8 @@ import Control.Monad.Trans.Accum (AccumT)
4753import qualified Control.Monad.Trans.Accum as Accum
4854import qualified Control.Monad.Trans.RWS.CPS as CPSRWS
4955import qualified Control.Monad.Trans.Writer.CPS as CPS
50- import Control.Monad.Trans.Class (lift )
56+ import Control.Monad.Trans.Class (MonadTrans (lift ))
57+ import Data.Kind (Type )
5158
5259-- ---------------------------------------------------------------------------
5360-- MonadWriter class
@@ -205,3 +212,80 @@ instance
205212 tell = lift . tell
206213 listen = Accum. liftListen listen
207214 pass = Accum. liftPass pass
215+
216+
217+ -- | A helper type to decrease boilerplate when defining new transformer
218+ -- instances of 'MonadWriter'.
219+ --
220+ -- @since ????
221+ type LiftingWriter :: ((Type -> Type ) -> Type -> Type ) -> (Type -> Type ) -> Type -> Type
222+ newtype LiftingWriter t m a = LiftingWriter { runLiftingWriter :: t m a }
223+ deriving (Functor , Applicative , Monad , MonadTrans )
224+
225+
226+ instance (Monoid w' , MonadWriter w m ) => MonadWriter w (LiftingWriter (LazyRWS. RWST r w' s ) m ) where
227+ writer = lift . writer
228+ tell = lift . tell
229+ listen (LiftingWriter (LazyRWS. RWST x)) = LiftingWriter $ LazyRWS. RWST $ \ r s -> do
230+ ((a, s, w'), w) <- listen $ x r s
231+ pure ((a, w), s, w')
232+ pass (LiftingWriter (LazyRWS. RWST x)) = LiftingWriter $ LazyRWS. RWST $ \ r s -> do
233+ (y, s, w') <- x r s
234+ a <- pass $ pure y
235+ pure (a, s, w')
236+
237+ instance (Monoid w' , MonadWriter w m ) => MonadWriter w (LiftingWriter (StrictRWS. RWST r w' s ) m ) where
238+ writer = lift . writer
239+ tell = lift . tell
240+ listen (LiftingWriter (StrictRWS. RWST x)) = LiftingWriter $ StrictRWS. RWST $ \ r s -> do
241+ ((a, s, w'), w) <- listen $ x r s
242+ pure ((a, w), s, w')
243+ pass (LiftingWriter (StrictRWS. RWST x)) = LiftingWriter $ StrictRWS. RWST $ \ r s -> do
244+ (y, s, w') <- x r s
245+ a <- pass $ pure y
246+ pure (a, s, w')
247+
248+ instance (Monoid w' , MonadWriter w m ) => MonadWriter w (LiftingWriter (CPSRWS. RWST r w' s ) m ) where
249+ writer = lift . writer
250+ tell = lift . tell
251+ listen (LiftingWriter (CPSRWS. runRWST -> x)) = LiftingWriter $ CPSRWS. rwsT $ \ r s -> do
252+ ((a, s, w'), w) <- listen $ x r s
253+ pure ((a, w), s, w')
254+ pass (LiftingWriter (CPSRWS. runRWST -> x)) = LiftingWriter $ CPSRWS. rwsT $ \ r s -> do
255+ (y, s, w') <- x r s
256+ a <- pass $ pure y
257+ pure (a, s, w')
258+
259+ instance (Monoid w' , MonadWriter w m ) => MonadWriter w (LiftingWriter (Lazy. WriterT w' ) m ) where
260+ writer = lift . writer
261+ tell = lift . tell
262+ listen (LiftingWriter (Lazy. WriterT x)) = LiftingWriter $ Lazy. WriterT $ do
263+ ((a, w'), w) <- listen x
264+ pure ((a, w), w')
265+ pass (LiftingWriter (Lazy. WriterT x)) = LiftingWriter $ Lazy. WriterT $ do
266+ (y, w') <- x
267+ a <- pass $ pure y
268+ pure (a, w')
269+
270+ instance (Monoid w' , MonadWriter w m ) => MonadWriter w (LiftingWriter (Strict. WriterT w' ) m ) where
271+ writer = lift . writer
272+ tell = lift . tell
273+ listen (LiftingWriter (Strict. WriterT x)) = LiftingWriter $ Strict. WriterT $ do
274+ ((a, w'), w) <- listen x
275+ pure ((a, w), w')
276+ pass (LiftingWriter (Strict. WriterT x)) = LiftingWriter $ Strict. WriterT $ do
277+ (y, w') <- x
278+ a <- pass $ pure y
279+ pure (a, w')
280+
281+ instance (Monoid w' , MonadWriter w m ) => MonadWriter w (LiftingWriter (CPS. WriterT w' ) m ) where
282+ writer = lift . writer
283+ tell = lift . tell
284+ listen (LiftingWriter (CPS. runWriterT -> x)) = LiftingWriter $ CPS. writerT $ do
285+ ((a, w'), w) <- listen x
286+ pure ((a, w), w')
287+ pass (LiftingWriter (CPS. runWriterT -> x)) = LiftingWriter $ CPS. writerT $ do
288+ (y, w') <- x
289+ a <- pass $ pure y
290+ pure (a, w')
291+
0 commit comments