haskell - 连接 Producer 和 Pipe 以提取结果

标签 haskell pipe haskell-pipes

有一个类型为 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 ())

最佳答案

通常,您需要将ProducerConsumer 组合起来,以获得可由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/

相关文章:

haskell - uncurry 函数的类型签名

c - 在我的 shell 中实现管道

c - 将 sed 的输出(从 grep 传送)重定向到 C 程序中的文件

haskell - 使用管道 4.0 折叠流的子集

haskell - 优化 Haskell、管道、attoparsec 和容器中的内存

haskell - 将 `(->) ((->) a b)` 实现为应用仿函数的最佳方法是什么?

haskell - 将 state monad 与 costate comonad 结合

haskell - 安全地将文本序列化为字节串

java - 尝试在java中运行从cpp文件创建的exe文件

json - 使用 Haskell 对巨大的 json 数组进行子采样