Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell mapMonadTrans::MonadTrans xT=>;(m a->;n b)>;xT m a->;xT n b_Haskell_Monads_Monad Transformers - Fatal编程技术网

Haskell mapMonadTrans::MonadTrans xT=>;(m a->;n b)>;xT m a->;xT n b

Haskell mapMonadTrans::MonadTrans xT=>;(m a->;n b)>;xT m a->;xT n b,haskell,monads,monad-transformers,Haskell,Monads,Monad Transformers,问题是这个。我有: f :: MonadIO m => ReaderT FooBar m Answer; f = (liftIO getArgs) >>= ... 我需要用修改过的参数运行这个。然而,由于m是未知的,我不能简单地使用 mapReaderT (withArgs args) :: ReaderT r IO b -> ReaderT r IO b 因为我需要以某种方式将(with args args)转换为所有m的m 我发现的一种可能性是用args定义我自己

问题是这个。我有:

f :: MonadIO m => ReaderT FooBar m Answer;
f = (liftIO getArgs) >>= ...
我需要用修改过的参数运行这个。然而,由于m是未知的,我不能简单地使用

mapReaderT (withArgs args) :: ReaderT r IO b -> ReaderT r IO b
因为我需要以某种方式将(with args args)转换为所有m的m

我发现的一种可能性是用args定义我自己的,因此:

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;
};
导入系统环境(setArgs、freeArgv);
withArgv new_args act=do{
pName我相信解决了这个问题。在中讨论了它。

该软件包将完成此操作。我想您希望从中获得函数
liftIOOp\uu

具体来说,

liftIOOp_ (withArgs newArgs) f

应该做你想做的事。你也可以用
liftIOOp
函数来提升像
bracket
这样的东西。

你要寻找的部分是将单子同态提升到单子变换器中

class MonadHoist t where
    hoist :: (Monad m, Monad n) => (forall a. m a -> n a) -> t m a -> t n a

    t :: Monad m => t Identity a -> t m a
    t = hoist (return . runIdentity)
也就是说,给定从
m
n
的一元同态
f
,您可以使用提升机获得从
tm
tn
的一元同态

单子同态略强于上述类型,即它负责维护单子定律

f . return = return
f . fmap g = fmap g . f
f . join = join . f . fmap f
         = join . fmap f . f -- by the second law
         = (>>= f) . f       -- >>= in terms of join
请注意,我在
起重机
类型中偷偷使用的量词,
单体重量
几乎在所有实例中都需要这种灵活性!(
阅读器
恰好是一种不需要的情况。试着在没有它的情况下编写MaybeT。)

Monad transformers通常可以实例化此类。例如:

instance MonadHoist (StateT s) where
    hoist f (StateT m) = StateT (f . m)

instance MonadHoist (ReaderT e) where
    hoist f (ReaderT m) = ReaderT (f . m)

instance MonadHoist MaybeT where
    hoist f (MaybeT m) = MaybeT (f m)
我们目前没有在
transformers
mtl
包中提供它,因为它需要
Rank2Type
,但它的实现非常简单

如果有足够的需求,我很乐意将其打包成一个
monad extras

现在,我说了这一部分,因为虽然这回答了你文章主题中的类型给出的问题,但它并没有解决与你的问题相关的大部分文本所反映的需求


为此,您可能希望遵循luqui的建议。=)

似乎您可以使用
runReaderT
获得您想要的效果:

*> :t withArgs [] (runReaderT f FooBar)
withArgs [] (runReaderT f FooBar) :: IO Answer

其中
FooBar
是一些数据构造函数,而
f
的定义如上所述。

如果删除
f
上的类型签名会怎么样?我想知道约束到
MonadIO
是否限制太多。我需要在
f
中进行I/O操作。否则,那就太夸张了。(实际上,我有一个数据类型a,其中有一个函数可以产生一些类型b的值,并且该函数必须足够通用,以便某些类型a的值可以进行I/O来产生b。)@strake:注意Control.Monad.CatchIO有一个问题。也就是说,如果您使用的是短路Monad变压器(例如ErrorT)有可能它的行为不符合您的预期。这是否是设计缺陷或误用是可以解释的,但您应该了解它。详细信息请参阅。它可能,但不幸的是,它非常令人困惑。它是如何使用的?@strake,不幸的是,我从未使用过它,我只记得它正在讨论中。也许还有一个问题是这样的按顺序?A!正是我需要的。谢谢!好主意。事实上,(正如我刚才注意到的),其他人意识到了这一点: