問題是這樣的。我有:mapMonadTrans :: MonadTrans xT =>(m a - > n b) - > xT m a - > xT n b
f :: MonadIO m => ReaderT FooBar m Answer;
f = (liftIO getArgs) >>= ...
我需要運行修改參數。然而,由於m是未知的,我不能簡單地用
mapReaderT (withArgs args) :: ReaderT r IO b -> ReaderT r IO b
,因爲我需要以某種方式改變(withArgs參數)爲m的所有的m。我發現
一種可能性是定義自己的withArgs,即:
import System.Environment (setArgs, freeArgv);
withArgv new_args act = do {
pName <- liftIO System.Environment.getProgName;
existing_args <- liftIO System.Environment.getArgs;
bracket (liftIO $ setArgs new_args)
(\argv -> do {
_ <- liftIO $ setArgs (pName:existing_args);
liftIO $ freeArgv argv;
})
(const act);
};
withArgs xs act = do {
p <- liftIO System.Environment.getProgName;
withArgv (p:xs) act;
};
然而,這是一個雜牌,而具體到一個功能 - 我需要重新寫每withX :: X -> IO a -> IO a
,例如Control.Exception.handle
什麼,如果有的話,是一個更好的方法來做到這一點?
編輯:在處理的情況下,我發現了Control.Monad.CatchIO。在另一種情況下,我使用了另一個簡短的kludge(不值得發佈)來避免上面的kludge。仍在尋求更好的解決方案!
如果您卸下'F'類型簽名是什麼?我想知道是否限制'MonadIO'的限制太多了。 –
我需要在'f'中做I/O。否則,這將是盛大的。 (事實上,我有在它的功能的數據類型的,以產生類型B的某個值,並且功能必須足夠一般使得類型的一些值可以做I/O得到灣) –
@strake :請注意,Control.Monad.CatchIO存在問題。也就是說,如果您使用的是短路單聲道變壓器(例如ErrorT),則可能無法按照您的預期運行。無論是設計缺陷還是誤用,都有待解釋,但您應該意識到這一點。有關詳細信息,請參閱http://andersk.mit.edu/haskell/monad-peel/。 –