我想解除像mask_ :: IO a -> IO a
这样的函数来创建一个带有此签名的函数:lmask_ :: StateT Bool IO a -> StateT IO a
。
我的问题是,如何处理回调/第一个参数?以下代码是否不正确,因为它会在mask_
代码之前执行回调?
lmask_ :: StateT Bool IO a -> StateT Bool IO a
lmask_ m = do
r <- m
lift (mask_ (return r))
有一些通用的方法吗?像lift1 :: MonadTrans t => (m a -> m a) -> (t m a -> t m a)
这样的帮手?
答案 0 :(得分:2)
一般来说,如果不了解有关monad变压器的信息,这是不可能的。但是,对于所有标准monad变换器,有一种方法可以做到这一点。请参阅类型类MonadBaseControl
。它的超类MonadBase
定义了monad变换器堆栈中的底部monad(对于包含IO
的所有堆栈,IO
),MonadBaseControl
定义了如何将monad嵌入基地monad。它的实例有些复杂,但一旦定义了它们,就可以解除所有这些函数,如mask_
。
在您的情况下,包提升基础使用上述结构重新定义提升到IO
的标准MonadBaseControl
函数。特别是mask_
mask_ :: MonadBaseControl IO m => m a -> m a
可以专门用于StateT Bool IO a -> StateT Bool IO a
,因为StateT s
的实例为MonadBaseControl
。
另见Lift a function and its argument to a different monadic context。
答案 1 :(得分:1)
如果我们推广lmask_
以摆脱StateT Bool IO
,我们会得到类似的结果:
lift1 :: (Monad m, Monad (t m), MonadTrans t) => (m a -> m a) -> (t m a -> t m a)
lift1 f term = do
x <- term
lift (f (return x))