問題はこれです。私は持っている:
f :: MonadIO m => ReaderT FooBar m Answer;
f = (liftIO getArgs) >>= ...
引数を変更してこれを実行する必要があります。ただ、mが不明なので単純には使えません
mapReaderT (withArgs args) :: ReaderT r IO b -> ReaderT r IO b
すべての m に対して (withArgs args) を m に変換する必要があるためです。
私が見つけた 1 つの可能性は、次のように、独自の 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;
};
ただし、これは面倒で、1 つの関数に固有のものですwithX :: X -> IO a -> IO a
。
もしあれば、これを行うためのより良い方法は何ですか?
編集: ハンドルの場合、Control.Monad.CatchIO が見つかりました。他のケースでは、上記のクラッジを避けるために、さらに別の短いクラッジ (投稿する価値はありません) を使用しました。まだより良い解決策を探しています!