2016-04-10 33 views
1

在本文檔中,我們稱eval6中的liftIO來執行I/O操作。 爲什麼我們在這種情況下需要提升?因爲我們可以實例化一個類型爲 沒有IO類。因此,對於I/O操作,我們 必須調用lift來向內發送命令。對於eval6,我們將 需要四次打印才能打印出一些東西。這僅僅是 不方便,所以人們創建一個新類MonadIO這樣,我們只 需要調用一次liftIO,而不必保留多少 次撰寫電梯數:liftIO而不是組合升降機

class (Monad m) => MonadIO m where 
liftIO :: IO a -> m a 
instance MonadIO IO where 
liftIO = id 
instance (Error e, MonadIO m) => MonadIO (ErrorT e m) where 
liftIO = lift . liftIO 
instance (MonadIO m) => MonadIO (ReaderT r m) where 
liftIO = lift . liftIO 

引文來從http://www.cs.virginia.edu/~wh5a/personal/Transformers.pdf

而且,我不明白爲什麼使用liftoud liftIO,我們不得不稱呼liftIO四次。我還看不出來,因此請清除它;)

回答

1
class MonadTrans t where 
    lift :: Monad m => m a -> t m a 

如果你想

foo :: Monad m => m a -> ExceptT e (StateT s (ReaderT r m)) a 

,那麼你需要一次爲每個類型的構造函數的應用lift。首先,我們得到

lift :: Monad m 
    => m a -> ReaderT r m a 

然後

lift . lift :: Monad m 
    => m a -> StateT s (ReaderT r m) a 

然後

foo = lift . lift . lift :: Monad m 
    => m a -> ExceptT e (StateT s (ReaderT r m)) a