2012年3月13日火曜日

関数型とデータフロー(2)

要求開発アライアンスのセッション『Object-Functional Analysis and Design: 次世代モデリングパラダイムへの道標』で使用するスライドについて背景説明を行っています。

今回は背景説明第10弾として、「関数型とデータフロー(2)」として用意した以下の図を説明します。


動作

図の動作は、入力されたInt値からデーターフロー的な処理を4段行い、最後に並行して計算した結果を足しこんで最終的な結果の値を計算しています。

これを、関数型の以下の記述方式で実現しています。

3 |> (plus5 &&& mul10) >>> (plus5 *** mul10) >>> plus5.first >>> plus5.second >>> join2

これは、Scalazの型クラスArrowで実現しています。Arrowのメカニズムは、以下のページが詳しいです。

構成要素

データフローの格段の処理を細かく見ていきましょう。


Fork
3 |> (plus5 &&& mul10)

「分岐」とすると条件分岐と紛らわしいのでForkとしておきました。値を2つのパイプラインにForkして、それぞれに関数plus5とmul10を適用します。結果は、タプルで返ってきます。

並列計算
(8, 30) |> (plus5 *** mul10)

タプルに格納された2つの値に対して並列演算します。結果は、タプルで返ってきます。

First
(13, 300) |> plus5.first

並列計算のパイプラインの1番目のパイプラインに関数を適用します。結果は、タプルで返ってきます。

Second
(18, 300) |> (plus5 *** mul10)

並列計算のパイプラインの2番目のパイプラインに関数を適用します。結果は、タプルで返ってきます。

結合

結合は、以下の関数で行っています。この関数では、タプルに格納された値を足しあわせています。

val join2 = { fs: (Int, Int) => fs.fold(_ + _) }

ノート

Scalazが提供するArrowまわりの部品を使って、それなりに複雑なデータフローを記述することができることが分かりました。もちろん、本格的なデータフローをここで紹介した部品だけで構築するのはちょっと難しそうですが、関数型の他の機能と合わせ技で色々なことが可能になりそうです。

0 件のコメント:

コメントを投稿