Haskell による並列・並行プログラミング読書会 #5 に参加しました #umekitahs

umekitahs.connpass.com

隔週ペースで続いている読書会です。前々回の #3 には参加できず、前回の #4 には参加しましたがブログを書き忘れてました。

宿題が出ていたのですが、今日までに回答を準備できていた人がいなかったため、まずは宿題をやる、ということで進めました。そして、そのまま宿題だけで終わってしまいました。本の続きを読むのはまた次回です。

宿題は、「4.2.1 生産者の流量制限」でした。前節のパターンでは、生産者が消費者より速い場合に生産者がどんどん長いリストを作ってしまう問題があるため、それを解決しよう、という話でした。しかし本では、型定義とアイデアだけ示されて、その実装は「読者への演習問題とするので、掲載しません」となっていました。

そこで宿題に取り組むわけですが、これが意外と難しい。そもそも、本文に書かれているアイデアが理解できない。それに、Haskell の理解だってまだあやふや。考えたり調べたりしているうちに、時間がどんどん過ぎていきました。

まず、IList 型に追加されたコンストラクタ Fork (Par ()) (IList a) がよく分からない。Par って何に使うんだ? ・・・いや、本文にちゃんと書いてあるんですけど、その内容が理解できなかったわけですね。

つまり、ここで与えられる Par は「続きの要素を生成する」処理であり、消費者は IList を処理していく中で Fork を見つけたら、その処理を fork する、ということでした。続きの要素を生成する処理というのは streamFromList 関数内の loop 関数です。

生産者は、最初は loop 関数でどんどんチャンクを生成しますが、ある一定数に達したら、loop 関数の実行をする代わりに loop 関数を内包する Fork を生成します。これによって、チャンクの生成が抑えられます。

消費者は、チャンクを消費していきますが、その途中で Fork に出会います。このときに fork を行ないます。ここでチャンク生成が再開され、チャンク消費も進むことになります。

こうして書いてみるとシンプルな仕組みでうまくやっているな、と感心します。自力では回答にたどり着けず、Stack Overflow の力を借りましたけど・・・。

次回は再来週の予定です。

umekitahs.connpass.com