El problema es este. Tengo:mapMonadTrans :: MonadTrans xT => (m a -> n b) -> xT m a -> xT n b
f :: MonadIO m => ReaderT FooBar m Answer;
f = (liftIO getArgs) >>= ...
Necesito ejecutar esto con argumentos modificados. Sin embargo, dado que m es desconocida, no puedo simplemente uso
mapReaderT (withArgs args) :: ReaderT r IO b -> ReaderT r IO b
ya que necesito alguna manera de transformar (withArgs args) en m para todo m.
Una posibilidad es que encontré para definir mis propias withArgs, por lo tanto:
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;
};
Sin embargo, esto es una chapuza, y específica para una función - que tendría que volver a escribir todos los withX :: X -> IO a -> IO a
, por ejemplo, Control.Exception.handle
¿Cuál es, en su caso, una mejor manera de hacerlo?
Editar: En el caso del identificador, encontré Control.Monad.CatchIO. En el otro caso, utilicé otro, más breve kludge (no vale la pena publicarlo) para evitar el kludge anterior. ¡Todavía buscando una mejor solución!
¿Qué sucede si elimina la firma de tipo en 'f'? Me pregunto si restringir a 'MonadIO' es demasiado restrictivo. –
Necesito hacer E/S en 'f'. De lo contrario, eso sería grandioso. (En realidad, tengo un tipo de datos a con una función para producir algún valor de tipo b, y la función debe ser lo suficientemente general para que algunos valores de tipo a puedan hacer E/S para producir b.) –
@strake : tenga en cuenta que hay un problema con Control.Monad.CatchIO. A saber, si está utilizando un transformador de mónada de cortocircuito (por ejemplo, ErrorT), es posible que no se comporte como esperaba. Si esto es un defecto de diseño o mal uso está abierto a la interpretación, pero debe tenerlo en cuenta. Ver http://andersk.mit.edu/haskell/monad-peel/ para más detalles. –