これは問題です。私は持っています:mapMonadTrans :: MonadTrans xT =>(m a - > n b) - > xT m a - > xT n b
f :: MonadIO m => ReaderT FooBar m Answer;
f = (liftIO getArgs) >>= ...
私はこれを修正された引数で実行する必要があります。 mが不明であるため、私はすべてのmについてメートルに(WITHARGSの引数)を形質転換するために何らかの形で必要なので、私は単に
mapReaderT (withArgs args) :: ReaderT r IO b -> ReaderT r IO b
を使用することはできません。
私が見つけた一つの可能性は、このように、私自身の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の値を返すための関数を持つデータ型aがあり、その型はa型の値の一部がI/Oを使ってbを生成できるほど一般的でなければなりません) –
@strake :Control.Monad.CatchIOに問題があることに注意してください。つまり、短絡モナド変圧器(たとえばErrorT)を使用している場合、予想どおりに動作しない可能性があります。これが設計上の欠陥であるか誤用であるかは、解釈が可能ですが、それを認識しておく必要があります。詳細については、http://andersk.mit.edu/haskell/monad-peel/を参照してください。 –