有一个类型为 Producer ByteString IO ()
的生产者和一个类型为 Pipe ByteString a IO ()
的管道,我如何编写一个效果,这将导致 IO a
什么时候运行?
这是我最好的尝试:
{-# LANGUAGE ScopedTypeVariables #-}
import Pipes
import Data.ByteString
run :: forall a. IO a
run = runEffect $
(undefined :: Producer ByteString IO ()) >-> (undefined :: Pipe ByteString a IO ())
失败并显示以下内容:
Couldn't match type `Void' with `()'
Expected type: IO a
Actual type: IO ()
In the expression:
runEffect
$ (undefined :: Producer ByteString IO ())
>-> (undefined :: Pipe ByteString a IO ())
In an equation for `run':
run
= runEffect
$ (undefined :: Producer ByteString IO ())
>-> (undefined :: Pipe ByteString a IO ())
最佳答案
通常,您需要将Producer
与Consumer
组合起来,以获得可由runEffect 运行的
。这不是你在这里得到的,但幸运的是,除了 Effect
runEffect
之外,还有更多方法可以消除 Proxy
。
总结一下我们所拥有的,这个组合以 Producer
结束。
pipe :: Producer a IO ()
pipe = (undefined :: Producer ByteString IO ()) >-> (undefined :: Pipe ByteString a IO ())
Pipes.Prelude
模块包含许多其他方法来消除 Producer
,例如 Pipes.Prelude.last
last :: Monad m => Producer a m () -> m (Maybe a)
获取a
的最通用方法可能是使用Pipes.Prelude.fold
fold :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Producer a m () -> m b
这类似于 runEffect
,只是它将 Producers
缩减为它们的底层 Monad
。因为这就是我们所拥有的,所以它会很好用。下面是我们如何实现 Pipes.Prelude.head
slowHead = fold (\res a -> res <> First (Just a)) mempty getFirst
值得注意的是 slowHead
消耗了整个 Producer
(因此执行了所有需要的效果)而 Pipes.Prelude.head
只执行第一个。它更懒惰!
关于haskell - 连接 Producer 和 Pipe 以提取结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19414549/