2012年2月3日金曜日

Tagged, Union

Scalaz7のSNAPSHOTがリポジトリにあったので、いろいろ試しています。

設計が大幅に変わったので6系にべったりだと移行はかなり大変な気がします。

Tagged

Scalaz7ではNewTypeがなくなり、代わりにTagged Typesというものが入りました。

これは既存の型にタグを付けることで、コンパイラに別の型のように見せることができます。
さらに、この型は元の型が必要な場合にはunboxされるという素敵なものです。

trait Foo
type Bar = Int @@ Foo
view raw tagged1.scala hosted with ❤ by GitHub

@@がタグを付けるためのものです。
ここではIntにFooタグを付けたものをBarとしました。

val bar: Bar = Tag[Int, Foo](100)
lazy val f: Bar => Int = 100 |+| _
f(bar) assert_=== 200
// f(100) Error
view raw tagged2.scala hosted with ❤ by GitHub

この型を取る関数にIntを渡すとコンパイルエラーになります。

val foobar: Long @@ Foo = Tag(10)
lazy val g: Long @@ Foo => Long = 100L |-| _
g(foobar) assert_=== 90L
type Baz[T] = T @@ Foo
val baz: Baz[String] = Tag("Scalaz")
lazy val h: Baz[String] => String = (_: String).multiply(2)
h(baz) assert_=== "ScalazScalaz"
view raw tagged3.scala hosted with ❤ by GitHub

エイリアス付けるとTagを使ったときに推論が効かないので、@@を直接書くか、型パラメータをとるようにするといいです。

Scalaz7ではNewTypeを使っていた殆どはTagged Typesに置き換えられました。
あまりなにも考えずNewTypeばかり継承していると移行が大変ですのでこのことも考えておきましょう。 (体験者談)

Tagged Typesについて詳しく知りたい場合はこちらを。

Union

最近入って、SNAPSHOTにもまだ入ってないもの。
型の和が簡単に作れてしまう優れもの。
これもunboxされる。

type Hoge = UnionTypes.t[Int]#t[String]
type Huga = UnionTypes.t[Long]#t[Double]
view raw union1.scala hosted with ❤ by GitHub

t[A]#t[B]でAとBの和を作ります。
この型を直接引数に取るのではなく、Containsという型を使います。

def f[T](t: T)(implicit ev: UnionTypes.Contains[T, Hoge]): Int = t match {
case i: Int => i
case s: String => s.length
}
f(100) assert_=== 100
f("Scalaz7") assert_=== 7
// f(10.05) Error
val huga: UnionTypes.Union[Huga] = Converter(0.5).union
huga.value.asInstanceOf[Double] assert_=== 0.5
view raw union2.scala hosted with ❤ by GitHub

Converterで値を持てるけど、Anyになってしまうので微妙。

Tagged Typeにも言えますが、Unionはsealed traitとcase classで新しいデータ構造を作るより手軽に使えるところがいいところですね。

Scalaz7は全体的に効率化がされていて、Unboxedなこれらの型もそのためにあるのだと思います。

便利な上に効率もいいのでガンガン使ってしまいましょう。

早くScalaz7が出て欲しいなぁ。


※追記

現在、Tagはspecializedアノテーションが付いているけど、実は機能していないということを教えて頂きました。
Scalazがプリミティブ全部にTagを用意するのか、Scalaのspecializedが良くなるのか、それともそのままなのか、Scalaz7がリリースされるまではわかりません。

Scalaz7のリリースはScala Daysの日になるかも・・・・・?

0 件のコメント:

コメントを投稿