我想知道是否有办法解决" /" /"复制" 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
有什么建议吗?
答案 0 :(得分:1)
您可以通过多种方式执行此操作,但由于countEvents
和logEvents
都是流上的折叠,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
库中的Fold
和FoldM
应用到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
等等。它是独立的超可组合褶皱和水槽的纪律。