我有一些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中嵌入异步是否有意义?不确定我是否在这里表达自己。
谢谢!
答案 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,这应该就是你所要做的。