{-# LANGUAGE
GeneralizedNewtypeDeriving, FlexibleInstances, UndecidableInstances, MultiParamTypeClasses
#-}
import Control.Monad.Except (MonadError (..), MonadIO (..), liftIO, lift)
import Control.Monad.Writer
import Control.Monad.Trans.Except (ExceptT, runExceptT, throwE)
import Control.Concurrent (threadDelay)
import Debug.Trace (trace)
newtype MyTrans m e a = MyTrans { unMyTrans :: ExceptT e m a }
deriving (Functor, Applicative, Monad, MonadError e)
instance (MonadIO m) => MonadIO (MyTrans m e) where
liftIO = MyTrans . liftIO
instance (MonadWriter w m) => MonadWriter w (MyTrans m e) where
writer = MyTrans. lift . writer
tell = MyTrans. lift . tell
throwMT :: Monad m => e -> MyTrans m e a
throwMT = MyTrans . throwE
runMyTrans :: Monad m => MyTrans m e a -> m (Either e a)
runMyTrans = runExceptT . unMyTrans
comp :: MyTrans IO String ()
comp = do
liftIO $ putStrLn "Starting Computation"
throwMT $ "Some Error"
-- dead code from this line
liftIO $ threadDelay (10*10^6)
liftIO $ putStrLn "Ending Computation"
return $ trace "retutning ()" ()
comp1 :: MyTrans (Writer [String]) String ()
comp1 = do
tell ["Starting Computation"]
throwMT "Some Error"
tell ["Ending Computation"]
return ()
main = do
print =<< runMyTrans comp
print $ runWriter (runMyTrans comp1)