3

我有一些pipes-concurrency看起来像这样的代码:

-- this won't compile but will give you the gist of what's happening
pipeline :: MonadIO m => Consumer a m ()
main = do
    (output, input) <- spawn Unbounded
    async $ do runEffect $ fromInput input >-> pipeline
               performGC
    -- skipped the `output` pipeline code.

问题 1:这显然不会编译,因为runEffectwill returnMonadIO m => m ()asyncrequires IO a。有没有办法做到这一点?还是我被困在强迫我的管道包含 IO monad 中的效果?

问题 2:在实现 MonadIO 的 Monad 中嵌入异步是否有意义?不确定我是否在这里很好地表达了自己。

谢谢!

4

2 回答 2

2

这显然不会编译,因为runEffect会返回MonadIO m => m ()并且异步需要IO a

这不太对。IO 一个实例,MonadIO因此您的输出runEffect可以传递给async或例如一个函数MaybeT IO ()(也是一个MonadIO实例)。

我认为您正在寻找的是liftIO :: IO a -> m a,它可以让您将IO (Async a)返回的特定“提升”为类型签名中要求async的多态类型。MonadIO

...
liftIO $ async $ do runEffect $ fromInput input >-> pipeline
           performGC

没有尝试编译这个;您可能还需要提升IO功能的其他部分。

问题 2:在实现 MonadIO 的 Monad 中嵌入异步是否有意义?不确定我是否在这里很好地表达了自己。

当然,如果你想在一些 monad 堆栈中进行并发,为什么不呢?

于 2014-06-06T22:00:16.887 回答
0

我正在尝试做完全相同的事情,这是问题的核心:

$ :t async . runEffect
async . runEffect :: Effect IO a -> IO (Async a)
$

简而言之,我应该提供这种类型的东西。但我真正想要的类型是:

someAsync . runEffect :: MonadIO m => Effect m a -> m (Async a)

不幸的是,我不确定如何做到这一点。目前这似乎是不可能的,但不是因为管道并发,而纯粹是因为异步的类型。

我认为我们应该向这两个库的开发人员指出这个问题,因为否则,我看不到如何获得我想要的类型。

编辑 1:我发现他们不想将 MonadIO 支持添加到 async的问题。

编辑 2:我喜欢 Pipes 库,但我很难找到解决这个问题的方法。如果我找不到这个问题的答案,那么我可能会使用 Data.Conduit.Async 中的缓冲区,因为它似乎很好地解决了这个问题。

编辑 3:似乎这个问题的正确解决方案是使用lifted-async。该库提供以下方法:

async :: MonadBaseControl IO m => m a -> m (Async (StM m a))

只要您为 Monad 实现 MonadBaseControl IO,那应该完全符合您的要求。

于 2015-02-11T22:18:46.070 回答