有没有办法拆分InputStream?

时间:2016-07-11 13:04:54

标签: haskell stream

我想知道是否有办法解决" /" /"复制" System.IO.Streams.InputStream包中的io-streams转发到两个处理阶段?

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

我可以看到,这可能不适用于流的需求驱动本质,但如果您需要处理几件事情,那么规范解决方案会是什么?你会建立一个"写到旁边的管道"?像:

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

我可能会去Arrow路由并将所有内容存储在元组中,但这会很快变脏,据我所知,io-streams没有箭头接口:

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

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

您可以通过多种方式执行此操作,但由于countEventslogEvents都是流上的折叠,outputFoldM的重复应用可能是最简单的。你不是在寻找一种分割流的方法,而不是一种链接折叠的方法。 outputFoldM将流转换为与将重复折叠操作应用于其中的结果相关联的新流,将结果写入一侧'如你所说。

>>> 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`

为了它的价值,我编写了一个补丁,可以将foldl库中的FoldFoldM应用到InputStreams https://github.com/snapframework/io-streams/issues/53。这将允许您无限期地应用许多同时折叠,根据您的需要区分镜头,因此符合您提到的箭头类比。这里应用了相同的折叠/接收器。我使用ApplicativeDo来编写一个大的折叠来做&#34;记录&#34;并收集统计数据并对其进行格式化同样的事情可以用应用程序运算符编写。

{-#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

&#34;美丽的折叠&#34;像foldl中的那些折叠很好,因为它们对于任何给定的框架都不是特殊的。您可以将myfolds无需更改应用于列表,Sequence,未装箱的向量,管道Producer,管道Source等等。它是独立的超可组合褶皱和水槽的纪律。