2011年12月22日木曜日

Reducer, Generator

昨日は #rpscala の忘年会がありました。
技術的な話がいっぱいで楽しかったです。
私も頑張らねば・・・!

Reducer

ある型CをMonoidである型Mへとマッピングするものです。

Identity#unit

値をモノイドへ変換します。

implicit lazy val m = IntProductReducer
implicit lazy val l = ListReducer[Int]
1.unit[IntMultiplication] assert_=== (1 ∏)
1.unit[List[Int]] assert_=== List(1)
view raw reducer1.scala hosted with ❤ by GitHub

Identity#cons, Identity#snoc

値と、モノイドである値を結合します。

5.cons(2 ∏) assert_=== (10 ∏)
(3 ∏).snoc(4) assert_=== (12 ∏)
5.cons(nil[Int]) assert_=== List(5)
List(1).snoc(1) assert_=== List(1, 1)
view raw reducer2.scala hosted with ❤ by GitHub

Identity#unitPure

モノイドへ変換した後、値を包みます。

1.pureUnit[List, IntMultiplication] assert_=== List(1 ∏)
100.pureUnit[Option, List[Int]] assert_=== Some(List(100))
view raw reducer3.scala hosted with ❤ by GitHub

MA#foldReduce

指定した型にまとめます。

List(1, 2, 3, 4).foldReduce[IntMultiplication] assert_=== (24 ∏)
nel(1, 2, 3, 4).foldReduce[List[Int]] assert_=== List(1, 2, 3, 4)
implicit lazy val s = DualReducer[String]
nel("Hello", "World").foldReduce[Dual[String]].value assert_=== "WorldHello"
view raw reducer4.scala hosted with ❤ by GitHub

Generator

Reducerを使ってコンテナの要素をまとめます。

GeneratorオブジェクトにはGeneratorのインスタンスが定義されており、Generator#reduceの実装が違います。

Generator#toとGenerator#fromはReducerと初期値とコンテナを渡します。
Generator#reduceはZeroが初期値となります。

Generator.FoldrGenerator[List].from(StreamReducer[String], List("Scala", "Scalaz"), Stream.empty) assert_=== Stream("Scala", "Scalaz")
Generator.FoldlGenerator[List].to(FirstReducer[String], mzero[FirstOption[String]], List("Scala", "Scalaz")) assert_=== "Scala".pure[FirstOption]
Generator.FoldMapGenerator[List].reduce(LastReducer[String], List("Scala", "Scalaz")) assert_=== "Scalaz".pure[LastOption]

Reducerのインスタンスはデフォルトでimplicit parameterではないので、いちいち宣言しないといけません。
unitやconsは普通に使える関数なだけに、とてももったいなく感じます。
しかし、Scalaz7では全てimplicitになっているので、Reducer関連の関数は使いやすくなるだろうと思います。

0 件のコメント:

コメントを投稿