conduitはストリームデータを扱うためのライブラリです。簡単に組み合わせることができるようになります。アプローチはこれらのものとは異なります。conduitは簡単に理解して利用できるものになることを一番の目的としています。純粋なコードに例外を持ち込みません。シンプルで効率の良い、高レベルのインターフェースが提供されるようになりました。殆どなくなったはずです。強力な機能が組み込まれました。して振る舞うことを可能にします(訳注:今のところ実装はされていない模様)。ひと通りのチュートリアルがHaddock自身に含まれています。使い始めるにあたっては、まずこれを読むのをお勧めします。(finalizationの動作の詳細とか)。attoparsec-conduitやzlib-conduitしか含まれていません。yesodあるいはもっといろいろな古いconduitに依存したパッケージは含まれません。それらは十分にテストしてリリース準備が整い次第リリースされる予定です。これらの問題や、リリースについての質問をGithubのIssueに挙げないこと。Yesodチームがリリースの準備が十分にできたと判断した時に、リリースは行われます。この記事の残りの部分で、conduitの使い方の洗練された例を紹介します。ベースになっています。ネットワークサーバとクライアントを作るための高レベルのライブラリです。基本的なサンプルから、違うアプリケーションを作っていきます。次のコードから始めましょう。(訳注:Applicationの型を補足)。()一番シンプルな例、echoでも実装してみましょうか。sinkここで必要になるのは、ソースとシンクをつなぐことだけ。あとはconduitが全部面倒を見てくれます。受け取ったデータは即座に正しくシンクに送られます。終了についての明示的なコードが無いこと。これらに注意されたい。これで十分実用的なのである。このTCPサーバは完全に並行にリクエストを処理する実装になる。接続ごとに独立したスレッドが作られる。オブジェクトをひとつ作るコストと大して変わらない。したがって、サーバオプションとしての並行度の指定は必要がない。タイムアウトの設定も必要ない。Haskellのスレッドは(FFIなどを使わない限り)いつでも安全にキャンセルできる。標準が提供するI/Oライブラリはすべてキャンセル可能なAPIの呼び出しによって行われる。これはあまりにもつまらない例ですね。エコーバックする際に大文字化するものでも書いてみましょう。このタスクに必要となるものを列挙します。それは正しくも楽しくもないので、ちゃんとやることにします)。次に1文字ずつ大文字に変換します。最後に、文字データをバイナリに再エンコードして出力に送ります。幾つか追加のimportが必要になります。これがそのコードです。sinkなんという宣言的なアプローチでしょう。次のステップにつながれているだけ!別の例を考えましょう。受け取った各チャンクに対して、そのサイズを表示します。sinkなにやらパターンが見えてきました。ソースとシンクを端において、その間をconduitのパイプラインでつなぐ。その考えを進めて、パターンを抽象化してみましょう。"\n")最初の例だと、こうなります。utf8さてこうなると、一つ疑問が生じます。それがConduitよりも真に強力だからです。強力な機能が実現できます。同じ処理を接続が切れるまで繰り返すものでした。なにか制御フローを追加してみましょう。エコーを繰り返すというものです。読んでデータを読み書きするようになりました。他のI/Oとインターリーブ簡単なファイルサーバを作りましょう。ファイル名を送ると、サーバがそのファイルの内容を返してくるようなものです。これを行うためには、わずかにプログラムの型を変更する必要があります。IOモナドを使うようにします。すれば、例外安全にファイルアクセスができるようになります。'\r'))ここでは意図的にファイル名のエンコーディングを無視しています。説明が億劫なので、単にascii文字列としてアンパックしています。’\r’を手動で取り除いています。これを取り除く処理を入れるべきでしょう。入力がある限り内部の関数を実行する、便利関数です。さっきみたいな“quitアプローチ”と組み合わせての、手動ループ制御もできます。クライアントのためのインターフェースもあります。printここには特に見所はありません。このセクションの目的は、最後の例のための準備です。HTTPプロキシサーバを作れるようにするというのがあります。(多段にネストしたIterateeを使えば、実際にはできます。それは恐るべき苦痛でもあります)。簡単なネットワークプロキシサーバを作ってみましょうか。これは次のように動作します。これは別にそんなに難しくありません。2つの別々のソケットに対して、sendとrecvをすれば良いだけです。違うソースを使う処理に簡単にインターリーブできるということです。インターリーブが難しくなるという、ちょうど逆転が起こるのです。用意することにしました。それがconnect-and-resumeと呼ばれるものです。なんだか恐ろしげに聞こえますが、大丈夫、怖くないですよ。ソースにシンクを接続し、シンクが終了するまで実行して、結果を返します。sourceを再度ソースとして使います。それの繰り返しになります。最初に、main関数を見ていきましょう。クライアントからの接続を受け付けます。proxyプロキシの処理では、ポートとホスト名が必要になります。次に、そのサーバへ接続します。ポートとホスト名のペアを読み込むヘルパ関数を定義しましょう。用いてproxy関数を定義しましょう。ソースをシンク、getPortHostに接続して、クライアントの設定と新しいResumableSourceを受け取ります。これをリードループ(proxyLoop)に渡します。toClient)proxyLoopからは、まず接続成功メッセージをクライアントに送ります。サーバから受け取るためのResumableSourceを作り、ループを開始します。where内部のループは(訳注:ちょっとややこしそうに見えるけど)とても直接的です。上の4ステップを忠実にこなしているだけです。fromServer'ここでは2つのトリックが用いられています。あるResumableSourceに対して動作します。resuming”ということです。これらは使い終わると自動的に閉じられ(訳注:リソース解放など)ます。ResumableSourceは、あとでの利用のためにすぐには閉じません。これを行うためには明示的に閉じてやる必要があります。これをやるのは簡単です。$$$$+-演算子を使います。やりたいことが所謂「コーナーケース」にあるような場合には、とても便利に使えます。完全なソースGistで完全なソースが見られます。このチュートリアルが、Conduitの強力さと、その使い方を示す助けになれば幸いです。proxyLoopを、スレッドを用いて実装するというのがありました。私はconnect-and-resumeのデモのために、故意にproxyLoopをこのように書きました。スレッドを用いれば次のようにも実装できます。使うと恐ろしくシンプルに。接続を並行に行うというやりたい処理をまさにそのまま書けてしまった。全体のソースはこちら。Bootswatch.。