2012年12月1日土曜日

Isomorphism

Scalaz Advent Calendar!

Isomorphism


あるcase classに対してMonoidを定義したいとき、大体のものはTupleのMonoidのインスタンスが使えると思います。
こんなときにIsomorphismMonoidが使えます。

case class Person(name: String, age: Int)
object Person {
type T = (String, Int)
object PersonTuple extends (Person <=> T) {
def from = Function.tupled(Person.apply)
def to = Person.unapply _ >>> (_.get)
}
implicit object PersonMonoid extends IsomorphismMonoid[Person, T] {
def G = Monoid[T]
def iso = PersonTuple
}
}
view raw person.scala hosted with ❤ by GitHub
scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._
scala> mzero[Person]
res0: Person = Person(,0)
scala> Person("hoge", 2) multiply 3
res1: Person = Person(hogehogehoge,6)
view raw repl.scala hosted with ❤ by GitHub
Monoid以外の型クラスを定義したい時もこんな感じで使える。

implicit object PersonShow extends IsomorphismShow[Person, T] {
def G = Show[T]
def iso = PersonTuple
}
implicit object PersonOrder extends IsomorphismOrder[Person, T] {
def G = Order[T]
def iso = PersonTuple
}
view raw iso.scala hosted with ❤ by GitHub
このように、データ構造が同じもののインスタンスを流用する場合はIsomorphismが使えます。

<=>[A, B]はIso[Function1, A, B]のtype aliasで、to: A => Bとfrom: B => Aを定義します。
IsomorphismMonoidなどの型クラスは、toを使って実装されていることに注意しましょう。

0 件のコメント:

コメントを投稿