在实现MonadIO的Monad中嵌入async

时间:2014-06-06 21:19:17

标签: haskell haskell-pipes

我有一些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 :这显然不会编译,因为runEffect将返回MonadIO m => m ()async需要IO a。有没有办法做到这一点?或者我是不是强迫我的管道在IO monad中包含效果?

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

谢谢!

2 个答案:

答案 0 :(得分:1)

  

这显然无法编译,因为runEffect将返回MonadIO m => m ()而异步需要IO a

那不太对劲。 IO MonadIO的一个实例,因此runEffect的输出可以传递给async或者MaybeT IO ()。一个函数MonadIO(也是一个IO (Async a)实例)。

我认为您要找的是liftIO :: IO a -> m a,这会让您将async返回的特定MonadIO“提升”为多态... liftIO $ async $ do runEffect $ fromInput input >-> pipeline performGC 类型在你的类型签名。

IO

没试过编译这个;您可能还需要解除其他{{1}}部分功能。

  

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

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

答案 1 :(得分:0)

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

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

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

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

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

我认为我们应该将两个图书馆的开发人员都指向这个问题,因为否则,我不知道如何获得我想要的类型。

修改1 :我在do not want to add MonadIO support to async找到了这个问题。

编辑2 :我喜欢Pipes库,但我很难找到解决此问题的方法。如果我找不到这个问题的答案,那么I might use buffer from Data.Conduit.Async因为它似乎很好地解决了这个问题。

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

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

只要你为Monad实现MonadBaseControl IO,这应该就是你所要做的。