2011年12月15日木曜日

Empty, Each, Plus

小粒な型クラスその2

Empty

空を定義します。

<∅>

コンテナの型と要素の型を渡し、空のコンテナを返します。
∅が打ちにくい。

implicit lazy val IkamusumeEmpty: Empty[Ikamusume] = new Empty[Ikamusume] {
def empty[A]: Ikamusume[A] = Ikamusume[A]()
}
<∅>[List, Int] assert_=== nil[Int]
<∅>[Ikamusume, Int] assert_=== Ikamusume[Int]()
view raw empty1.scala hosted with ❤ by GitHub

Each

繰り返し処理を定義します。

foreach, |>|

関数を渡し、処理を繰り返します。
|>|はforeachのエイリアスです。

implicit lazy val IkamusumeEach: Each[Ikamusume] = new Each[Ikamusume] {
def each[A](e: Ikamusume[A], f: A => Unit): Unit = e.value.foreach(f)
}
Ikamusume(2, 3, 5, 7, 11).foreach(print)
Ikamusume(1, 1, 2, 3, 5) |>| print
scala> implicit lazy val IkamusumeEach: Each[Ikamusume] = new Each[Ikamusume] {
| def each[A](e: Ikamusume[A], f: A => Unit): Unit = e.value.foreach(f)
| }
IkamusumeEach: scalaz.Each[Ikamusume] = <lazy>
scala> Ikamusume(2, 3, 5, 7, 11).foreach(print)
235711
scala> Ikamusume(1, 1, 2, 3, 5) |>| print
11235
view raw each1.scala hosted with ❤ by GitHub

Plus

plusという2つの値を結合する関数を持つ。
Semigroupよりも、短絡評価ORの性質が強い。

<+>, <+>:

<+> は2つのコンテナを結合します。
<+>: は要素の型にPureのインスタンスが必要で、要素を渡して包み、結合します。

implicit lazy val IkamusumePlus: Plus[Ikamusume] = new Plus[Ikamusume] {
def plus[A](a1: Ikamusume[A], a2: => Ikamusume[A]): Ikamusume[A] = Ikamusume(a1.value ++ a2.value: _*)
}
Ikamusume('Scala) <+> Ikamusume('Scalaz) assert_=== Ikamusume('Scala, 'Scalaz)
nel(1, 2, 3) <+> nel(4, 5, 6) assert_=== NonEmptyList(1, 2, 3, 4, 5, 6)
1.some <+> 2.some assert_=== Some(1)
none <+> 1.some assert_=== Some(1)
"Scalaz".left[Int] <+> 100.right[String] assert_=== Right(100)
"Scalaz".left[Int] <+> "Scala".left[Int] assert_=== Left("Scalaz")
1 <+>: nel(2, 3) assert_=== NonEmptyList(1, 2, 3)
'a' <+>: 'z'.some assert_=== Some('a')
view raw plus1.scala hosted with ❤ by GitHub

今回紹介した型クラスは関数がそこまで多くないのであまり自分で定義することはないだろうけど、定義されたものを使う分にはとても便利です。

0 件のコメント:

コメントを投稿