有没有办法拆分InputStream? [英] Is there a way to split an InputStream?

查看:80
本文介绍了有没有办法拆分InputStream?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有一种方法可以从io-streams 包中拆分"/复制" System.IO.Streams.InputStream 两个处理阶段?

I wonder if there is a way to "split"/"duplicate" an System.IO.Streams.InputStream from the io-streams package to be forwarded to two processing stages?

duplicate :: InputStream a -> IO (InputStream a, InputStream a)

我可以看到,这可能与流的需求驱动性质不兼容,但是如果您需要处理几件事,那么规范的解决方案是什么?您是否会构建写到一边"的管道?喜欢:

I can see that this probably doesn't work with the demand driven nature of streams, but what would be the canonical solution if you need several things to be processed? Would you build a pipeline that "writes to the side"? Like:

input >>= countEvents countIORef >>= logEvents loggerRef >>= output

我可能会走 Arrow 路线并将所有内容存储在元组中,但这很快就会变得肮脏,据我所知,没有 io-streams 的Arrow接口>:

I could probably go the Arrow route and store everything in tuples, but that is going to get dirty quickly and to my knowledge there is no Arrow interface to io-streams:

input >>= (countEvents *** logEvents) >>= output

有什么建议吗?

推荐答案

您可以通过多种方式执行此操作,但是由于 countEvents logEvents 都是流中, outputFoldM 的重复应用可能是最简单的.您并不是在寻找一种将流分离的方法,而是一种将折痕连接在一起的方法. outputFoldM 将一个流转换成一个新流,该流与对其应用重复折叠操作的结果相关联,如您所说,将结果写到一边".

You can do this a number of ways, but since countEvents and logEvents are both folds over the stream, repeated applications of outputFoldM is probably the simplest. You aren't looking for a way to split the stream so much as a way to link the folds. outputFoldM turns a stream into a new stream associated with the result of applying a repeated fold operation to it, writing the result 'to the side' as you say.

>>> let logger = IOS.inputFoldM (\() x -> print x >> putStrLn "----") ()
>>> let counter = IOS.inputFoldM (\a _ -> return $! a + 1) (0::Int)
>>> ls0 <- IOS.fromList [1..5::Int]
>>> (ls1,io_count) <- counter ls0
>>> (ls2,_) <- logger ls1
>>> IOS.fold (+) 0 ls2
1          -- here we see the "logging" happening from `logger`
----
2
----
3
----
4
----
5
----
15        -- this is the sum from the `fold (+) 0` that actually exhausted the stream
>>> io_count 
5         -- this is the result of `counter`


对于它的价值,我写了一个补丁程序以使其可以应用来自Fold s和 FoldM s.haskell.org/package/foldl-1.2.1/docs/Control-Foldl.html"rel =" nofollow> foldl 库转换为 InputStreams https://github.com/snapframework/io-streams/issues/53 .这将允许您无限期地应用多个同时折叠,并根据需要使用镜片来区分元素,从而适合您提到的箭头"类比.这是相同的折叠/水槽方式.我用 ApplicativeDo 编写了一个记录"并收集统计数据并格式化它们的大折叠.可以用应用运算符写同样的东西.


For what it's worth, I wrote a patch to make it possible to apply the Folds and FoldMs from the foldl library to InputStreams https://github.com/snapframework/io-streams/issues/53 . This would permit you to apply indefinitely many simultaneous folds, discriminating elements as you please with lens, thus fitting the Arrow analogy you mention. Here's the same folds/sinks applied that way. I used ApplicativeDo to write the one big fold that does "logging" and collects statistics and formats them. The same thing can be written with the applicative operators.

{-#LANGUAGE ApplicativeDo #-}

import qualified System.IO.Streams as IOS
import qualified Control.Foldl as L
import Control.Lens (filtered)

main = do
  ls <- IOS.fromList [1..5::Int]
  res <- L.impurely IOS.foldM_ myfolds ls
  putStrLn res

myfolds = do 
  sum_        <- L.generalize L.sum     -- generalize makes an 'impure' fold
  length_     <- L.generalize L.length  -- out of a pure one like sum or length
  odd_length_ <- L.generalize (L.handles (filtered odd) L.length)
  _           <- L.sink (\n -> print n >> putStrLn "-------")
  pure  (format sum_ length_  odd_length_)

 where  
  format sum_ length_ odd_length_ = unlines
     [ ""
     , "Results:"
     , "sum:        " ++ show sum_
     , "length:     " ++ show length_
     , "number odd: " ++ show odd_length_]

所以看起来像这样

>>> main
1
-------
2
-------
3
-------
4
-------
5
-------

Results:
sum:        15
length:     5
number odd: 3

foldl 中那样的美丽的折叠"折叠很不错,因为它们对任何给定的框架都不特殊.您可以将 myfolds 应用于列表, Sequence ,非装箱矢量,管道 Producer ,管道 Source 等.这是超可折叠和水槽的独立学科.

The "beautiful folding" folds like the ones in foldl are nice since they are not special to any given framework. You can apply the myfolds without alteration to a list, a Sequence, an unboxed vector, a pipes Producer, conduit Source etc etc.. It's a separate discipline of hyper-composable folds and sinks.

这篇关于有没有办法拆分InputStream?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆