2012-05-31 10 views
9

私は単純な作業をしています - ファイルから一連の行を読み取り、それぞれの行で何かをします。最初のものを除いて - 無視されるいくつかの見出しです。パイプラインで導管ドロップ機能を使用するには?

私はコンジットを試してみると思いました。

printFile src = runResourceT $ CB.sourceFile src =$= 
    CT.decode CT.utf8 =$= CT.lines =$= CL.mapM_ putStrLn 

クール。

は、だから今、私はちょうどオフ...最初の行をドロップしたいし、そのための機能があるように思われる -

printFile src = runResourceT $ CB.sourceFile src =$= 
    CT.decode CT.utf8 =$= CT.lines =$= drop 1 =$= CL.mapM_ putStrLn 

うーん - 今私は、ドロップが署名Sink a m()を入力してい気づきます。 - 誰かが私はeffectfullyいくつかの要素をドロップするようにパイプや使用ドロップのためのモナドのインスタンスを使用することができることを私に示唆したので、私はこれを試してみました:パイプのモナドのインスタンスのみのパイプに適用されるので、チェックを入力しない

drop' :: Int -> Pipe a a m() 
drop' n = do 
    CL.drop n 
    x <- await 
    case x of 
    Just v -> yield v 
    Nothing -> return() 

同じタイプのシンクは出力としてVoidを持っているので、私はこのように使うことはできません。

私はパイプとパイプコアをすばやく見て、パイプコアが最小限のライブラリだがドキュメントにはどのように実装されるかを示しているように、パイプコアには期待した機能があることがわかりました。

だから私は混乱している - 多分私は欠けている重要な概念があります..私は関数に

sequence :: Sink input m output -> Conduit input m output 

を見たしかし、それは(出力値があるとして、右のアイデアではないようです)

CL.sequence (CL.drop 1) :: Conduit a m()  

私はおそらくちょうど戻って、私は本当にすべてのストリーミングを必要としないよう怠惰-IOを使用します - しかし、私はそれを行うには、適切な方法を見て興味があると思います。まず

答えて

6

、単純な答え:

... =$= CT.lines =$= (CL.drop 1 >> CL.mapM_ putStrLn) 

長い説明:あなたはdropを実装することができる2つの異なる方法が実際にあります。いずれにせよ、入力から最初にn要素を落とします。それは次何をするかについての二つの選択肢があります。

  • は、それが入力ストリームから残りの項目のすべてを出力
  • スタートを行うの言うが

以前の動作はSinkを実行することになりものです(と我々のdropが実際に何をしているのか)、後者はConduitの挙動です。あなたは、実際にはモナド構図を通じて、前者から後者を生成することができます。

dropConduit n = CL.drop n >> CL.map id 

あなたが最初に説明するように、あなたがdropConduit使用することができます。これは、モナド組成と融解との違いを実証する良い方法です。前者は2つの機能が同じ入力ストリーム上で動作することを可能にするが、後者は一方の機能が他方の機能にストリームを供給することを可能にする。

私はベンチマークはしていませんが、モナド合成がより効率的になることは確かです。

+0

Hmm - 簡単な答えがうまくいきます、ありがとう。 dropConduitは 'Monad m => Int - > Pipe Void Void m()'と思っています。 – Oliver

+0

申し訳ありませんが、私はそれが適用されないコードベースの別のバージョンで作業しています。コンジット0.4では、 'sinkToPipe(CL.drop n)>> CL.map id'が必要です。問題は、Data.Conduit.Listの型が過度に制限されていることです。導管0.5はそれらを弛緩させるだろう。 –

+0

ああ、元気です。それは理にかなっている。 – Oliver

関連する問題