2012年6月26日火曜日

Scala Tips / Reducer (2) - List

前回はIntとIntMultiplicationを例にReducerを基本的な使い方について説明しました。

次は可換でないモノイド演算の例として任意の型TとList[T]を結びつけるListReducerを使ってみましょう。TにはIntを使うことにします。

まずListReducerの取得ですが以下のようにListに格納する型を指定して取得します。

scala> val r = ListReducer[Int]
r: scalaz.Reducer[Int,List[Int]] = scalaz.Reducers$$anon$1@719bc401

ListReducerのunitメソッドを使ってIntをList[Int]にします。

scala> r.unit(3)
res9: List[Int] = List(3)

consメソッドを使って、2をList(3)の左側からモノイド演算すると以下になります。

scala> r.cons(2, r.unit(3))
res10: List[Int] = List(2, 3)

snocメソッドを使って、2をList(3)の右側からモノイド演算すると以下になります。

scala> r.snoc(r.unit(3), 2)
res11: List[Int] = List(3, 2)

Listの場合は、左側からモノイド演算した場合と、右側からモノイド演算した場合で結果が変わってきます。前回説明したIntやIntMultiplicationの場合は結果が変わらないので、これは重要な性質の違いになります。結果が変わらないモノイドは可換モノイドと呼びます。今のところScalazで、単なるモノイドと可換モノイドを区別する手段はありません。

List

参考のために以上の処理をListを直接使って書くと以下になります。

scala> List(3)
res0: List[Int] = List(3)

scala> 2 :: List(3)
res1: List[Int] = List(2, 3)

scala> List(3) :+ 2
res2: List[Int] = List(3, 2)

ノート

アルゴリズムを記述する場合、一般的には普通にList(あるいはSeq)を使えば簡単でよいわけですが、アルゴリズムの操作対象をReducerにすることで、List以外の任意のデータ構造に対してアルゴリズムを適用することができるようになります。

この場合の条件は、操作対象がモノイドであるということです。モノイドを操作するアルゴリズムはReducerを対象にすることで、モノイドの性質を持つ任意のオブジェクトを操作対象にすることができるようになります。

モノイドを操作するアルゴリズムでは、ReducerではなくMonoidを操作対象にする選択肢もあります。このあたりの得失は別途考えてみたいと思います。

諸元

  • Scala 2.9.2
  • Scalaz 6.0.4

0 件のコメント:

コメントを投稿