monad-wrap-0.0: Wrap functions such as catch around different monads

Control.Monad.MultiWrap

Contents

Synopsis

MultiWrap class

class Monad mOut => MultiWrap mIn mOut a r | mIn mOut a -> r whereSource

MultiWrap is like MonadWrapIO, but for monads created by MonadTrans transformers. This is useful, if, for example, you implement your own monad, ReaderTLike, that is like a ReaderT except that you don't want to make it a member of the MonadReader class because you are already using MonadReader for some different state (or because you are implementing a library and the user of the library should be free to use ReaderT).

As long as ReaderTLike is a member of the MonadTrans class and assuming you have a localLike function equivalent to local, you should be able to run things like:

    mwrap (localLike modifyConfig :: ReaderTLike IO a -> ReaderTLike IO a)
          someComputation

You will generally have to specify the type of the wrap function or computation explicitly, but as long as you specify the type, mwrap saves you from keeping track of how many nested levels of transformer you have and from having to invoke wrap repeatedly.

Note one difference from MonadWrap and MonadWrapIO is that mresult and mresultF require an extra argument so as to specify the inner monad in which you want to supply the result. (E.g., in the case of using catch to produce a different return value in case of exceptions, the inner monad would be IO, and the extra argument might be supplied as (undefined :: IO Type).

Note that MultiWrap only works for up to 9 levels of nested monad transformer.

Methods

mwrap :: (mIn r -> mIn r) -> mOut a -> mOut aSource

mresultFSource

Arguments

:: mIn b

This argumet is here just for the type, because otherwise the resultTrans has no way of knowing which inner monad you want. The value of this argument is ignored, so it is safe to use (undefined :: InnerMonad ()) just as a way of specifying the type.

-> mOut (a -> r) 

mresult :: mIn b -> a -> mOut rSource

Instances

Monad m => MultiWrap m m a a 
(MonadTrans t9, Monad (t9 (t8 (t7 (t6 (t5 (t4 (t3 (t2 (t1 m))))))))), MonadWrap t9 a9 a8, MonadTrans t8, Monad (t8 (t7 (t6 (t5 (t4 (t3 (t2 (t1 m)))))))), MonadWrap t8 a8 a7, MonadTrans t7, Monad (t7 (t6 (t5 (t4 (t3 (t2 (t1 m))))))), MonadWrap t7 a7 a6, MonadTrans t6, Monad (t6 (t5 (t4 (t3 (t2 (t1 m)))))), MonadWrap t6 a6 a5, MonadTrans t5, Monad (t5 (t4 (t3 (t2 (t1 m))))), MonadWrap t5 a5 a4, MonadTrans t4, Monad (t4 (t3 (t2 (t1 m)))), MonadWrap t4 a4 a3, MonadTrans t3, Monad (t3 (t2 (t1 m))), MonadWrap t3 a3 a2, MonadTrans t2, Monad (t2 (t1 m)), MonadWrap t2 a2 a1, MonadTrans t1, Monad (t1 m), MonadWrap t1 a1 a0, Monad m) => MultiWrap m (t9 (t8 (t7 (t6 (t5 (t4 (t3 (t2 (t1 m))))))))) a9 a0 
(MonadTrans t8, Monad (t8 (t7 (t6 (t5 (t4 (t3 (t2 (t1 m)))))))), MonadWrap t8 a8 a7, MonadTrans t7, Monad (t7 (t6 (t5 (t4 (t3 (t2 (t1 m))))))), MonadWrap t7 a7 a6, MonadTrans t6, Monad (t6 (t5 (t4 (t3 (t2 (t1 m)))))), MonadWrap t6 a6 a5, MonadTrans t5, Monad (t5 (t4 (t3 (t2 (t1 m))))), MonadWrap t5 a5 a4, MonadTrans t4, Monad (t4 (t3 (t2 (t1 m)))), MonadWrap t4 a4 a3, MonadTrans t3, Monad (t3 (t2 (t1 m))), MonadWrap t3 a3 a2, MonadTrans t2, Monad (t2 (t1 m)), MonadWrap t2 a2 a1, MonadTrans t1, Monad (t1 m), MonadWrap t1 a1 a0, Monad m) => MultiWrap m (t8 (t7 (t6 (t5 (t4 (t3 (t2 (t1 m)))))))) a8 a0 
(MonadTrans t7, Monad (t7 (t6 (t5 (t4 (t3 (t2 (t1 m))))))), MonadWrap t7 a7 a6, MonadTrans t6, Monad (t6 (t5 (t4 (t3 (t2 (t1 m)))))), MonadWrap t6 a6 a5, MonadTrans t5, Monad (t5 (t4 (t3 (t2 (t1 m))))), MonadWrap t5 a5 a4, MonadTrans t4, Monad (t4 (t3 (t2 (t1 m)))), MonadWrap t4 a4 a3, MonadTrans t3, Monad (t3 (t2 (t1 m))), MonadWrap t3 a3 a2, MonadTrans t2, Monad (t2 (t1 m)), MonadWrap t2 a2 a1, MonadTrans t1, Monad (t1 m), MonadWrap t1 a1 a0, Monad m) => MultiWrap m (t7 (t6 (t5 (t4 (t3 (t2 (t1 m))))))) a7 a0 
(MonadTrans t6, Monad (t6 (t5 (t4 (t3 (t2 (t1 m)))))), MonadWrap t6 a6 a5, MonadTrans t5, Monad (t5 (t4 (t3 (t2 (t1 m))))), MonadWrap t5 a5 a4, MonadTrans t4, Monad (t4 (t3 (t2 (t1 m)))), MonadWrap t4 a4 a3, MonadTrans t3, Monad (t3 (t2 (t1 m))), MonadWrap t3 a3 a2, MonadTrans t2, Monad (t2 (t1 m)), MonadWrap t2 a2 a1, MonadTrans t1, Monad (t1 m), MonadWrap t1 a1 a0, Monad m) => MultiWrap m (t6 (t5 (t4 (t3 (t2 (t1 m)))))) a6 a0 
(MonadTrans t5, Monad (t5 (t4 (t3 (t2 (t1 m))))), MonadWrap t5 a5 a4, MonadTrans t4, Monad (t4 (t3 (t2 (t1 m)))), MonadWrap t4 a4 a3, MonadTrans t3, Monad (t3 (t2 (t1 m))), MonadWrap t3 a3 a2, MonadTrans t2, Monad (t2 (t1 m)), MonadWrap t2 a2 a1, MonadTrans t1, Monad (t1 m), MonadWrap t1 a1 a0, Monad m) => MultiWrap m (t5 (t4 (t3 (t2 (t1 m))))) a5 a0 
(MonadTrans t4, Monad (t4 (t3 (t2 (t1 m)))), MonadWrap t4 a4 a3, MonadTrans t3, Monad (t3 (t2 (t1 m))), MonadWrap t3 a3 a2, MonadTrans t2, Monad (t2 (t1 m)), MonadWrap t2 a2 a1, MonadTrans t1, Monad (t1 m), MonadWrap t1 a1 a0, Monad m) => MultiWrap m (t4 (t3 (t2 (t1 m)))) a4 a0 
(MonadTrans t3, Monad (t3 (t2 (t1 m))), MonadWrap t3 a3 a2, MonadTrans t2, Monad (t2 (t1 m)), MonadWrap t2 a2 a1, MonadTrans t1, Monad (t1 m), MonadWrap t1 a1 a0, Monad m) => MultiWrap m (t3 (t2 (t1 m))) a3 a0 
(MonadTrans t2, Monad (t2 (t1 m)), MonadWrap t2 a2 a1, MonadTrans t1, Monad (t1 m), MonadWrap t1 a1 a0, Monad m) => MultiWrap m (t2 (t1 m)) a2 a0 
(MonadTrans t1, Monad (t1 m), MonadWrap t1 a1 a0, Monad m) => MultiWrap m (t1 m) a1 a0 

Example

 module Main where
 
 import Control.Monad.MultiLift
 import Control.Monad.MultiWrap
 import Control.Monad.Reader
 import Control.Monad.State
 import Control.Monad.Trans
 import Control.Monad.Wrap
 
 newtype Type1 = Type1 { unType1 :: String }
 type Reader1 = ReaderT Type1 IO
 
 newtype Type2 = Type2 { unType2 :: String }
 type Reader2 = ReaderT Type2 Reader1
 
 type Outer = StateT () Reader2
 
 r3 :: Outer ()
 r3 = do
   -- Note that you have to specify the inner type
   s1 <- mlift (asks unType1 :: Reader1 String)
   liftIO $ putStrLn $ "s1: " ++ s1
   s2 <- mlift (asks unType2 :: Reader2 String)
   liftIO $ putStrLn $ "s2: " ++ s2
 
 r2 :: Outer ()
 r2 = do
   mwrap (local augment :: Reader1 a -> Reader1 a) r3
   where
     augment (Type1 s) = Type1 $ s ++ " (augmented)"
 
 r1 :: Reader2 ()
 r1 = do
   liftM fst $ runStateT r3 ()
   liftM fst $ runStateT r2 ()
   -- runContWrapT r2 return
   
 
 main :: IO ()
 main = do
   runReaderT (runReaderT r1 $ Type2 "this is the Reader2 contents")
        $ Type1 "this is the Reader1 contents"