使用单个Haskell管道将HTTP内容拆分为两个消费者



我真的无法弄清楚其中一些其他问题是否与我的问题足够相似,但我无法从中提取解决方案,所以我正在发布。请随时向我表明其他情况。

我有一个流程,我需要下载一个大的 CSV 文件,然后 1) 将其保存到磁盘,2) 处理它。我想使用 Haskell pipes,以及 pipes-http 和 pipes-csv 包来做到这一点。

显而易见的方法是有两个单独的管道:1) web -> 磁盘,然后 2) 磁盘 -> 进程。是否可以执行另一种拓扑,其中Web的输出拆分为两个消费者,一个保存,另一个处理?我觉得这可以更优雅,也可能更有效率。

如果是这样,如何进行拆分?文档中的任何地方都没有提到管道的拆分。

"在使用者之间拆分内容"的表达可能有点误导;您希望将所有字节发送给两个使用者中的每一个。但是Pipes.Prelude.tee把任何消费者都变成了管道,因此

producer >-> tee consumer1 >-> consumer2

将生产者提供给两个消费者。但是写入文件的特殊情况可能是最简单的Pipes.Prelude.chain,而不是消费者。 teechain 允许您在沿管道转发每个传入值之前对每个传入值执行某些操作。在这种情况下,我只是将每个连续的块写入句柄,然后再传递它:

import Pipes
import Pipes.HTTP
import qualified Pipes.ByteString as PB 
import qualified Pipes.Prelude as P
import qualified System.IO as IO
import qualified Data.ByteString as B
main = do
    req <- parseUrl "https://www.example.com"
    m <- newManager tlsManagerSettings 
    withHTTP req m $ resp -> 
      IO.withFile "file.txt" IO.WriteMode $ h -> 
        runEffect $ responseBody resp >-> P.chain (B.hPut h) >-> PB.stdout

我用PB.stdout结束了管道,您将在其中使用pipes-csv材料。使用tee,我也可以写

runEffect $ responseBody resp >-> P.tee (PB.toHandle h) >-> PB.stdout

最后一行。在"消费者"可以被视为折叠的地方,有将许多折叠组合在一起的Control.Foldl装置 - 以及任何其他设备。

相关内容

最新更新