2016-07-11 10 views
1

io-streamsパッケージのSystem.IO.Streams.InputStreamを「分割」/「複製」して2つの処理段階に転送する方法があるのだろうか?InputStreamを分割する方法はありますか?

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

私はこれはおそらく、ストリームの需要駆動し、自然と動作しないことがわかります、しかし、あなたはいくつかのことが必要な場合は正規のソリューション処理されるべきでしょうか?あなたは "側に書いて"パイプラインを構築しますか?同様に:

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

私はおそらくArrowルートを行くとタプル内のすべてを保存し、それはすぐに汚れて取得する予定ですし、私の知識にio-streamsへの矢印インタフェースはありませんでした:

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

どれでも勧告?

+2

あなたが参照している 'InputStream'がわかるように、インポートを含めるべきです。このタイプはいくつかの異なるモジュールが定義されています:[(リンク)](http://hayoo.fh-wedel.de/?query=InputStream) – ErikR

+0

1つのオプションは、1つの入力から要素を受け取る個別のスレッドを作成することです['Chan'](https://hackage.haskell.org/package/base-4.8.1.0/docs/Control-Concurrent-Chan.html#t:Chan)、2つ(またはそれ以上)の出力チャンネルに送信します。そして、[System.IO.Streams.Concurrent](https://hackage.haskell.org/package/io-streams-1.3.5.0/docs/System-IO-Streams-Concurrent.html)を使ってそれらを適切にバインドします。 –

答えて

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` 

、私はInputStreamshttps://github.com/snapframework/io-streams/issues/53foldlライブラリからFold sおよびFoldM秒を適用することを可能にするためのパッチを書きました。これは、あなたが無限に多くの同時折り目を適用することを可能にします。これは同じ折り目/シンクがそのように適用されています。私は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_] 

だから、これは「美しい折りたたみは」foldl中のもののように折るこの

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

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

のように見えるがいいです。 myfoldsを変更せずにリストに追加することができます。Sequence、ボックス化されていないベクトル、パイプProducer、コンジットSourceなどです。これは、超コンポジットの折り目とシンクの別個の規律です。

+0

私はinputFoldMがそのように使用できることを本当に知りませんでした。ありがとう! – fho

+0

私は、返されたアクションがアキュムレータを実際に初期値にリセットすることに気がつきました。そのため、各フレーム*と*をアキュムレータに依存する(演算平均のように)何かを返す計算では、これは機能しません。 – fho

関連する問題