有没有办法拆分输入流



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

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

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

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

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

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

有什么建议吗?

您可以通过

多种方式执行此操作,但由于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 s应用于InputStreams https://github.com/snapframework/io-streams/issues/53。这将允许您无限期地同时应用许多折叠,随心所欲地使用镜头区分元素,从而符合您提到的箭头类比。这是以这种方式应用的相同折叠/水槽。我曾经用ApplicativeDo来编写一个大折叠,它执行"日志记录"并收集统计信息并格式化它们。同样的事情可以用应用运算符编写。

{-#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等。这是一个由超可组合的褶皱和水槽组成的独立学科。

相关内容

  • 没有找到相关文章

最新更新