Haskell 使用“MonadBaseControl”API
我目前正在使用Bryan O'Sullivan的库,对扩展Haskell 使用“MonadBaseControl”API,haskell,monads,monad-transformers,Haskell,Monads,Monad Transformers,我目前正在使用Bryan O'Sullivan的库,对扩展with resource函数有疑问。 我想将with resource函数的签名从(MonadBaseControl IO m)=>池a->(a->m b)->m b更改为(MonadBaseControl IO m)=>池a->(a->m(Bool,b))->m b 我想要实现的是,操作应该返回(Bool,b)元组,其中布尔值指示借用的资源是否应该 被放回池中或销毁 现在,我当前的实现如下所示: withResource :: for
with resource
函数有疑问。
我想将with resource
函数的签名从(MonadBaseControl IO m)=>池a->(a->m b)->m b
更改为(MonadBaseControl IO m)=>池a->(a->m(Bool,b))->m b
我想要实现的是,操作应该返回
(Bool,b)
元组,其中布尔值指示借用的资源是否应该
被放回池中或销毁
现在,我当前的实现如下所示:
withResource :: forall m a b. (MonadBaseControl IO m) => Pool a -> (a -> m (Bool, b)) -> m b
{-# SPECIALIZE withResource :: Pool a -> (a -> IO (Bool,b)) -> IO b #-}
withResource pool act = fmap snd result
where
result :: m (Bool, b)
result = control $ \runInIO -> mask $ \restore -> do
resource <- takeResource pool
ret <- restore (runInIO (act resource)) `onException`
destroyResource pool resource
void . runInIO $ do
(keep, _) <- restoreM ret :: m (Bool, b)
if keep
then liftBaseWith . const $ putResource pool resource
else liftBaseWith . const $ destroyResource pool resource
return ret
withResource::对于所有m a b。(MonadBaseControl IO m)=>池a->(a->m(布尔,b))->MB
{-#专门化资源::池a->(a->IO(Bool,b))->IO b}
withResource pool act=fmap snd结果
哪里
结果::m(Bool,b)
结果=控制$\RUNIIO->掩码$\restore->do
参考资料我觉得这种方法存在一个根本问题。对于StM ma
与a
相等/同构的单子,它将起作用。但对于其他单子来说,这将是一个问题。让我们考虑<代码> MayBET IO < /代码>。a->MaybeT IO(Bool,b)
类型的操作可能会失败,因此不会产生Bool
值。代码在哪
void . runInIO $ do
(keep, _) <- restoreM ret :: m (Bool, b)
...
会打印出来的
destroy
return
destroy
return
对于空列表,不会打印任何内容,这意味着不会在函数中调用清理
我不得不说,我不知道如何更好地实现你的目标。我会努力探索签名的方向
withResource :: forall m a b. (MonadBaseControl IO m)
=> Pool a -> (a -> IO () -> m b) -> m b
其中,IO()
参数将是一个函数,当执行该函数时,将使当前资源无效并将其标记为已销毁。(或者,为了方便起见,将IO()
替换为m()
)。然后在内部,由于它是基于IO
,我只需要创建一个助手MVar
,通过调用
函数,最后根据值返回或销毁资源。粗略一看就可以了。有什么困扰你的?@luqui让我有点困扰的是,我必须运行runInIO
两次,这会导致代码更加冗长。有没有更好的方法来打开IO monad中的ret
(第一次runInIO
调用的结果)?非常感谢您提供的有用答案。我现在可以看到“MaybeT”和“ListT”单子的问题了。。。再次感谢!
withResource :: forall m a b. (MonadBaseControl IO m)
=> Pool a -> (a -> IO () -> m b) -> m b